Refactor SVG processing scripts and add new functionality

- Updated `svg-cleanup.js` to improve SVG file processing and validation.
- Refactored `update-data.js` to streamline the data update process and integrate new scripts for generating image variants and syncing data files.
- Introduced `generate-variants.js` to handle the conversion of SVG files to PNG and JPG formats.
- Created `sync-data.js` to synchronize logo data with the filesystem, ensuring accurate representation of available images.
- Enhanced error handling and logging throughout the scripts for better debugging and user feedback.
- Added support for processing all collections or a specific collection based on command-line arguments or environment variables.
This commit is contained in:
sHa
2025-06-19 17:09:45 +03:00
parent 1db0f1cbe9
commit 374ece5142
11 changed files with 424 additions and 386 deletions

View File

@@ -5,7 +5,7 @@
fill="#005bbb" stroke="#ffd500" stroke-width="2.5" />
<path
d="M5.985561 78.82382a104.079383 104.079383 0 0 0 14.053598 56.017033 55 55 0 0 1-13.218774 70.637179A20 20 0 0 0 0 212.5a20 20 0 0 0-6.820384-7.021968 55 55 0 0 1-13.218774-70.637179A104.079383 104.079383 0 0 0-5.98556 78.82382l-1.599642-45.260519A30.103986 30.103986 0 0 1 0 12.5a30.103986 30.103986 0 0 1 7.585202 21.063301zM5 193.624749a45 45 0 0 0 6.395675-53.75496A114.079383 114.079383 0 0 1 0 112.734179a114.079383 114.079383 0 0 1-11.395675 27.13561A45 45 0 0 0-5 193.624749V162.5H5z" />
<path id="a"
<path id="ua-coat-a"
d="M27.779818 75.17546A62.64982 62.64982 0 0 1 60 27.5v145H0l-5-10a22.5 22.5 0 0 1 17.560976-21.95122l14.634147-3.292683a10 10 0 1 0-4.427443-19.503751zm5.998315 34.353887a20 20 0 0 1-4.387889 37.482848l-14.634146 3.292683A12.5 12.5 0 0 0 5 162.5h45V48.265462a52.64982 52.64982 0 0 0-12.283879 28.037802zM42 122.5h10v10H42z" />
<use xlink:href="#a" transform="scale(-1 1)" />
<use xlink:href="#ua-coat-a" transform="scale(-1 1)" />
</svg>

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@@ -1,9 +1,9 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="100%" height="100%" viewBox="0 0 1200 600">
<clipPath id="a">
<clipPath id="ag-a">
<path d="M0 0h60v30H0z" />
</clipPath>
<path fill="#012169" d="M0 0h1200v600H0z" />
<g clip-path="url(#a)" transform="scale(10)">
<g clip-path="url(#ag-a)" transform="scale(10)">
<path stroke="#fff" stroke-width="6" d="m0 0 60 30M0 30 60 0" />
<path stroke="#c8102e" stroke-width="4" d="m0 0 60 30M0 30 60 0" />
<path fill="#fff" d="M0 0h5l30 15L65 0h-5L30 15M-5 30l30-15 30 15h5L30 15 0 30" />

Before

Width:  |  Height:  |  Size: 139 KiB

After

Width:  |  Height:  |  Size: 139 KiB

View File

@@ -56,7 +56,7 @@
<path fill="none" stroke="#540" stroke-width="2" d="M336.135 248.863h266.159m-262.188 96.136h258.111" />
<path fill="#FFF" stroke="#000" stroke-width=".805"
d="m436.14 311.056 32.228-13.13-13.13 32.229 14.324-9.548 14.325 9.548-13.131-32.229 32.229 13.13-9.55-14.323 9.55-14.324-32.229 13.13 13.131-32.228-14.325 9.549-14.324-9.549 13.13 32.228-32.228-13.13 9.549 14.324-9.549 14.323z" />
<g id="a" fill="#FFF" stroke="#000">
<g id="bl-a" fill="#FFF" stroke="#000">
<path fill="#EACE24" stroke="none"
d="M256.42 398.03c-.345 39.061-.69 40.443-.69 40.443 17.109 16.765 19.139 22.906 24.195 28.346 6.567-9.507 16.764-5.705 16.764-5.705 2.075-8.986 12.964-16.764 12.964-16.764-15.209-1.209-41.48-8.989-43.554-12.099-6.888-10.332 2.592-41.651 2.592-41.651l-12.271 7.43z" />
<path fill="none" stroke="#806600"
@@ -128,17 +128,17 @@
<path fill="#000" stroke="none"
d="M304.346 270.347s2.054 5.674 3.519 6.162c0 0 1.666.56 2.766-.172 1.001-.668 0-2.075 0-2.075-1.342-1.955-6.285-3.915-6.285-3.915m-8.745 2.846s-.339 6.024.819 7.049c0 0 1.313 1.17 2.611.926 1.184-.221.815-1.908.815-1.908-.47-2.326-4.245-6.067-4.245-6.067m5.988 21.264s-.338 6.024.82 7.05c0 0 1.313 1.167 2.611.926 1.181-.222.814-1.909.814-1.909-.47-2.326-4.245-6.067-4.245-6.067m14.788 6.038-.13.301h-.329a.697.697 0 0 1-.527-.246c-.636-.721-.359-3.964-.116-5.977-.627-.818-2.075-2.852-1.885-3.942a.943.943 0 0 1 .43-.658l.317-.198.28.248c.368.326 3.603 3.232 3.83 4.825.133.922-1.398 4.555-1.87 5.647zm-32.675 17.667c-1.099 0-2.07 3.32-1.346 4.689 0 0 .816 1.555 2.118 1.785 1.185.209 1.434-1.5 1.434-1.5.377-2.343-.002-4.974-2.206-4.974m-6.604 48.563c-.472.821-2.362 1.968-2.735 2.189l-.294.174-.27-.211c-.673-.529-.293-1.921 1.128-4.138.006-.99.106-3.571.945-4.327a.947.947 0 0 1 .745-.253l.372.039.067.367c.089.485.845 4.767.042 6.16zm-15.52 4.521c-.273.477-.762.633-1.26.633-.436 0-.878-.119-1.191-.249l-.116-.068c-.819-.641-.438-2.657-.216-3.561.001-.916.081-3.635.945-4.413a.948.948 0 0 1 .744-.253l.349.037.083.341c.25 1.016 1.454 6.154.662 7.533zm12.832-23.586c-.285.494-.774.637-1.241.637-.569 0-1.107-.211-1.208-.253l-.118-.068c-.839-.658-.42-2.752-.201-3.622.176-.507 1.055-2.805 2.531-2.649l.384.041.058.382c.062.419.592 4.144-.205 5.532zm20.046-17.399s-2.435 5.519-1.714 6.886c0 0 .817 1.558 2.119 1.786 1.185.209 1.433-1.5 1.433-1.5.38-2.342-1.838-7.172-1.838-7.172m-7.096 14.258c-3.62 1.194-4.38 5.486-4.112 7.005 0 0 .3 1.732 1.467 2.351 1.064.565 1.825-.986 1.825-.986 1.08-2.114 3.386-6.414.82-8.37m-19.551-21.318c-2.441 1.646-2.449 3.084-2.465 4.629 0 0-.022 1.756 1.013 2.58.943.747 4.174-.638 4.174-.638 1.448-1.879-2.6-1.928-2.722-6.571m26.152-23.586c-2.441 1.646-2.448 1.371-2.464 4.626 0 0 .832 2.614 1.869 3.436.94.748 1.974-1.614 1.974-1.614 1.449-1.877.699-5.838-1.379-6.448m17.972 13.049c-1.1 0-2.07 3.32-1.347 4.686 0 0 .818 1.556 2.119 1.786 1.185.21 1.434-1.499 1.434-1.499.376-2.343-.003-4.973-2.206-4.973m-7.578 9.409c-1.571 5.08-3.413 6.621-2.691 7.988 0 0 1.794.455 3.096.684 1.185.211 1.432-1.497 1.432-1.497.381-2.344-1.471-1.676-1.837-7.175m-42.775 59.174c-1.1 0-2.07 3.319-1.347 4.686 0 0 .816 1.555 2.119 1.785 1.185.209 1.432-1.499 1.432-1.499.38-2.341-.001-4.972-2.204-4.972" />
</g>
<use xlink:href="#a" transform="matrix(-1 0 0 1 938.5 0)" />
<g id="b" fill="#EACE24" stroke="#806600">
<use xlink:href="#bl-a" transform="matrix(-1 0 0 1 938.5 0)" />
<g id="bl-b" fill="#EACE24" stroke="#806600">
<path
d="M462.575 214.875c.309-2.981.144-8.604-1.376-11.159-.514-.862-1.772-1.869-2.755-1.826-.966.043-2.298.336-2.753 1.216-.417.808-.689 2.541-.59 3.45.137 1.264 1.572 3.854 1.572 3.854s-5.142-1.064-6.884-2.434c-1.721-1.356-3.581-3.925-4.13-6.088-.189-.74-.924-3.139.005-6.017.539-1.67 2.159-3.905 3.415-5.018 3.276-2.909 9.636-2.064 10.939-1.341 1.719.957 3.816 2.991 4.522 4.87.549 1.459 1.689 5.766 1.967 7.305.568 3.137.734 4.323.983 7.506.171 2.185.645 4.146.196 6.29-.241 1.155-.541 3.804-1.196 5.549-.658 1.754-1.67 2.604-2.541 3.379-1.78 1.585-7.473 2.435-7.473 2.435s3.128-4.073 3.933-5.884c.959-2.153 1.924-3.732 2.166-6.087M476.522 214.875c-.308-2.981-.144-8.604 1.376-11.159.514-.862 1.774-1.869 2.755-1.826.966.043 2.296.336 2.753 1.216.419.808.69 2.541.59 3.45-.139 1.264-1.574 3.854-1.574 3.854s5.144-1.064 6.886-2.434c1.721-1.356 3.579-3.925 4.129-6.088.189-.74.924-3.139-.005-6.017-.539-1.67-2.161-3.905-3.414-5.018-3.277-2.909-9.639-2.064-10.94-1.341-1.721.957-3.818 2.991-4.524 4.87-.549 1.459-1.688 5.766-1.967 7.305-.568 3.137-.733 4.323-.983 7.506-.173 2.185-.646 4.146-.197 6.29.243 1.155.544 3.804 1.197 5.549.656 1.754 1.67 2.604 2.541 3.379 1.779 1.585 7.474 2.435 7.474 2.435s-3.129-4.073-3.934-5.884c-.955-2.153-1.919-3.732-2.163-6.087" />
<path
d="M469.513 237.02s4.594-3.887 5.356-8.286c.683-3.958-2.362-8.591-2.594-10.455-.921-7.454 1.034-17.384 1.21-18.195.701-3.224 1.581-4.604 2.051-5.66.339-.76 1.304-2.271 2.269-3.735.554-.841 1.787-2.406 2.416-3.999.666-1.687.71-3.405.721-4.321.016-1.561-.271-2.89-.673-4.161-.381-1.209-1.626-3.186-3.429-4.323-1.944-1.226-3.515-2.211-4.114-2.601-1.975-1.289-3.191-5.528-3.215-5.528s-1.24 4.238-3.215 5.528c-.598.39-2.098 1.375-4.043 2.601-1.802 1.136-3.048 3.114-3.427 4.323-.403 1.271-.689 2.6-.671 4.161.009.916.054 2.634.721 4.321.628 1.592 1.861 3.156 2.416 3.999.966 1.464 1.93 2.975 2.268 3.735.47 1.056 1.351 2.436 2.051 5.66.176.811 2.132 10.741 1.209 18.195-.231 1.864-3.348 6.497-2.664 10.455.762 4.398 5.357 8.286 5.357 8.286" />
<path d="m479.837 213.11-2.213-3.16h-16.145l-2.218 3.16 2.218 3.144h16.146l2.212-3.144z" />
</g>
<use xlink:href="#b" x="-86.94" />
<use xlink:href="#b" x="86.94" />
<g id="c">
<use xlink:href="#bl-b" x="-86.94" />
<use xlink:href="#bl-b" x="86.94" />
<g id="bl-c">
<path fill="#EACE24" stroke="#806600" stroke-miterlimit="10"
d="M445.151 439.394h48.684v11.395h-48.684v-11.395zm-.002-2.479c-.081-10.701-1.586-21.734-6.15-31.13a6.23 6.23 0 0 1 8.016 5.969c0 .854-.169 1.663-.479 2.401a6.233 6.233 0 1 1 2.634 11.882c-.446 0-.882-.05-1.302-.138.467 4.205 2.625 7.391 5.216 7.391 2 0 3.74-1.897 4.647-4.696.905 2.799 2.648 4.696 4.647 4.696 2.785 0 5.069-3.681 5.291-8.356a6.186 6.186 0 0 1-3.533 1.103 6.231 6.231 0 0 1-.048-12.464 6.23 6.23 0 0 1 5.405-9.331 6.231 6.231 0 0 1 5.405 9.331 6.232 6.232 0 0 1-.047 12.464 6.19 6.19 0 0 1-3.534-1.103c.221 4.675 2.506 8.356 5.293 8.356 2 0 3.741-1.897 4.647-4.696.906 2.799 2.646 4.696 4.646 4.696 2.593 0 4.749-3.186 5.218-7.391a6.232 6.232 0 0 1-7.534-6.092 6.232 6.232 0 0 1 8.864-5.652 6.23 6.23 0 0 1 7.538-8.37c-4.565 9.396-6.069 20.429-6.151 31.13h-48.689z" />
<path fill="#806600"
@@ -182,6 +182,6 @@
<circle fill="#CCC" stroke="#9E7800" stroke-width=".5" cx="481.16" cy="447.518" r="1.668" />
<circle fill="#FFF" cx="480.874" cy="447.026" r=".677" />
</g>
<use xlink:href="#c" x="-49.151" y="-55.104" />
<use xlink:href="#c" x="49.151" y="-55.104" />
<use xlink:href="#bl-c" x="-49.151" y="-55.104" />
<use xlink:href="#bl-c" x="49.151" y="-55.104" />
</svg>

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 38 KiB

View File

@@ -2,14 +2,14 @@
viewBox="0 0 378 189">
<path fill="#ce1720" d="m0 0h378v189H0z" />
<g transform="matrix(.21,0,0,.21,2,0)" clip-path="url(#p)" fill="#fff">
<g id="b">
<path id="a"
<g id="by-b">
<path id="by-a"
d="m36 0v14h-9v14H16v16H8v13H-8V24H8V6H-8V0zm26 77v15h-8v12h-8V92h-8V77h-8V57h8V42h8V30h8v12h8v15h8v20zm-17-1h10V58H45zM19 183h8v-18h-8zm54 0h8v-18h-8zM-8 305H6v13h6v16h9v15h12v-15h9v-16h8v-13H38v-15h21v10h13v17h11v19h-8v14h-7v13h-6v14h-9v12h-7v11h-9v14H24v-15h-9v-14H8v-9H-8v-23H8v-20H-8z" />
<use xlink:href="#a" transform="matrix(-1,0,0,1,200,0)" />
<use xlink:href="#by-a" transform="matrix(-1,0,0,1,200,0)" />
<path
d="m96 0v32h8V0h32v14h-8v14h-12v16h-8v13H92V44h-8V28H72V14h-8V0zm-2 274v-11h-6v-13h-7v-14h-8v-14h-8v-10h-9v-14H44v14h-9v10h-7v14h-8v14h-6v13H8v17H-8v-44H8v-20H-8v-33H8v14h10v14h10v-14h10v-14h8v-18h-8v-14H28v-14H18v14H8v14H-8v-41H8v-19H-8V77H8v13h8v16h11v13h9v15h7v12h14v-12h7v-15h9v-13h11V90h8V77h16v13h8v16h11v13h9v15h7v12h14v-12h7v-15h9v-13h11V90h8V77h16v28h-16v19h16v41h-16v-14h-10v-14h-10v14h-10v14h-8v18h8v14h10v14h10v-14h10v-14h16v33h-16v20h16v44h-16v-17h-6v-13h-6v-14h-8v-14h-7v-10h-9v-14h-12v14h-9v10h-8v14h-8v14h-7v13h-6v11zm2-167v27h8v-27zm-4 58v-14H82v-14H72v14H62v14h-8v18h8v14h10v14h10v-14h10v-14h16v14h10v14h10v-14h10v-14h8v-18h-8v-14h-10v-14h-10v14h-10v14zm4 46v27h8v-27z" />
</g>
<use xlink:href="#b" transform="matrix(1,0,0,-1,0,900)" />
<use xlink:href="#by-b" transform="matrix(1,0,0,-1,0,900)" />
<path
d="m-8 408H8v14h7v8h8v14h7v12h-7v14h-8v8H8v14H-8zm216 0v84h-16v-14h-7v-8h-8v-14h-7v-12h7v-14h8v-8h7v-14zM62 459h8v-18h-8zm76 0v-18h-8v18zm-42-59h8v-18h-8zm0 100v18h8v-18zm-50-75h14v-11h10v-10h5v-10h6v-14h8v-14h4v-13h14v13h4v14h8v14h6v10h5v10h10v11h14v50h-14v11h-10v10h-5v10h-6v14h-8v14h-4v13H93v-13h-4v-14h-8v-14h-6v-10h-5v-10H60v-11H46zm50 9v-15h-8v-10h-8v25h8v9h5v14h-5v9h-8v25h8v-10h8v-15h8v15h8v10h8v-25h-8v-9h-5v-14h5v-9h8v-25h-8v10h-8v15z" />
</g>

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@@ -1,59 +1,59 @@
<svg height="100%" width="100%" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 1000 500">
<clipPath id="a">
<clipPath id="uk-tbat-a">
<path d="m-420-195h840v390h-840z" />
</clipPath>
<linearGradient id="b">
<linearGradient id="uk-tbat-b">
<stop offset="0" stop-color="#003994" />
<stop offset="1" stop-color="#012169" />
</linearGradient>
<linearGradient id="c">
<linearGradient id="uk-tbat-c">
<stop offset="0" stop-color="#caa11c" />
<stop offset="1" stop-color="#ffce18" />
</linearGradient>
<linearGradient id="d" gradientUnits="userSpaceOnUse" x1="250.26718" x2="255.90634" y1="364.716839" y2="359.280959">
<linearGradient id="uk-tbat-d" gradientUnits="userSpaceOnUse" x1="250.26718" x2="255.90634" y1="364.716839" y2="359.280959">
<stop offset="0" stop-color="#de1010" />
<stop offset="1" stop-color="#8e1116" />
</linearGradient>
<linearGradient id="e" gradientUnits="userSpaceOnUse" x1="49.8125" x2="62.696896" y1="476.33093" y2="476.33093">
<linearGradient id="uk-tbat-e" gradientUnits="userSpaceOnUse" x1="49.8125" x2="62.696896" y1="476.33093" y2="476.33093">
<stop offset="0" stop-color="#5a2118" />
<stop offset="1" stop-color="#bb1e1e" />
</linearGradient>
<linearGradient id="f" gradientUnits="userSpaceOnUse" x1="279.92262" x2="354.48179" y1="593.91897" y2="576.41808">
<linearGradient id="uk-tbat-f" gradientUnits="userSpaceOnUse" x1="279.92262" x2="354.48179" y1="593.91897" y2="576.41808">
<stop offset="0" stop-color="#fff231" />
<stop offset="1" stop-color="#fff" />
</linearGradient>
<linearGradient id="g" gradientUnits="userSpaceOnUse" x1="194.33936" x2="208.19142" y1="474.26843" y2="474.26843">
<linearGradient id="uk-tbat-g" gradientUnits="userSpaceOnUse" x1="194.33936" x2="208.19142" y1="474.26843" y2="474.26843">
<stop offset="0" stop-color="#5d241b" />
<stop offset="1" stop-color="#ba1d1d" />
</linearGradient>
<linearGradient id="h" gradientUnits="userSpaceOnUse" x1="363.04586" x2="410.14387" y1="576.80636" y2="580.01867">
<linearGradient id="uk-tbat-h" gradientUnits="userSpaceOnUse" x1="363.04586" x2="410.14387" y1="576.80636" y2="580.01867">
<stop offset="0" stop-color="#fff" />
<stop offset="1" stop-color="#fff231" />
</linearGradient>
<linearGradient id="i" gradientUnits="userSpaceOnUse" x1="283.31082" x2="287.17383" y1="394.666736" y2="400.292656">
<linearGradient id="uk-tbat-i" gradientUnits="userSpaceOnUse" x1="283.31082" x2="287.17383" y1="394.666736" y2="400.292656">
<stop offset="0" />
<stop offset="1" stop-color="#fff" />
</linearGradient>
<linearGradient id="j" gradientUnits="userSpaceOnUse" x1="272.137134" x2="283.456924" y1="400.641582"
<linearGradient id="uk-tbat-j" gradientUnits="userSpaceOnUse" x1="272.137134" x2="283.456924" y1="400.641582"
y2="405.965802">
<stop offset="0" stop-color="#e5aa12" />
<stop offset="1" stop-color="#ffc718" stop-opacity="0" />
</linearGradient>
<linearGradient id="k" gradientUnits="userSpaceOnUse" x1="614.838015" x2="620.313975" xlink:href="#b"
<linearGradient id="uk-tbat-k" gradientUnits="userSpaceOnUse" x1="614.838015" x2="620.313975" xlink:href="#uk-tbat-b"
y1="327.972905" y2="330.254155" />
<linearGradient id="l" gradientUnits="userSpaceOnUse" x1="632.713015" x2="638.313975" xlink:href="#b"
<linearGradient id="uk-tbat-l" gradientUnits="userSpaceOnUse" x1="632.713015" x2="638.313975" xlink:href="#uk-tbat-b"
y1="327.379155" y2="330.316655" />
<linearGradient id="m" gradientUnits="userSpaceOnUse" x1="651.266305" x2="656.292665" xlink:href="#b"
<linearGradient id="uk-tbat-m" gradientUnits="userSpaceOnUse" x1="651.266305" x2="656.292665" xlink:href="#uk-tbat-b"
y1="331.007945" y2="333.055275" />
<linearGradient id="n" gradientUnits="userSpaceOnUse" x1="275.09232" x2="275.09232" y1="176.73798" y2="187.64273">
<linearGradient id="uk-tbat-n" gradientUnits="userSpaceOnUse" x1="275.09232" x2="275.09232" y1="176.73798" y2="187.64273">
<stop offset="0" stop-color="#ba9117" />
<stop offset=".5" stop-color="#7f670c" />
<stop offset="1" stop-color="#ffce18" />
</linearGradient>
<linearGradient id="o" gradientTransform="matrix(1.053586 0 0 1.0555803 -81.136077 -58.917508)"
gradientUnits="userSpaceOnUse" x1="356.09232" x2="356.09232" xlink:href="#c" y1="221.42548" y2="241.84431" />
<linearGradient id="p" gradientTransform="matrix(1 0 0 .8880322 -42.967302 -15.745106)"
gradientUnits="userSpaceOnUse" x1="356.09232" x2="356.09232" xlink:href="#c" y1="221.42548" y2="241.84431" />
<linearGradient id="uk-tbat-o" gradientTransform="matrix(1.053586 0 0 1.0555803 -81.136077 -58.917508)"
gradientUnits="userSpaceOnUse" x1="356.09232" x2="356.09232" xlink:href="#uk-tbat-c" y1="221.42548" y2="241.84431" />
<linearGradient id="uk-tbat-p" gradientTransform="matrix(1 0 0 .8880322 -42.967302 -15.745106)"
gradientUnits="userSpaceOnUse" x1="356.09232" x2="356.09232" xlink:href="#uk-tbat-c" y1="221.42548" y2="241.84431" />
<path d="m0-.000209h1000.0005v500.00021h-1000.0005z" fill="#fff" stroke-width="1pt" />
<path d="m0 0h500v250h-500z" fill="#012169" fill-rule="evenodd" />
<g transform="matrix(8.333338 0 0 8.333343 0 -.000226)">
@@ -70,7 +70,7 @@
<g transform="matrix(1.32408032 0 0 1.32408032 444.043707 -270.869704)">
<path
d="m241.41949 360.67308c3.16562 1.26684 6.56513 1.48122 8.83883 6.7617l11.31371.17678-1.98874-7.99914-9.89949-2.74004z"
fill="url(#d)" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-width=".601" />
fill="url(#uk-tbat-d)" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-width=".601" />
<path
d="m349.13296 489.86757.17678 6.71752h-1.23744l-.17678 1.76777h-5.48007v.88388h-2.12132v1.23743l-1.40442-.17676.01563 4.43502-1.08609-.19238v1.23742h-1.76777v.70711l-5.3033-.35355v1.41422h-2.29809v4.94974l-34.64823-.17678-.17678 2.2981-1.76777-.17678v1.06066h-2.82842v-1.41421l-6.01041-.17678v1.59099h-1.41421l-.35356 1.94456-9.72272.17676-3.18198 3.00521-1.41421-1.59099-3.88909.17677-.35355-1.06065-3.18198-.17678-2.65165 2.65165h-4.59619l-.88389-1.41422-4.06586 3.53554h-1.76777l-1.34792-.44195h-3.94433l-.05524-.60766-7.73398-.14364-.17678-37.16729z"
fill="#fff" />
@@ -205,22 +205,22 @@
<g transform="translate(-120.7385 -82.554714)">
<path
d="m67.3125 476.33093c0 4.19391-3.917508 7.59375-8.75 7.59375s-8.75-3.39984-8.75-7.59375 3.917508-7.59375 8.75-7.59375 8.75 3.39984 8.75 7.59375z"
fill="url(#e)" opacity=".99" transform="matrix(.9214286 0 0 1.0123457 229.85585 96.639995)" />
fill="url(#uk-tbat-e)" opacity=".99" transform="matrix(.9214286 0 0 1.0123457 229.85585 96.639995)" />
<path
d="m283.75451 572.85155c9.63605.1802 5.16169 8.48119-3 5.9375l2.9375 8 8.3125-.9375c2.06876-1.61077 6.70022-16.82066-8.3125-16"
fill="#fff231" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-width=".601" />
<path
d="m283.75451 569.85155c.73472 1.36661.74082 2.21282 0 3-9.74083.22468-9.74647 12.1238.125 13.25 7.93896.90573 38.11955-16.40767 69.62499-17.25.15735 3.53267.38315 8.73973.67678 14.78401-29.7772.35678-39.93595 15.94536-70.125 15.90533-18.92199-21.26688-12.59899-29.55595-.30177-29.68934z"
fill="url(#f)" />
fill="url(#uk-tbat-f)" />
<path
d="m210.375 474.26843c0 4.12488-3.67966 7.46875-8.21875 7.46875s-8.21875-3.34387-8.21875-7.46875 3.67966-7.46875 8.21875-7.46875 8.21875 3.34387 8.21875 7.46875z"
fill="url(#g)" opacity=".99" transform="matrix(1.0304183 0 0 1.0209205 221.04277 91.41119)" />
fill="url(#uk-tbat-g)" opacity=".99" transform="matrix(1.0304183 0 0 1.0209205 221.04277 91.41119)" />
<path
d="m429.692 569.85534c-7.7162-.29441-11.30507 7.35789 1.875 8.625l-1.875 6.18371-11.0625-4.375c-1.92013-8.01795-1.36723-14.13001 11.03315-13.43544"
fill="#fff231" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-width=".601" />
<path
d="m429.6295 569.85155c-.92487-.77882-.78258-2.13956 0-3 22.31216.75478 2.68293 27.19332 1.75 31.28401-16.63225-1.13339-28.86016-15.19746-77.44513-14.62541-.14991-5.43742-.19194-7.58094-.52368-14.65943 41.51107-1.10191 74.84465 13.84939 77.59381 13.87583 5.06963.04876 9.13356-12.68278-1.375-12.875z"
fill="url(#h)" />
fill="url(#uk-tbat-h)" />
<path d="m284.94463 599.49869c16.644.2999 45.64863-15.66978 61.42936-18.03123" fill="none" />
<path
d="m287.48296 596.92963-.08186-8.57333 3.08085-.1621c.61932-.03258 1.09088.01965 1.41466.15668.32376.13705.58389.39544.78037.77516.19646.37975.29695.80548.30146 1.27723.0058.60821-.14887 1.12928-.46403 1.56324-.31516.43395-.80557.72501-1.47121.87315.24468.13146.43089.26403.55863.39772.27148.28998.52948.65672.77399 1.10023l1.23092 2.26981-1.15651.06085-.93654-1.73529c-.27351-.5005-.49845-.88264-.67485-1.14641-.1764-.26375-.33384-.44661-.47233-.54855-.1385-.10192-.27905-.17059-.42165-.206-.10454-.0218-.2753-.02647-.51229-.014l-1.06645.05611.03636 3.80712zm.87378-4.83798 1.97649-.104c.42025-.0221.74836-.093.98433-.21269.23596-.11968.41443-.30071.53542-.54307.12098-.24235.18015-.50193.17751-.77875-.00388-.40546-.12635-.73253-.3674-.9812-.24107-.24865-.61913-.35944-1.13418-.33234l-2.19925.11571zm6.13941 4.19135-1.07254-8.43341 4.96429-1.14622.12657.99521-4.05573.93643.32849 2.58296 3.79815-.87696.12584.98945-3.79815.87697.36507 2.87059 4.21496-.97321.12657.99522zm5.57905-4.15088.82966-.35788c.11635.40304.2722.71464.46753.93483s.46223.36381.80071.43086c.33846.06705.70039.03974 1.08577-.08193.34221-.10803.63291-.26576.87209-.4732.23916-.20744.40279-.44.49086-.69768s.10853-.51501.06138-.77198c-.04785-.26075-.15129-.46896-.31032-.62464-.15904-.15569-.39251-.25488-.70042-.29761-.19785-.02949-.62498-.03756-1.28138-.02424-.65641.01333-1.12439-.02183-1.40393-.10549-.36186-.10564-.65043-.28739-.86573-.54525-.21529-.25786-.35795-.57763-.428-.95931-.07697-.41945-.0518-.84218.07551-1.26817.12732-.42598.36016-.79234.69854-1.09906.33837-.3067.7357-.53209 1.19199-.67615.50253-.15864.96392-.19935 1.38417-.12215.42024.07723.76901.27596 1.04631.59619.27729.32025.46837.72168.57325 1.20429l-.8456.35091c-.14264-.51066-.37192-.85806-.68784-1.04218-.31592-.18411-.73439-.19392-1.25542-.02944-.54262.17131-.91565.41801-1.11911.74009-.20345.3221-.27363.6551-.21053.99898.05479.29853.18773.51643.39883.65367.20801.13823.69514.19333 1.46138.16531.76623-.02801 1.29888-.00926 1.59792.05624.43554.09837.77872.28888 1.02955.57149.25082.28264.41715.6469.49898 1.09282.08113.44213.0543.89137-.08048 1.3477-.1348.45633-.37572.85422-.72276 1.19366-.34705.33944-.7626.58556-1.24663.73838-.61353.19368-1.14773.2464-1.60262.15812-.45489-.08826-.84065-.31529-1.15729-.68109-.31664-.36578-.5321-.82448-.64637-1.37609zm7.12952.51568-1.75082-8.23368 4.8624-1.74767.20661.97165-3.97249 1.42781.53623 2.52178 3.7202-1.33714.20542.96602-3.7202 1.33714.59595 2.80259 4.12846-1.48387.20661.97164zm5.51536-2.00237.74494-9.17004.95573-.35832 4.57328 7.17605-1.0106.3789-1.33607-2.19175-2.80316 1.051-.18211 2.76096zm1.18302-4.09446 2.27271-.8521-1.20634-2.00994c-.36732-.61025-.65231-1.11794-.85497-1.52309.03195.5581.02801 1.12561-.01181 1.70252zm5.82137 1.45012-1.7658-8.22828 2.97992-1.07981c.59904-.21706 1.0703-.30818 1.41377-.27335.34346.03484.64855.20557.91529.51219.26674.30663.44869.68632.54586 1.13907.12526.58374.07651 1.13172-.14625 1.64393-.22278.51225-.64496.93946-1.26656 1.28166.26505.05317.47315.12495.62432.21536.32242.19772.64675.47339.97299.82702l1.64964 1.81586-1.11862.40534-1.25677-1.3896c-.36578-.39978-.66083-.70018-.88514-.90119s-.41418-.32981-.56961-.38642c-.15544-.05659-.30634-.08054-.4527-.07187-.10649.01036-.27434.05707-.50356.14012l-1.03152.37379.78414 3.65389zm-.09709-4.91912 1.91174-.69274c.40648-.1473.7133-.31393.92044-.49989.20715-.18597.34602-.41374.41665-.68332.0706-.26955.0774-.53718.0204-.80286-.08352-.38914-.26755-.66726-.5521-.83435-.28456-.16707-.67593-.16036-1.17411.02016l-2.12721.77082zm11.19322-1.94619.94793.00297c-.02796.96254-.24453 1.75633-.64974 2.3814s-.96139 1.04593-1.66853 1.26257c-.73184.2242-1.35943.22388-1.88276-.00098-.52333-.22485-.96607-.64703-1.32821-1.26653-.36215-.6195-.6137-1.32676-.75464-2.1218-.15371-.86696-.15268-1.66458.00308-2.39286.15576-.72825.45329-1.3363.8926-1.82414.43931-.48782.95849-.8235 1.55755-1.00703.67935-.20812 1.28821-.17112 1.82657.11099.53837.28212.96678.77953 1.28522 1.49224l-.83939.52658c-.26488-.55748-.57159-.92853-.92011-1.11315-.34854-.18459-.74976-.20737-1.20369-.06831-.52187.15989-.93085.44683-1.22697.86086-.29612.41404-.4694.90119-.51982 1.46147-.05043.5603-.02699 1.11492.07034 1.66387.12551.70796.31923 1.30023.58115 1.7768.26193.47657.5936.79107.99503.94351.40142.15243.80903.16527 1.22281.0385.50334-.1542.89794-.46269 1.18378-.92546.28585-.46278.42845-1.06327.4278-1.8015zm2.56496 2.29994-.69572-8.50746.91496-.14847.28569 3.49351 3.5938-.58319-.28569-3.4935.91496-.14847.69572 8.50745-.91496.14847-.32793-4.00999-3.5938.58318.32793 4.00999z"
@@ -243,7 +243,7 @@
fill="#fec717" stroke="#000" stroke-linecap="round" stroke-width=".601" />
<path
d="m277.01757 395.54173c9.02511-1.133 15.19244-9.52683 20.3125-21.4375l-7.1875 43.1875c-4.03694 2.21306-7.86988 4.63012-11.75 7z"
fill="url(#i)" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-width=".601" />
fill="url(#uk-tbat-i)" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-width=".601" />
<g transform="translate(-118.85743 25.929526)">
<path
d="m351.26696 461.07762c-6.22172-.36709-49.06251-17.88246-48.66051-60.48348v-60.4835h48.66051 48.66054v60.4835c.402 42.60102-42.43878 60.11639-48.66054 60.48348z"
@@ -472,7 +472,7 @@
</g>
<path
d="m272.6267 398.04795c1.45811-.33359 7.51612-2.08466 7.98411-1.11577l-6.08673 18.62977c-3.03875-1.3942-7.39001-1.11339-9.11626-2.42009 2.49033-3.36802 1.03062-15.19271 7.21888-15.09391z"
fill="url(#j)" />
fill="url(#uk-tbat-j)" />
<g stroke="#000" stroke-linecap="round" stroke-width=".601">
<path
d="m278.30359 424.90132c-4.39324 1.00381-1.26285 6.2167 3.125 5.125-1.02616 7.69232 2.59476 3.52196 7.875 6"
@@ -821,11 +821,11 @@
fill="#fff" />
<g stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-width=".601">
<path d="m624.6385 332.19166-4.25-6.75c-2.97679-.11786-6.48375-.20126-9.34375.84374l5.53125 7.71876"
fill="url(#k)" />
<path d="m641.32599 333.16041-2.99999-8.40625-9.46875.0625 4.0625 7.46875" fill="url(#l)" />
fill="url(#uk-tbat-k)" />
<path d="m641.32599 333.16041-2.99999-8.40625-9.46875.0625 4.0625 7.46875" fill="url(#uk-tbat-l)" />
<path
d="m647.3885 325.37916c6.67037.80952 10.74276 4.71802 10.6715 7.12359-.05923 1.99903-3.49656 3.61052-10.23401 1.86189z"
fill="url(#m)" />
fill="url(#uk-tbat-m)" />
<path
d="m613.95099 325.75415c-11.15144.50842-11.59946 16.75292 1.75 8.6875 6.69899-4.05395 23.732-1.99752 32.125-.0625 13.14336 3.03022 12.82173-4.49534 3.8125-7.9375-8.00244-3.05748-28.57232-1.10308-37.6875-.6875z"
fill="none" />
@@ -884,7 +884,7 @@
<path
d="m413.43602 234.08231c.04646.93622.12635 1.96606.14331 2.98557-2.01639-2.03322-3.43422-.67522-5.92523-1.02089-.04682-.61599.02979-2.52221-.00024-2.9829 5.77416.06208 3.91739-.85772 5.78216 1.01822z"
fill="#012169" stroke-linecap="round" stroke-linejoin="round" stroke-width=".1" />
<g clip-path="url(#a)" transform="matrix(.0767085 -.0008391 .0008391 .0767085 408.79613 233.61637)">
<g clip-path="url(#uk-tbat-a)" transform="matrix(.0767085 -.0008391 .0008391 .0767085 408.79613 233.61637)">
<circle fill="#012169" r="20" />
<path d="m-20-10 40 20m-40 0 40-20" stroke="#fff" stroke-width="3" />
<path d="m-20-10 40 20m-40 0 40-20" stroke="#c8102e" stroke-width="2" />
@@ -894,15 +894,15 @@
<path d="m-20 0h40m-20-10v20" stroke="#c8102e" stroke-width="3" />
</g>
</g>
<path d="m274.63077 176.967c.24427-.20774.64321-.23586.92307 0v33.04615h-.92307z" fill="url(#n)" />
<path d="m274.63077 176.967c.24427-.20774.64321-.23586.92307 0v33.04615h-.92307z" fill="url(#uk-tbat-n)" />
<g fill="none" stroke="#878383" stroke-linecap="round" stroke-linejoin="round" stroke-width=".4">
<path
d="m319.39921 209.55379c-8.90853-10.47087-17.16471-21.23167-25.0139-32.17335 6.04517 11.09408 12.05823 22.19276 19.7106 33.05724" />
<path d="m294.20853 177.29205c4.817 11.01819 8.82981 22.18716 15.37958 32.88046" />
<path d="m323.73024 185.60055c.7272 4.93736 1.13378 9.95487 2.74004 14.67247" />
</g>
<path d="m293.5515 175.05663c.25736-.2193.67767-.24898.97253 0v34.88286h-.97253z" fill="url(#o)" />
<path d="m312.66346 181.09123c.24427-.18449.64321-.20945.92307 0v29.34604h-.92307z" fill="url(#p)" />
<path d="m293.5515 175.05663c.25736-.2193.67767-.24898.97253 0v34.88286h-.97253z" fill="url(#uk-tbat-o)" />
<path d="m312.66346 181.09123c.24427-.18449.64321-.20945.92307 0v29.34604h-.92307z" fill="url(#uk-tbat-p)" />
<g stroke-linecap="round" transform="translate(-81 -44.75)">
<path d="m344.61612 253.65558h63.01392v5.90555l-56.92161-.06154z" stroke="#000" stroke-linejoin="round"
stroke-width=".101336" />

Before

Width:  |  Height:  |  Size: 98 KiB

After

Width:  |  Height:  |  Size: 98 KiB

View File

@@ -1 +1,10 @@
<svg height="100%" width="100%" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 1200 800"><path d="m0 0h1200v800h-1200z" fill="#ffd700"/><g stroke="#bf0a30" transform="translate(600 400)"><path id="a" d="m157.344 38.2812h-314.688m348.719-25.5312h-382.75m382.75-25.5h-382.75m348.719-25.5312h-314.688" stroke-linecap="round" stroke-width="17"/><use transform="rotate(90)" xlink:href="#a"/><circle fill="#ffd700" r="64.3125" stroke-width="10.625"/></g></svg>
<svg height="100%" width="100%" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
viewBox="0 0 1200 800">
<path d="m0 0h1200v800h-1200z" fill="#ffd700" />
<g stroke="#bf0a30" transform="translate(600 400)">
<path id="us-ri-a" d="m157.344 38.2812h-314.688m348.719-25.5312h-382.75m382.75-25.5h-382.75m348.719-25.5312h-314.688"
stroke-linecap="round" stroke-width="17" />
<use transform="rotate(90)" xlink:href="#us-ri-a" />
<circle fill="#ffd700" r="64.3125" stroke-width="10.625" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 498 B

After

Width:  |  Height:  |  Size: 573 B

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 7.8 KiB

After

Width:  |  Height:  |  Size: 8.2 KiB

View File

@@ -0,0 +1,131 @@
#!/usr/bin/env node
const fs = require('fs');
const path = require('path');
const { Resvg } = require('@resvg/resvg-js');
// Use collections from src/collections.js
const { collections } = require('../src/collections.js');
// Accept collection as a CLI arg or env var
const collectionArg = process.argv.find(arg => arg.startsWith('--collection='));
const collectionName = collectionArg ? collectionArg.split('=')[1] : (process.env.COLLECTION || 'logos');
// Get file name without extension
function getBaseName(filename) {
return path.basename(filename, path.extname(filename));
}
// Clean directory (remove all contents)
function cleanDir(dir) {
if (fs.existsSync(dir)) {
for (const file of fs.readdirSync(dir)) {
if (file !== '.gitignore') {
const filePath = path.join(dir, file);
if (fs.lstatSync(filePath).isDirectory()) {
fs.rmSync(filePath, { recursive: true, force: true });
} else {
fs.unlinkSync(filePath);
}
}
}
} else {
fs.mkdirSync(dir, { recursive: true });
}
}
// Convert SVG to PNG with transparency
function svgToPng(svgBuffer, width, height) {
// No background specified to maintain transparency
const resvg = new Resvg(svgBuffer, {
fitTo: { mode: 'width', value: width || 256 }
});
const pngData = resvg.render().asPng();
return pngData;
}
// Convert SVG to JPG
function svgToJpg(svgBuffer, width, height) {
// For JPGs we need a white background since JPG doesn't support transparency
const resvg = new Resvg(svgBuffer, {
background: 'white',
fitTo: { mode: 'width', value: width || 256 }
});
const pngData = resvg.render().asPng();
return pngData;
}
// Generate PNG and JPG variants for SVG files
function generateVariants(collectionName) {
const collection = collections.find(c => c.name === collectionName);
if (!collection) {
console.error(`Collection "${collectionName}" not found`);
return;
}
const imagesDir = path.join(__dirname, '..', 'public', collection.baseDir);
const varDir = path.join(__dirname, '..', 'public', collection.varDir);
if (!fs.existsSync(imagesDir)) {
console.error(`Directory does not exist: ${imagesDir}`);
return;
}
console.log(`Generating variants for collection: ${collection.label}`);
console.log(`Source: ${imagesDir}`);
console.log(`Target: ${varDir}`);
// Clean variants directory
cleanDir(varDir);
const files = fs.readdirSync(imagesDir);
const svgFiles = files.filter(file => /\.svg$/i.test(file));
console.log(`Found ${svgFiles.length} SVG files to process`);
let processed = 0;
let errors = 0;
for (const file of svgFiles) {
const base = getBaseName(file);
const svgPath = path.join(imagesDir, file);
const pngPath = path.join(varDir, base + '.png');
const jpgPath = path.join(varDir, base + '.jpg');
try {
const svgBuffer = fs.readFileSync(svgPath);
// Generate PNG
const pngBuffer = svgToPng(svgBuffer, 256, 256);
fs.writeFileSync(pngPath, pngBuffer);
// Generate JPG
const jpgBuffer = svgToJpg(svgBuffer);
fs.writeFileSync(jpgPath, jpgBuffer);
processed++;
console.log(`✓ Generated variants for ${file}`);
} catch (e) {
errors++;
console.error(`✗ Error generating variants for ${file}:`, e.message);
}
}
console.log(`\nCompleted: ${processed} processed, ${errors} errors`);
}
// Main function
function main() {
if (collectionName === 'all') {
// Process all collections
for (const col of collections) {
generateVariants(col.name);
}
} else {
// Process single collection
generateVariants(collectionName);
}
}
// Run the script
main();

View File

@@ -106,24 +106,24 @@ function processSvgFiles(collectionName) {
}
const imagesDir = path.join(__dirname, '..', 'public', collection.baseDir);
if (!fs.existsSync(imagesDir)) {
console.error(`Directory does not exist: ${imagesDir}`);
return;
}
console.log(`Processing SVG files in collection: ${collection.label}`);
const files = fs.readdirSync(imagesDir);
const svgFiles = files.filter(file => /\.svg$/i.test(file));
console.log(`Found ${svgFiles.length} SVG files`);
for (const file of svgFiles) {
const svgPath = path.join(imagesDir, file);
validateAndFixSvg(svgPath);
}
console.log(`Completed processing SVG files for ${collection.label}`);
}

142
scripts/sync-data.js Normal file
View File

@@ -0,0 +1,142 @@
#!/usr/bin/env node
const fs = require('fs');
const path = require('path');
// Use collections from src/collections.js
const { collections } = require('../src/collections.js');
// Accept collection as a CLI arg or env var
const collectionArg = process.argv.find(arg => arg.startsWith('--collection='));
const collectionName = collectionArg ? collectionArg.split('=')[1] : (process.env.COLLECTION || 'logos');
// Get file extension without the dot
function getFileExtension(filename) {
return path.extname(filename).slice(1).toUpperCase();
}
// Get file name without extension
function getBaseName(filename) {
return path.basename(filename, path.extname(filename));
}
// Convert filename to readable name (replace hyphens with spaces, capitalize words)
function formatName(filename) {
return getBaseName(filename)
.split(/[-_]/)
.map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
.join(' ');
}
// Sync data file with filesystem
function syncDataFile(collectionName) {
const collection = collections.find(c => c.name === collectionName);
if (!collection) {
console.error(`Collection "${collectionName}" not found`);
return;
}
const imagesDir = path.join(__dirname, '..', 'public', collection.baseDir);
const outputFile = path.join(__dirname, '..', 'public', collection.dataFile);
if (!fs.existsSync(imagesDir)) {
console.error(`Directory does not exist: ${imagesDir}`);
return;
}
console.log(`Syncing data file for collection: ${collection.label}`);
console.log(`Source: ${imagesDir}`);
console.log(`Data file: ${outputFile}`);
// Load existing data
let existing = [];
if (fs.existsSync(outputFile)) {
try {
existing = JSON.parse(fs.readFileSync(outputFile, 'utf8'));
} catch (e) {
console.error('Could not parse existing data file:', e);
}
}
// Get current files
const files = fs.readdirSync(imagesDir);
const logoFiles = files.filter(file =>
/\.(svg|png|jpg|jpeg)$/i.test(file)
);
const logoFilesSet = new Set(logoFiles);
// Update existing entries
let updated = 0;
let disabled = 0;
let enabled = 0;
for (const logo of existing) {
// Fix: If logo.path contains a slash, strip to filename only
if (logo.path.includes('/')) {
logo.path = logo.path.split('/').pop();
updated++;
}
// Check if file exists
if (!logoFilesSet.has(logo.path)) {
if (!logo.disable) {
logo.disable = true;
disabled++;
}
} else if (logo.disable) {
logo.disable = false;
enabled++;
}
}
// Add new entries
const existingPathsSet = new Set(existing.map(logo => logo.path));
const newLogos = logoFiles
.filter(file => !existingPathsSet.has(file))
.map(file => {
const format = getFileExtension(file);
return {
name: formatName(file),
path: file,
format: format,
disable: false
};
})
.sort((a, b) => a.name.localeCompare(b.name));
// Merge existing and new logos
const merged = [...existing, ...newLogos];
// Save updated data
try {
const data = JSON.stringify(merged, null, 2);
fs.writeFileSync(outputFile, data);
console.log(`\nSync completed:`);
console.log(`- Total entries: ${merged.length}`);
console.log(`- New entries: ${newLogos.length}`);
console.log(`- Updated paths: ${updated}`);
console.log(`- Disabled: ${disabled}`);
console.log(`- Re-enabled: ${enabled}`);
} catch (error) {
console.error('Error writing data file:', error);
}
}
// Main function
function main() {
if (collectionName === 'all') {
// Process all collections
for (const col of collections) {
syncDataFile(col.name);
}
} else {
// Process single collection
syncDataFile(collectionName);
}
}
// Run the script
main();

View File

@@ -1,352 +1,64 @@
#!/usr/bin/env node
const fs = require('fs');
const { execSync } = require('child_process');
const path = require('path');
const { Resvg } = require('@resvg/resvg-js');
// Use collections from src/collections.js
const { collections } = require('../src/collections.js');
// Accept collection as a CLI arg or env var
const collectionArg = process.argv.find(arg => arg.startsWith('--collection='));
const collectionName = collectionArg ? collectionArg.split('=')[1] : (process.env.COLLECTION || 'logos');
const collection = collections.find(c => c.name === collectionName) || collections[0];
const imagesDir = path.join(__dirname, '..', 'public', collection.baseDir);
const outputFile = path.join(__dirname, '..', 'public', collection.dataFile);
const imagesVarDir = path.join(__dirname, '..', 'public', collection.varDir);
// Remove old PNG/JPG folders if they exist
const pngDir = path.join(__dirname, '..', 'public', collection.baseDir + '-png');
const jpgDir = path.join(__dirname, '..', 'public', collection.baseDir + '-jpg');
if (fs.existsSync(pngDir)) fs.rmSync(pngDir, { recursive: true, force: true });
if (fs.existsSync(jpgDir)) fs.rmSync(jpgDir, { recursive: true, force: true });
// Get file extension without the dot
function getFileExtension(filename) {
return path.extname(filename).slice(1).toUpperCase();
}
// Get file name without extension
function getBaseName(filename) {
return path.basename(filename, path.extname(filename));
}
// Convert filename to readable name (replace hyphens with spaces, capitalize words)
function formatName(filename) {
return getBaseName(filename)
.split(/[-_]/)
.map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
.join(' ');
}
// Clean directory (remove all contents)
function cleanDir(dir) {
if (fs.existsSync(dir)) {
for (const file of fs.readdirSync(dir)) {
if (file !== '.gitignore') {
const filePath = path.join(dir, file);
if (fs.lstatSync(filePath).isDirectory()) {
fs.rmSync(filePath, { recursive: true, force: true });
} else {
fs.unlinkSync(filePath);
}
}
}
} else {
fs.mkdirSync(dir, { recursive: true });
}
}
// Convert SVG to PNG with transparency
function svgToPng(svgBuffer, width, height) {
// No background specified to maintain transparency
const resvg = new Resvg(svgBuffer, {
fitTo: { mode: 'width', value: width || 256 }
});
const pngData = resvg.render().asPng();
return pngData;
}
// Convert SVG to JPG
function svgToJpg(svgBuffer, width, height) {
// For JPGs we need a white background since JPG doesn't support transparency
const resvg = new Resvg(svgBuffer, {
background: 'white',
fitTo: { mode: 'width', value: width || 256 }
});
const pngData = resvg.render().asPng();
return pngData;
}
// Pregenerate PNG and JPG images for SVG files
function pregenerateImages(logoFiles, imagesDir, imagesVarDir) {
cleanDir(imagesVarDir);
// Only process SVG files
const svgFiles = logoFiles.filter(file => /\.svg$/i.test(file));
for (const file of svgFiles) {
const base = getBaseName(file);
const svgPath = path.join(imagesDir, file);
// Validate and fix SVG before processing
validateAndFixSvg(svgPath);
const pngPath = path.join(imagesVarDir, base + '.png');
const jpgPath = path.join(imagesVarDir, base + '.jpg');
try {
const svgBuffer = fs.readFileSync(svgPath);
const pngBuffer = svgToPng(svgBuffer, 256, 256);
fs.writeFileSync(pngPath, pngBuffer);
const jpgBuffer = svgToJpg(svgBuffer);
fs.writeFileSync(jpgPath, jpgBuffer);
} catch (e) {
console.error('Error generating PNG/JPG for', file, e);
}
}
}
// Scan directory and update logo objects
function scanLogos() {
console.log(`Scanning logos directory: ${imagesDir}`);
let existing = [];
if (fs.existsSync(outputFile)) {
try {
existing = JSON.parse(fs.readFileSync(outputFile, 'utf8'));
} catch (e) {
console.error('Could not parse existing logos.json:', e);
}
}
const collectionName = collectionArg ? collectionArg.split('=')[1] : (process.env.COLLECTION || 'all');
// Execute a script with proper error handling
function runScript(scriptName, collection) {
try {
if (!fs.existsSync(imagesDir)) {
console.error(`Directory does not exist: ${imagesDir}`);
return [];
}
const files = fs.readdirSync(imagesDir);
// Filter for image files (svg, png, jpg, jpeg)
const logoFiles = files.filter(file =>
/\.(svg|png|jpg|jpeg)$/i.test(file)
);
// Create a Set of all logo filenames in the directory
const logoFilesSet = new Set(logoFiles);
// Mark existing records as disabled if they are not found in the directory
for (const logo of existing) {
// Fix: If logo.path contains a slash, strip to filename only
if (logo.path.includes('/')) {
logo.path = logo.path.split('/').pop();
}
if (!logoFilesSet.has(logo.path)) {
logo.disable = true;
} else if (logo.disable) {
logo.disable = false;
}
}
// Create a Set of existing filenames to avoid duplication
const existingPathsSet = new Set(existing.map(logo => logo.path));
// Create new minimal logo objects for files that don't have records yet
const newLogos = logoFiles
.filter(file => !existingPathsSet.has(file))
.map(file => {
const format = getFileExtension(file);
// Only add minimal fields for new files
return {
name: formatName(file),
path: file,
format: format,
disable: false
};
})
.sort((a, b) => a.name.localeCompare(b.name));
// Merge existing and new logos (add new at the end)
let merged = [...existing, ...newLogos];
return merged;
const scriptPath = path.join(__dirname, scriptName);
const command = `node "${scriptPath}" --collection=${collection}`;
console.log(`\n=== Running ${scriptName} for ${collection} ===`);
execSync(command, { stdio: 'inherit' });
console.log(`=== Completed ${scriptName} ===`);
} catch (error) {
console.error('Error scanning logos directory:', error);
return [];
console.error(`Error running ${scriptName}:`, error.message);
process.exit(1);
}
}
// Save logos data to JSON file
function saveLogosToJson(logos) {
try {
const data = JSON.stringify(logos, null, 2);
fs.writeFileSync(outputFile, data);
console.log(`Successfully wrote ${logos.length} logos to ${outputFile}`);
} catch (error) {
console.error('Error writing logos data to file:', error);
}
}
// SVG validation and fixing function
function validateAndFixSvg(svgPath) {
try {
let svgContent = fs.readFileSync(svgPath, 'utf8');
let modified = false;
// Clean up SVG content
const originalContent = svgContent;
// Remove XML declaration
svgContent = svgContent.replace(/<\?xml[^>]*\?>\s*/gi, '');
// Remove DOCTYPE declaration
svgContent = svgContent.replace(/<!DOCTYPE[^>]*>\s*/gi, '');
// Remove comments
svgContent = svgContent.replace(/<!--[\s\S]*?-->/g, '');
// Remove leading/trailing whitespace and ensure it starts with <svg
svgContent = svgContent.trim();
if (originalContent !== svgContent) {
modified = true;
console.log(`${path.basename(svgPath)}: Cleaned up SVG (removed XML/DOCTYPE/comments)`);
}
// Parse SVG tag attributes
const svgTagMatch = svgContent.match(/<svg[^>]*>/i);
if (!svgTagMatch) {
console.warn(`No SVG tag found in ${path.basename(svgPath)}`);
return;
}
const svgTag = svgTagMatch[0];
const viewBoxMatch = svgTag.match(/viewBox\s*=\s*["']([^"']+)["']/i);
const widthMatch = svgTag.match(/width\s*=\s*["']([^"']+)["']/i);
const heightMatch = svgTag.match(/height\s*=\s*["']([^"']+)["']/i);
const hasViewBox = !!viewBoxMatch;
const hasWidth = !!widthMatch;
const hasHeight = !!heightMatch;
const width = hasWidth ? widthMatch[1] : null;
const height = hasHeight ? heightMatch[1] : null;
if (!hasViewBox && !hasWidth && !hasHeight) {
console.warn(`${path.basename(svgPath)}: No viewBox, width, or height found - cannot determine dimensions`);
return;
}
let newSvgTag = svgTag;
if (!hasViewBox && hasWidth && hasHeight) {
// Add viewBox using width and height
const widthValue = parseFloat(width);
const heightValue = parseFloat(height);
if (!isNaN(widthValue) && !isNaN(heightValue)) {
const viewBoxValue = `0 0 ${widthValue} ${heightValue}`;
newSvgTag = newSvgTag.replace(/(<svg[^>]*?)>/i, `$1 viewBox="${viewBoxValue}">`);
modified = true;
console.log(`${path.basename(svgPath)}: Added viewBox="${viewBoxValue}"`);
}
}
// Update width and height to 100% if they exist
if (hasWidth && width !== '100%') {
newSvgTag = newSvgTag.replace(/width\s*=\s*["'][^"']+["']/i, 'width="100%"');
modified = true;
console.log(`${path.basename(svgPath)}: Updated width to 100%`);
}
if (hasHeight && height !== '100%') {
newSvgTag = newSvgTag.replace(/height\s*=\s*["'][^"']+["']/i, 'height="100%"');
modified = true;
console.log(`${path.basename(svgPath)}: Updated height to 100%`);
}
if (modified) {
svgContent = svgContent.replace(svgTag, newSvgTag);
fs.writeFileSync(svgPath, svgContent, 'utf8');
console.log(`${path.basename(svgPath)}: SVG file updated`);
}
} catch (error) {
console.error(`Error processing SVG ${path.basename(svgPath)}:`, error.message);
}
}
// Main function
// Main batch processing function
function main() {
// If no collection is specified, process all collections
if (!collectionArg && !process.env.COLLECTION) {
for (const col of collections) {
const imagesDir = path.join(__dirname, '..', 'public', col.baseDir);
const outputFile = path.join(__dirname, '..', 'public', col.dataFile);
const varDir = path.join(__dirname, '..', 'public', col.varDir);
if (!fs.existsSync(imagesDir)) {
fs.mkdirSync(imagesDir, { recursive: true });
}
const files = fs.readdirSync(imagesDir);
// Only update/disable/add, do not overwrite existing keys
let existing = [];
if (fs.existsSync(outputFile)) {
try {
existing = JSON.parse(fs.readFileSync(outputFile, 'utf8'));
} catch (e) {
console.error('Could not parse existing', col.dataFile + ':', e);
}
}
// Filter for image files (svg, png, jpg, jpeg)
const logoFiles = files.filter(file =>
/\.(svg|png|jpg|jpeg)$/i.test(file)
);
const logoFilesSet = new Set(logoFiles);
// Validate and fix SVG files
const svgFiles = logoFiles.filter(file => /\.svg$/i.test(file));
for (const file of svgFiles) {
const svgPath = path.join(imagesDir, file);
validateAndFixSvg(svgPath);
}
for (const logo of existing) {
// Fix: If logo.path contains a slash, strip to filename only
if (logo.path.includes('/')) {
logo.path = logo.path.split('/').pop();
}
if (!logoFilesSet.has(logo.path)) {
logo.disable = true;
} else if (logo.disable) {
logo.disable = false;
}
}
const existingPathsSet = new Set(existing.map(logo => logo.path));
const newLogos = logoFiles
.filter(file => !existingPathsSet.has(file))
.map(file => {
const format = getFileExtension(file);
return {
name: formatName(file),
path: file,
format: format,
disable: false
};
})
.sort((a, b) => a.name.localeCompare(b.name));
let merged = [...existing, ...newLogos];
pregenerateImages(files, imagesDir, varDir);
try {
const data = JSON.stringify(merged, null, 2);
fs.writeFileSync(outputFile, data);
console.log(`Successfully wrote ${merged.length} items to ${outputFile}`);
} catch (error) {
console.error('Error writing data to file:', outputFile, error);
}
}
console.log('🚀 Starting data update process...');
if (collectionName === 'all') {
console.log('Processing all collections');
} else {
// Single collection mode (as before)
const logos = scanLogos();
const files = fs.readdirSync(imagesDir);
pregenerateImages(files, imagesDir, varDir);
saveLogosToJson(logos);
const collection = collections.find(c => c.name === collectionName);
if (!collection) {
console.error(`Collection "${collectionName}" not found`);
process.exit(1);
}
console.log(`Processing collection: ${collection.label}`);
}
// Step 1: Clean and validate SVG files
console.log('\n📋 Step 1: SVG Cleanup and Validation');
runScript('svg-cleanup.js', collectionName);
// Step 2: Generate PNG/JPG variants
console.log('\n🖼 Step 2: Generate Image Variants');
runScript('generate-variants.js', collectionName);
// Step 3: Sync data files with filesystem
console.log('\n📄 Step 3: Sync Data Files');
runScript('sync-data.js', collectionName);
// Step 4: Generate PWA cache list
console.log('\n💾 Step 4: Generate PWA Cache List');
runScript('generate-pwa-cache-list.js', 'all');
console.log('\n✅ All tasks completed successfully!');
}
// Run the script
// Run the batch process
main();