svger-cli 3.1.0 → 4.0.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.
- package/CHANGELOG.md +399 -0
- package/README.md +448 -37
- package/SECURITY.md +3 -3
- package/assets/svges/500px.svg +3 -0
- package/assets/svges/adobe.svg +3 -0
- package/assets/svges/adonis.svg +3 -0
- package/assets/svges/aeroplane-1.svg +3 -0
- package/assets/svges/agenda.svg +3 -0
- package/assets/svges/airbnb.svg +3 -0
- package/assets/svges/airtable.svg +3 -0
- package/assets/svges/alarm-1.svg +7 -0
- package/assets/svges/align-text-center.svg +6 -0
- package/assets/svges/align-text-left.svg +6 -0
- package/assets/svges/align-text-right.svg +6 -0
- package/assets/svges/alpinejs.svg +4 -0
- package/assets/svges/amazon-original.svg +5 -0
- package/assets/svges/amazon-pay.svg +7 -0
- package/assets/svges/amazon.svg +10 -0
- package/assets/svges/ambulance-1.svg +4 -0
- package/assets/svges/amd.svg +3 -0
- package/assets/svges/amex.svg +4 -0
- package/assets/svges/anchor.svg +3 -0
- package/assets/svges/android-old.svg +3 -0
- package/assets/svges/android.svg +3 -0
- package/assets/svges/angellist.svg +3 -0
- package/assets/svges/angle-double-down.svg +4 -0
- package/assets/svges/angle-double-left.svg +4 -0
- package/assets/svges/angle-double-right.svg +4 -0
- package/assets/svges/angle-double-up.svg +4 -0
- package/assets/svges/angular.svg +3 -0
- package/assets/svges/app-store.svg +3 -0
- package/assets/svges/apple-brand.svg +3 -0
- package/assets/svges/apple-music-alt.svg +3 -0
- package/assets/svges/apple-music.svg +3 -0
- package/assets/svges/apple-pay.svg +3 -0
- package/assets/svges/arc-browser.svg +6 -0
- package/assets/svges/arrow-all-direction.svg +6 -0
- package/assets/svges/arrow-angular-top-left.svg +3 -0
- package/assets/svges/arrow-angular-top-right.svg +3 -0
- package/assets/svges/arrow-both-direction-horizontal-1.svg +3 -0
- package/assets/svges/arrow-both-direction-vertical-1.svg +3 -0
- package/assets/svges/arrow-downward.svg +3 -0
- package/assets/svges/arrow-left-circle.svg +4 -0
- package/assets/svges/arrow-left.svg +3 -0
- package/assets/svges/arrow-right-circle.svg +4 -0
- package/assets/svges/arrow-right.svg +3 -0
- package/assets/svges/arrow-upward.svg +3 -0
- package/assets/svges/asana.svg +3 -0
- package/assets/svges/astro.svg +4 -0
- package/assets/svges/atlassian.svg +3 -0
- package/assets/svges/audi-alt.svg +3 -0
- package/assets/svges/audi.svg +3 -0
- package/assets/svges/aws.svg +3 -0
- package/assets/svges/azure.svg +3 -0
- package/assets/svges/badge-decagram-percent.svg +6 -0
- package/assets/svges/balloons.svg +3 -0
- package/assets/svges/ban-2.svg +3 -0
- package/assets/svges/bar-chart-4.svg +6 -0
- package/assets/svges/bar-chart-dollar.svg +6 -0
- package/assets/svges/basket-shopping-3.svg +5 -0
- package/assets/svges/beat.svg +3 -0
- package/assets/svges/behance.svg +5 -0
- package/assets/svges/bell-1.svg +3 -0
- package/assets/svges/bike.svg +6 -0
- package/assets/svges/bing.svg +5 -0
- package/assets/svges/bitbucket.svg +5 -0
- package/assets/svges/bitcoin.svg +5 -0
- package/assets/svges/bittorrent.svg +6 -0
- package/assets/svges/blogger-alt.svg +3 -0
- package/assets/svges/blogger.svg +3 -0
- package/assets/svges/bluetooth-logo.svg +3 -0
- package/assets/svges/bluetooth.svg +3 -0
- package/assets/svges/bmw.svg +7 -0
- package/assets/svges/board-writing-3.svg +3 -0
- package/assets/svges/bold.svg +3 -0
- package/assets/svges/bolt-2.svg +3 -0
- package/assets/svges/bolt-3.svg +3 -0
- package/assets/svges/book-1.svg +4 -0
- package/assets/svges/bookmark-1.svg +3 -0
- package/assets/svges/bookmark-circle.svg +4 -0
- package/assets/svges/books-2.svg +3 -0
- package/assets/svges/bootstrap-5-square.svg +3 -0
- package/assets/svges/bootstrap-5.svg +3 -0
- package/assets/svges/box-archive-1.svg +4 -0
- package/assets/svges/box-closed.svg +3 -0
- package/assets/svges/box-gift-1.svg +3 -0
- package/assets/svges/brave.svg +3 -0
- package/assets/svges/bricks.svg +3 -0
- package/assets/svges/bridge-3.svg +3 -0
- package/assets/svges/briefcase-1.svg +3 -0
- package/assets/svges/briefcase-2.svg +3 -0
- package/assets/svges/briefcase-plus-1.svg +4 -0
- package/assets/svges/brush-1-rotated.svg +3 -0
- package/assets/svges/brush-2.svg +3 -0
- package/assets/svges/btc.svg +3 -0
- package/assets/svges/bug-1.svg +3 -0
- package/assets/svges/buildings-1.svg +5 -0
- package/assets/svges/bulb-2.svg +3 -0
- package/assets/svges/bulb-4.svg +9 -0
- package/assets/svges/burger-1.svg +3 -0
- package/assets/svges/burger-drink.svg +4 -0
- package/assets/svges/bus-1.svg +5 -0
- package/assets/svges/busket-ball.svg +3 -0
- package/assets/svges/cake-1.svg +3 -0
- package/assets/svges/calculator-1.svg +8 -0
- package/assets/svges/calculator-2.svg +13 -0
- package/assets/svges/calendar-days.svg +9 -0
- package/assets/svges/camera-1.svg +4 -0
- package/assets/svges/camera-movie-1.svg +3 -0
- package/assets/svges/candy-cane-2.svg +3 -0
- package/assets/svges/candy-round-1.svg +3 -0
- package/assets/svges/canva.svg +3 -0
- package/assets/svges/capsule-1.svg +3 -0
- package/assets/svges/car-2.svg +5 -0
- package/assets/svges/car-4.svg +3 -0
- package/assets/svges/car-6.svg +5 -0
- package/assets/svges/caravan-1.svg +3 -0
- package/assets/svges/cart-1.svg +5 -0
- package/assets/svges/cart-2.svg +5 -0
- package/assets/svges/cash-app.svg +3 -0
- package/assets/svges/certificate-badge-1.svg +6 -0
- package/assets/svges/chat-bubble-2.svg +5 -0
- package/assets/svges/check-circle-1.svg +4 -0
- package/assets/svges/check-square-2.svg +4 -0
- package/assets/svges/check.svg +3 -0
- package/assets/svges/chevron-down-circle.svg +4 -0
- package/assets/svges/chevron-down.svg +3 -0
- package/assets/svges/chevron-left-circle.svg +4 -0
- package/assets/svges/chevron-left.svg +3 -0
- package/assets/svges/chevron-right-circle.svg +4 -0
- package/assets/svges/chevron-up-circle.svg +4 -0
- package/assets/svges/chevron-up.svg +3 -0
- package/assets/svges/chrome.svg +6 -0
- package/assets/svges/chromecast.svg +3 -0
- package/assets/svges/cisco.svg +3 -0
- package/assets/svges/claude.svg +3 -0
- package/assets/svges/clickup.svg +4 -0
- package/assets/svges/clipboard.svg +3 -0
- package/assets/svges/cloud-2.svg +3 -0
- package/assets/svges/cloud-bolt-1.svg +4 -0
- package/assets/svges/cloud-bolt-2.svg +4 -0
- package/assets/svges/cloud-check-circle.svg +5 -0
- package/assets/svges/cloud-download.svg +5 -0
- package/assets/svges/cloud-iot-2.svg +3 -0
- package/assets/svges/cloud-rain.svg +6 -0
- package/assets/svges/cloud-refresh-clockwise.svg +5 -0
- package/assets/svges/cloud-sun.svg +9 -0
- package/assets/svges/cloud-upload.svg +5 -0
- package/assets/svges/cloudflare.svg +3 -0
- package/assets/svges/code-1.svg +5 -0
- package/assets/svges/code-s.svg +5 -0
- package/assets/svges/codepen.svg +3 -0
- package/assets/svges/coffee-cup-2.svg +6 -0
- package/assets/svges/coinbase.svg +10 -0
- package/assets/svges/colour-palette-3.svg +7 -0
- package/assets/svges/comment-1-share.svg +4 -0
- package/assets/svges/comment-1-text.svg +5 -0
- package/assets/svges/comment-1.svg +3 -0
- package/assets/svges/compass-drafting-2.svg +3 -0
- package/assets/svges/connectdevelop.svg +3 -0
- package/assets/svges/copilot.svg +8 -0
- package/assets/svges/coral.svg +3 -0
- package/assets/svges/cpanel.svg +3 -0
- package/assets/svges/crane-4.svg +3 -0
- package/assets/svges/creative-commons.svg +4 -0
- package/assets/svges/credit-card-multiple.svg +3 -0
- package/assets/svges/crop-2.svg +3 -0
- package/assets/svges/crown-3.svg +3 -0
- package/assets/svges/css3.svg +3 -0
- package/assets/svges/dashboard-square-1.svg +6 -0
- package/assets/svges/database-2.svg +3 -0
- package/assets/svges/deno.svg +4 -0
- package/assets/svges/dev.svg +3 -0
- package/assets/svges/dialogflow.svg +4 -0
- package/assets/svges/diamonds-1.svg +3 -0
- package/assets/svges/diamonds-2.svg +3 -0
- package/assets/svges/digitalocean.svg +3 -0
- package/assets/svges/diners-club.svg +38 -0
- package/assets/svges/direction-ltr.svg +4 -0
- package/assets/svges/direction-rtl.svg +4 -0
- package/assets/svges/discord-chat.svg +5 -0
- package/assets/svges/discord.svg +3 -0
- package/assets/svges/discover.svg +3 -0
- package/assets/svges/docker.svg +3 -0
- package/assets/svges/dollar-circle.svg +4 -0
- package/assets/svges/dollar.svg +3 -0
- package/assets/svges/double-quotes-end-1.svg +4 -0
- package/assets/svges/download-1.svg +4 -0
- package/assets/svges/download-circle-1.svg +4 -0
- package/assets/svges/dribbble-symbol.svg +3 -0
- package/assets/svges/dribbble.svg +3 -0
- package/assets/svges/drizzle.svg +6 -0
- package/assets/svges/dropbox.svg +7 -0
- package/assets/svges/drupal.svg +3 -0
- package/assets/svges/dumbbell-1.svg +3 -0
- package/assets/svges/edge.svg +3 -0
- package/assets/svges/emoji-expressionless-flat-eyes.svg +6 -0
- package/assets/svges/emoji-expressionless.svg +6 -0
- package/assets/svges/emoji-grin.svg +6 -0
- package/assets/svges/emoji-sad.svg +6 -0
- package/assets/svges/emoji-smile-side.svg +6 -0
- package/assets/svges/emoji-smile-sunglass.svg +5 -0
- package/assets/svges/emoji-smile-tongue.svg +3 -0
- package/assets/svges/emoji-smile.svg +6 -0
- package/assets/svges/enter-down.svg +4 -0
- package/assets/svges/enter.svg +4 -0
- package/assets/svges/envato.svg +4 -0
- package/assets/svges/envelope-1.svg +3 -0
- package/assets/svges/eraser-1.svg +4 -0
- package/assets/svges/ethereum-logo.svg +4 -0
- package/assets/svges/euro.svg +3 -0
- package/assets/svges/exit-up.svg +4 -0
- package/assets/svges/exit.svg +4 -0
- package/assets/svges/expand-arrow-1.svg +3 -0
- package/assets/svges/expand-square-4.svg +6 -0
- package/assets/svges/expressjs.svg +4 -0
- package/assets/svges/eye.svg +4 -0
- package/assets/svges/facebook-messenger.svg +3 -0
- package/assets/svges/facebook-rounded.svg +4 -0
- package/assets/svges/facebook-square.svg +3 -0
- package/assets/svges/facebook.svg +3 -0
- package/assets/svges/facetime.svg +3 -0
- package/assets/svges/figma.svg +3 -0
- package/assets/svges/file-format-zip.svg +4 -0
- package/assets/svges/file-multiple.svg +4 -0
- package/assets/svges/file-pencil.svg +4 -0
- package/assets/svges/file-plus-circle.svg +5 -0
- package/assets/svges/file-question.svg +5 -0
- package/assets/svges/file-xmark.svg +4 -0
- package/assets/svges/firebase.svg +3 -0
- package/assets/svges/firefox.svg +3 -0
- package/assets/svges/firework-rocket-4.svg +3 -0
- package/assets/svges/fitbit.svg +3 -0
- package/assets/svges/flag-1.svg +3 -0
- package/assets/svges/flag-2.svg +3 -0
- package/assets/svges/flickr.svg +4 -0
- package/assets/svges/floppy-disk-1.svg +3 -0
- package/assets/svges/flower-2.svg +3 -0
- package/assets/svges/flutter.svg +3 -0
- package/assets/svges/folder-1.svg +3 -0
- package/assets/svges/ford.svg +3 -0
- package/assets/svges/framer.svg +3 -0
- package/assets/svges/funnel-1.svg +3 -0
- package/assets/svges/gallery.svg +4 -0
- package/assets/svges/game-pad-modern-1.svg +6 -0
- package/assets/svges/gatsby.svg +3 -0
- package/assets/svges/gauge-1.svg +5 -0
- package/assets/svges/gear-1.svg +4 -0
- package/assets/svges/gears-3.svg +6 -0
- package/assets/svges/gemini.svg +3 -0
- package/assets/svges/git.svg +3 -0
- package/assets/svges/github.svg +3 -0
- package/assets/svges/glass-juice-1.svg +3 -0
- package/assets/svges/globe-1.svg +3 -0
- package/assets/svges/globe-stand.svg +4 -0
- package/assets/svges/go.svg +7 -0
- package/assets/svges/goodreads.svg +3 -0
- package/assets/svges/google-cloud.svg +3 -0
- package/assets/svges/google-drive.svg +3 -0
- package/assets/svges/google-meet.svg +3 -0
- package/assets/svges/google-pay.svg +3 -0
- package/assets/svges/google-wallet.svg +3 -0
- package/assets/svges/google.svg +3 -0
- package/assets/svges/graduation-cap-1.svg +3 -0
- package/assets/svges/grammarly.svg +3 -0
- package/assets/svges/hacker-news.svg +3 -0
- package/assets/svges/hammer-1.svg +3 -0
- package/assets/svges/hammer-2.svg +3 -0
- package/assets/svges/hand-mic.svg +3 -0
- package/assets/svges/hand-shake.svg +3 -0
- package/assets/svges/hand-stop.svg +3 -0
- package/assets/svges/hand-taking-dollar.svg +4 -0
- package/assets/svges/hand-taking-leaf-1.svg +5 -0
- package/assets/svges/hand-taking-user.svg +5 -0
- package/assets/svges/hashnode.svg +3 -0
- package/assets/svges/hat-chef-3.svg +3 -0
- package/assets/svges/headphone-1.svg +3 -0
- package/assets/svges/heart.svg +3 -0
- package/assets/svges/helicopter-2.svg +4 -0
- package/assets/svges/helmet-safety-1.svg +3 -0
- package/assets/svges/hierarchy-1.svg +9 -0
- package/assets/svges/highlighter-1.svg +3 -0
- package/assets/svges/highlighter-2.svg +3 -0
- package/assets/svges/home-2.svg +3 -0
- package/assets/svges/hospital-2.svg +4 -0
- package/assets/svges/hourglass.svg +3 -0
- package/assets/svges/html5.svg +4 -0
- package/assets/svges/ibm.svg +3 -0
- package/assets/svges/id-card.svg +7 -0
- package/assets/svges/imdb.svg +7 -0
- package/assets/svges/indent.svg +8 -0
- package/assets/svges/info.svg +4 -0
- package/assets/svges/injection-1.svg +3 -0
- package/assets/svges/instagram-logotype.svg +3 -0
- package/assets/svges/instagram.svg +4 -0
- package/assets/svges/intel.svg +4 -0
- package/assets/svges/ios.svg +3 -0
- package/assets/svges/island-2.svg +4 -0
- package/assets/svges/jaguar.svg +3 -0
- package/assets/svges/jamstack.svg +3 -0
- package/assets/svges/java.svg +3 -0
- package/assets/svges/javascript.svg +3 -0
- package/assets/svges/jcb.svg +3 -0
- package/assets/svges/joomla.svg +6 -0
- package/assets/svges/jsfiddle.svg +4 -0
- package/assets/svges/key-1.svg +3 -0
- package/assets/svges/keyboard.svg +12 -0
- package/assets/svges/knife-fork-1.svg +5 -0
- package/assets/svges/kubernetes.svg +11 -0
- package/assets/svges/label-dollar-2.svg +4 -0
- package/assets/svges/laptop-2.svg +3 -0
- package/assets/svges/laptop-phone.svg +5 -0
- package/assets/svges/laravel.svg +3 -0
- package/assets/svges/layers-1.svg +4 -0
- package/assets/svges/layout-26.svg +3 -0
- package/assets/svges/layout-9.svg +3 -0
- package/assets/svges/leaf-1.svg +3 -0
- package/assets/svges/leaf-6.svg +4 -0
- package/assets/svges/lemon-squeezy.svg +6 -0
- package/assets/svges/life-guard-tube-1.svg +3 -0
- package/assets/svges/line-dashed.svg +5 -0
- package/assets/svges/line-dotted.svg +8 -0
- package/assets/svges/line-height.svg +7 -0
- package/assets/svges/line.svg +3 -0
- package/assets/svges/lineicons.svg +6 -0
- package/assets/svges/link-2-angular-right.svg +3 -0
- package/assets/svges/linkedin.svg +3 -0
- package/assets/svges/location-arrow-right.svg +3 -0
- package/assets/svges/locked-1.svg +4 -0
- package/assets/svges/locked-2.svg +4 -0
- package/assets/svges/loom.svg +3 -0
- package/assets/svges/magento.svg +4 -0
- package/assets/svges/magnet.svg +3 -0
- package/assets/svges/mailchimp.svg +3 -0
- package/assets/svges/map-marker-1.svg +6 -0
- package/assets/svges/map-marker-5.svg +4 -0
- package/assets/svges/map-pin-5.svg +3 -0
- package/assets/svges/markdown.svg +5 -0
- package/assets/svges/mastercard.svg +7 -0
- package/assets/svges/medium-alt.svg +3 -0
- package/assets/svges/medium.svg +3 -0
- package/assets/svges/megaphone-1.svg +3 -0
- package/assets/svges/menu-cheesburger.svg +8 -0
- package/assets/svges/menu-hamburger-1.svg +5 -0
- package/assets/svges/menu-meatballs-1.svg +5 -0
- package/assets/svges/menu-meatballs-2.svg +5 -0
- package/assets/svges/mercedes.svg +3 -0
- package/assets/svges/message-2-question.svg +5 -0
- package/assets/svges/message-2.svg +3 -0
- package/assets/svges/message-3-text.svg +5 -0
- package/assets/svges/meta-alt.svg +3 -0
- package/assets/svges/meta.svg +7 -0
- package/assets/svges/microphone-1.svg +4 -0
- package/assets/svges/microscope.svg +3 -0
- package/assets/svges/microsoft-edge.svg +5 -0
- package/assets/svges/microsoft-teams.svg +6 -0
- package/assets/svges/microsoft.svg +6 -0
- package/assets/svges/minus-circle.svg +4 -0
- package/assets/svges/minus.svg +3 -0
- package/assets/svges/mongodb.svg +3 -0
- package/assets/svges/monitor-code.svg +5 -0
- package/assets/svges/monitor-mac.svg +3 -0
- package/assets/svges/monitor.svg +3 -0
- package/assets/svges/moon-half-right-5.svg +3 -0
- package/assets/svges/mountains-2.svg +3 -0
- package/assets/svges/mouse-2.svg +3 -0
- package/assets/svges/mushroom-1.svg +3 -0
- package/assets/svges/mushroom-5.svg +6 -0
- package/assets/svges/music.svg +3 -0
- package/assets/svges/mysql.svg +3 -0
- package/assets/svges/nasa.svg +3 -0
- package/assets/svges/netflix.svg +3 -0
- package/assets/svges/netlify.svg +3 -0
- package/assets/svges/next-step-2.svg +3 -0
- package/assets/svges/nextjs.svg +3 -0
- package/assets/svges/nike.svg +3 -0
- package/assets/svges/nissan.svg +3 -0
- package/assets/svges/nodejs-alt.svg +3 -0
- package/assets/svges/nodejs.svg +3 -0
- package/assets/svges/notebook-1.svg +3 -0
- package/assets/svges/notion.svg +3 -0
- package/assets/svges/npm.svg +3 -0
- package/assets/svges/nuxt.svg +3 -0
- package/assets/svges/nvidia.svg +3 -0
- package/assets/svges/oculus.svg +4 -0
- package/assets/svges/open-ai.svg +3 -0
- package/assets/svges/opera-mini.svg +3 -0
- package/assets/svges/oracle.svg +3 -0
- package/assets/svges/outdent.svg +8 -0
- package/assets/svges/paddle.svg +3 -0
- package/assets/svges/page-break-1.svg +7 -0
- package/assets/svges/pagination.svg +7 -0
- package/assets/svges/paint-bucket.svg +3 -0
- package/assets/svges/paint-roller-1.svg +3 -0
- package/assets/svges/paperclip-1.svg +3 -0
- package/assets/svges/party-flags.svg +3 -0
- package/assets/svges/party-spray.svg +3 -0
- package/assets/svges/patreon.svg +3 -0
- package/assets/svges/pause.svg +4 -0
- package/assets/svges/payoneer.svg +4 -0
- package/assets/svges/paypal.svg +4 -0
- package/assets/svges/pen-to-square.svg +4 -0
- package/assets/svges/pencil-1.svg +3 -0
- package/assets/svges/pepsi.svg +4 -0
- package/assets/svges/phone.svg +4 -0
- package/assets/svges/photos.svg +4 -0
- package/assets/svges/php.svg +3 -0
- package/assets/svges/pie-chart-2.svg +3 -0
- package/assets/svges/pilcrow.svg +3 -0
- package/assets/svges/pimjo-logo.svg +9 -0
- package/assets/svges/pimjo-symbol.svg +3 -0
- package/assets/svges/pinterest.svg +3 -0
- package/assets/svges/pizza-2.svg +6 -0
- package/assets/svges/placeholder-dollar.svg +4 -0
- package/assets/svges/plantscale.svg +3 -0
- package/assets/svges/play-store.svg +3 -0
- package/assets/svges/play.svg +3 -0
- package/assets/svges/playstation.svg +5 -0
- package/assets/svges/plug-1.svg +3 -0
- package/assets/svges/plus-circle.svg +4 -0
- package/assets/svges/plus.svg +3 -0
- package/assets/svges/pnpm.svg +10 -0
- package/assets/svges/postgresql.svg +3 -0
- package/assets/svges/postman.svg +3 -0
- package/assets/svges/pound.svg +3 -0
- package/assets/svges/power-button.svg +4 -0
- package/assets/svges/previous-step-2.svg +3 -0
- package/assets/svges/printer.svg +3 -0
- package/assets/svges/prisma.svg +3 -0
- package/assets/svges/producthunt.svg +4 -0
- package/assets/svges/proton-mail-logo.svg +3 -0
- package/assets/svges/proton-mail-symbol.svg +3 -0
- package/assets/svges/python.svg +3 -0
- package/assets/svges/question-mark-circle.svg +5 -0
- package/assets/svges/question-mark.svg +4 -0
- package/assets/svges/quora.svg +4 -0
- package/assets/svges/radis.svg +3 -0
- package/assets/svges/react.svg +3 -0
- package/assets/svges/reddit.svg +6 -0
- package/assets/svges/refresh-circle-1-clockwise.svg +4 -0
- package/assets/svges/refresh-dollar-1.svg +5 -0
- package/assets/svges/refresh-user-1.svg +6 -0
- package/assets/svges/remix-js.svg +4 -0
- package/assets/svges/road-1.svg +6 -0
- package/assets/svges/rocket-5.svg +5 -0
- package/assets/svges/route-1.svg +7 -0
- package/assets/svges/rss-right.svg +6 -0
- package/assets/svges/ruler-1.svg +3 -0
- package/assets/svges/ruler-pen.svg +4 -0
- package/assets/svges/rupee.svg +3 -0
- package/assets/svges/safari.svg +35 -0
- package/assets/svges/sanity.svg +20 -0
- package/assets/svges/school-bench-1.svg +4 -0
- package/assets/svges/school-bench-2.svg +4 -0
- package/assets/svges/scissors-1-vertical.svg +4 -0
- package/assets/svges/scoter.svg +8 -0
- package/assets/svges/scroll-down-2.svg +6 -0
- package/assets/svges/search-1.svg +3 -0
- package/assets/svges/search-2.svg +4 -0
- package/assets/svges/search-minus.svg +4 -0
- package/assets/svges/search-plus.svg +4 -0
- package/assets/svges/search-text.svg +5 -0
- package/assets/svges/select-cursor-1.svg +10 -0
- package/assets/svges/seo-monitor.svg +6 -0
- package/assets/svges/service-bell-1.svg +3 -0
- package/assets/svges/share-1-circle.svg +4 -0
- package/assets/svges/share-1.svg +3 -0
- package/assets/svges/share-2.svg +4 -0
- package/assets/svges/shield-2-check.svg +4 -0
- package/assets/svges/shield-2.svg +3 -0
- package/assets/svges/shield-dollar.svg +4 -0
- package/assets/svges/shift-left.svg +4 -0
- package/assets/svges/shift-right.svg +4 -0
- package/assets/svges/ship-1.svg +5 -0
- package/assets/svges/shirt-1.svg +3 -0
- package/assets/svges/shopify.svg +3 -0
- package/assets/svges/shovel.svg +3 -0
- package/assets/svges/shuffle.svg +3 -0
- package/assets/svges/sign-post-left.svg +3 -0
- package/assets/svges/signal-app.svg +3 -0
- package/assets/svges/signs-post-2.svg +3 -0
- package/assets/svges/sketch.svg +3 -0
- package/assets/svges/skype.svg +3 -0
- package/assets/svges/slack.svg +10 -0
- package/assets/svges/slice-2.svg +3 -0
- package/assets/svges/sliders-horizontal-square-2.svg +7 -0
- package/assets/svges/slideshare.svg +5 -0
- package/assets/svges/snapchat.svg +3 -0
- package/assets/svges/sort-alphabetical.svg +5 -0
- package/assets/svges/sort-high-to-low.svg +7 -0
- package/assets/svges/soundcloud.svg +3 -0
- package/assets/svges/spacex.svg +4 -0
- package/assets/svges/spellcheck.svg +4 -0
- package/assets/svges/spinner-2-sacle.svg +10 -0
- package/assets/svges/spinner-3.svg +3 -0
- package/assets/svges/sports.svg +3 -0
- package/assets/svges/spotify-alt.svg +6 -0
- package/assets/svges/spotify.svg +3 -0
- package/assets/svges/squarespace.svg +3 -0
- package/assets/svges/stackoverflow.svg +8 -0
- package/assets/svges/stamp.svg +3 -0
- package/assets/svges/star-fat-half-2.svg +4 -0
- package/assets/svges/star-fat.svg +3 -0
- package/assets/svges/star-sharp-disabled.svg +4 -0
- package/assets/svges/statista.svg +3 -0
- package/assets/svges/steam.svg +5 -0
- package/assets/svges/stethoscope-1.svg +3 -0
- package/assets/svges/stopwatch.svg +5 -0
- package/assets/svges/storage-hdd-2.svg +4 -0
- package/assets/svges/strikethrough-1.svg +5 -0
- package/assets/svges/stripe.svg +9 -0
- package/assets/svges/stumbleupon.svg +3 -0
- package/assets/svges/sun-1.svg +11 -0
- package/assets/svges/supabase.svg +5 -0
- package/assets/svges/surfboard-2.svg +3 -0
- package/assets/svges/svelte.svg +3 -0
- package/assets/svges/swift.svg +3 -0
- package/assets/svges/tab.svg +4 -0
- package/assets/svges/tailwindcss.svg +3 -0
- package/assets/svges/target-user.svg +5 -0
- package/assets/svges/telegram.svg +3 -0
- package/assets/svges/telephone-1.svg +4 -0
- package/assets/svges/telephone-3.svg +5 -0
- package/assets/svges/tesla.svg +3 -0
- package/assets/svges/text-format-remove.svg +5 -0
- package/assets/svges/text-format.svg +5 -0
- package/assets/svges/text-paragraph.svg +6 -0
- package/assets/svges/thumbs-down-3.svg +3 -0
- package/assets/svges/thumbs-up-3.svg +3 -0
- package/assets/svges/ticket-1.svg +3 -0
- package/assets/svges/tickets-3.svg +7 -0
- package/assets/svges/tiktok-alt.svg +3 -0
- package/assets/svges/tiktok.svg +3 -0
- package/assets/svges/tower-broadcast-1.svg +7 -0
- package/assets/svges/toyota.svg +4 -0
- package/assets/svges/train-1.svg +4 -0
- package/assets/svges/train-3.svg +5 -0
- package/assets/svges/trash-3.svg +5 -0
- package/assets/svges/tree-2.svg +3 -0
- package/assets/svges/trees-3.svg +3 -0
- package/assets/svges/trello.svg +3 -0
- package/assets/svges/trend-down-1.svg +3 -0
- package/assets/svges/trend-up-1.svg +3 -0
- package/assets/svges/trophy-1.svg +3 -0
- package/assets/svges/trowel-1.svg +3 -0
- package/assets/svges/truck-delivery-1.svg +3 -0
- package/assets/svges/tumblr.svg +3 -0
- package/assets/svges/turborepo.svg +4 -0
- package/assets/svges/twitch.svg +3 -0
- package/assets/svges/twitter-old.svg +3 -0
- package/assets/svges/typescript.svg +3 -0
- package/assets/svges/uber-symbol.svg +3 -0
- package/assets/svges/uber.svg +3 -0
- package/assets/svges/ubuntu.svg +3 -0
- package/assets/svges/underline.svg +4 -0
- package/assets/svges/unlink-2-angular-eft.svg +8 -0
- package/assets/svges/unlocked-2.svg +4 -0
- package/assets/svges/unsplash.svg +4 -0
- package/assets/svges/upload-1.svg +4 -0
- package/assets/svges/upload-circle-1.svg +4 -0
- package/assets/svges/user-4.svg +4 -0
- package/assets/svges/user-multiple-4.svg +6 -0
- package/assets/svges/vector-nodes-6.svg +3 -0
- package/assets/svges/vector-nodes-7.svg +3 -0
- package/assets/svges/vercel.svg +3 -0
- package/assets/svges/vimeo.svg +3 -0
- package/assets/svges/visa.svg +3 -0
- package/assets/svges/vite.svg +6 -0
- package/assets/svges/vk.svg +3 -0
- package/assets/svges/vmware.svg +4 -0
- package/assets/svges/volkswagen.svg +8 -0
- package/assets/svges/volume-1.svg +5 -0
- package/assets/svges/volume-high.svg +6 -0
- package/assets/svges/volume-low.svg +4 -0
- package/assets/svges/volume-mute.svg +6 -0
- package/assets/svges/volume-off.svg +3 -0
- package/assets/svges/vs-code.svg +3 -0
- package/assets/svges/vuejs.svg +3 -0
- package/assets/svges/wallet-1.svg +3 -0
- package/assets/svges/watch-beat-1.svg +4 -0
- package/assets/svges/water-drop-1.svg +4 -0
- package/assets/svges/webflow.svg +3 -0
- package/assets/svges/webhooks.svg +3 -0
- package/assets/svges/wechat.svg +4 -0
- package/assets/svges/weight-machine-1.svg +4 -0
- package/assets/svges/whatsapp.svg +3 -0
- package/assets/svges/wheelbarrow-empty.svg +3 -0
- package/assets/svges/wheelchair-1.svg +3 -0
- package/assets/svges/windows.svg +6 -0
- package/assets/svges/wise.svg +3 -0
- package/assets/svges/wordpress.svg +3 -0
- package/assets/svges/www-cursor.svg +5 -0
- package/assets/svges/www.svg +4 -0
- package/assets/svges/x.svg +3 -0
- package/assets/svges/xampp.svg +5 -0
- package/assets/svges/xbox.svg +6 -0
- package/assets/svges/xmark-circle.svg +4 -0
- package/assets/svges/xmark.svg +3 -0
- package/assets/svges/xrp.svg +3 -0
- package/assets/svges/yahoo.svg +3 -0
- package/assets/svges/yarn.svg +4 -0
- package/assets/svges/ycombinator.svg +3 -0
- package/assets/svges/yen.svg +3 -0
- package/assets/svges/youtube-kids.svg +3 -0
- package/assets/svges/youtube-music.svg +4 -0
- package/assets/svges/youtube.svg +3 -0
- package/assets/svges/zapier.svg +3 -0
- package/assets/svges/zero-size.svg +6 -0
- package/assets/svges/zoom.svg +4 -0
- package/bin/test-svger.js +163 -0
- package/dist/__tests__/__mocks__/visual-diff.d.ts +7 -0
- package/dist/__tests__/__mocks__/visual-diff.js +13 -0
- package/dist/__tests__/fixtures.js +18 -18
- package/dist/cli.js +148 -2
- package/dist/config.js +4 -1
- package/dist/core/enhanced-plugin-manager.d.ts +107 -0
- package/dist/core/enhanced-plugin-manager.js +315 -0
- package/dist/core/error-handler.d.ts +1 -1
- package/dist/core/error-handler.js +14 -17
- package/dist/core/framework-templates.js +37 -47
- package/dist/core/logger.js +0 -1
- package/dist/core/performance-engine.js +10 -15
- package/dist/core/plugin-manager.js +4 -4
- package/dist/core/style-compiler.d.ts +0 -1
- package/dist/core/style-compiler.js +3 -6
- package/dist/index.d.ts +4 -0
- package/dist/index.js +4 -0
- package/dist/integrations/babel.d.ts +1 -1
- package/dist/integrations/babel.js +31 -12
- package/dist/integrations/jest-preset.js +1 -1
- package/dist/integrations/rollup.js +29 -10
- package/dist/integrations/vite.js +29 -14
- package/dist/integrations/webpack.d.ts +1 -0
- package/dist/integrations/webpack.js +29 -10
- package/dist/optimizers/advanced-stages.d.ts +40 -0
- package/dist/optimizers/advanced-stages.js +297 -0
- package/dist/optimizers/basic-cleaner.d.ts +68 -0
- package/dist/optimizers/basic-cleaner.js +198 -0
- package/dist/optimizers/collapse-useless-groups.d.ts +26 -0
- package/dist/optimizers/collapse-useless-groups.js +104 -0
- package/dist/optimizers/command-optimizer.d.ts +48 -0
- package/dist/optimizers/command-optimizer.js +299 -0
- package/dist/optimizers/index.d.ts +14 -0
- package/dist/optimizers/index.js +15 -0
- package/dist/optimizers/move-attrs-to-parent.d.ts +31 -0
- package/dist/optimizers/move-attrs-to-parent.js +115 -0
- package/dist/optimizers/numeric-optimizer.d.ts +43 -0
- package/dist/optimizers/numeric-optimizer.js +383 -0
- package/dist/optimizers/optimizer-pipeline.d.ts +39 -0
- package/dist/optimizers/optimizer-pipeline.js +81 -0
- package/dist/optimizers/path-deduplicator.d.ts +37 -0
- package/dist/optimizers/path-deduplicator.js +406 -0
- package/dist/optimizers/path-parser.d.ts +60 -0
- package/dist/optimizers/path-parser.js +428 -0
- package/dist/optimizers/path-shortener.d.ts +41 -0
- package/dist/optimizers/path-shortener.js +274 -0
- package/dist/optimizers/path-simplifier.d.ts +30 -0
- package/dist/optimizers/path-simplifier.js +326 -0
- package/dist/optimizers/remove-hidden-empty.d.ts +29 -0
- package/dist/optimizers/remove-hidden-empty.js +130 -0
- package/dist/optimizers/remove-unused-defs.d.ts +24 -0
- package/dist/optimizers/remove-unused-defs.js +132 -0
- package/dist/optimizers/shape-conversion.d.ts +74 -0
- package/dist/optimizers/shape-conversion.js +277 -0
- package/dist/optimizers/style-optimizer.d.ts +30 -0
- package/dist/optimizers/style-optimizer.js +324 -0
- package/dist/optimizers/svg-tree-parser.d.ts +55 -0
- package/dist/optimizers/svg-tree-parser.js +352 -0
- package/dist/optimizers/transform-collapsing.d.ts +38 -0
- package/dist/optimizers/transform-collapsing.js +444 -0
- package/dist/optimizers/transform-optimizer.d.ts +65 -0
- package/dist/optimizers/transform-optimizer.js +320 -0
- package/dist/optimizers/tree-serializer.d.ts +46 -0
- package/dist/optimizers/tree-serializer.js +190 -0
- package/dist/optimizers/tree-stages.d.ts +27 -0
- package/dist/optimizers/tree-stages.js +141 -0
- package/dist/optimizers/types.d.ts +207 -0
- package/dist/optimizers/types.js +122 -0
- package/dist/plugins/color-replacer.d.ts +39 -0
- package/dist/plugins/color-replacer.js +126 -0
- package/dist/plugins/gradient-optimizer.d.ts +33 -0
- package/dist/plugins/gradient-optimizer.js +197 -0
- package/dist/plugins/stroke-normalizer.d.ts +33 -0
- package/dist/plugins/stroke-normalizer.js +166 -0
- package/dist/plugins/watermark-remover.d.ts +32 -0
- package/dist/plugins/watermark-remover.js +133 -0
- package/dist/processors/svg-processor.d.ts +17 -2
- package/dist/processors/svg-processor.js +108 -32
- package/dist/services/config.d.ts +4 -0
- package/dist/services/config.js +62 -1
- package/dist/services/file-watcher.d.ts +1 -1
- package/dist/services/file-watcher.js +1 -1
- package/dist/services/svg-service.d.ts +6 -0
- package/dist/services/svg-service.js +66 -16
- package/dist/types/index.d.ts +1 -0
- package/dist/types/plugin-system.d.ts +153 -0
- package/dist/types/plugin-system.js +5 -0
- package/dist/utils/visual-diff.d.ts +150 -0
- package/dist/utils/visual-diff.js +247 -0
- package/dist/watch.js +0 -2
- package/docs/COMPLETE-ACHIEVEMENT-SUMMARY.md +401 -0
- package/docs/MIGRATION-4.0.0.md +271 -0
- package/docs/PIPELINE-INTEGRATION.md +406 -0
- package/docs/PLUGIN-DEVELOPMENT-GUIDE.md +807 -0
- package/docs/QUICK-REFERENCE.md +176 -0
- package/docs/SAMPLE-SVGS-TESTING.md +276 -0
- package/docs/archive/PHASE-1-ARCHITECTURE.md +345 -0
- package/docs/archive/PHASE-1-IMPLEMENTATION.md +307 -0
- package/docs/archive/PHASE-1-SUMMARY.md +298 -0
- package/docs/archive/PHASE-2-COMPLETE.md +207 -0
- package/docs/archive/PHASE-3-SUMMARY.md +149 -0
- package/docs/archive/PHASE-4.3-COMMAND-OPTIMIZER.md +323 -0
- package/docs/archive/PHASE-4.4-PATH-SIMPLIFICATION.md +81 -0
- package/docs/archive/PHASE-4.5-PATH-DEDUPLICATION.md +449 -0
- package/docs/archive/PHASE-5.1-SUCCESS-REPORT.md +207 -0
- package/docs/archive/PHASE-5.1-TRANSFORM-COLLAPSING.md +362 -0
- package/docs/archive/PHASE-6.1-SHAPE-CONVERSION-DESIGN.md +518 -0
- package/docs/archive/PHASE-6.2-PLUGIN-SYSTEM-STATUS.md +403 -0
- package/docs/archive/PHASE-6.3-FINAL-STATUS.md +193 -0
- package/docs/archive/PHASE-6.3-VALIDATION-PROGRESS.md +345 -0
- package/docs/archive/PHASE-6.3-VISUAL-DIFF-DESIGN.md +553 -0
- package/docs/archive/PHASE-6.3-VISUAL-DIFF-SUMMARY.md +367 -0
- package/docs/archive/PHASE-6.3-XML-SERIALIZATION-FIX.md +210 -0
- package/docs/archive/RELEASE-NOTES-3.2.0.md +344 -0
- package/docs/archive/RELEASE-PREP-3.2.0.md +376 -0
- package/docs/performance/PERFORMANCE-RESULTS.md +31 -0
- package/docs/performance/REAL-WORLD-BENCHMARKS.md +159 -0
- package/package.json +16 -6
- package/DEVELOPMENT.md +0 -353
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Phase 6.3: Visual Diff Testing
|
|
3
|
+
*
|
|
4
|
+
* Provides pixel-perfect comparison of SVGs before/after optimization
|
|
5
|
+
* to ensure zero visual regression.
|
|
6
|
+
*
|
|
7
|
+
* Uses:
|
|
8
|
+
* - sharp: SVG → PNG rendering (via librsvg)
|
|
9
|
+
* - pixelmatch: Pixel-by-pixel comparison
|
|
10
|
+
* - pngjs: PNG buffer handling
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* Rendering configuration for SVG → PNG conversion
|
|
14
|
+
*/
|
|
15
|
+
export interface RenderConfig {
|
|
16
|
+
/** Image width in pixels */
|
|
17
|
+
width: number;
|
|
18
|
+
/** Image height in pixels */
|
|
19
|
+
height: number;
|
|
20
|
+
/** DPI density (144 = 2x retina) */
|
|
21
|
+
density: number;
|
|
22
|
+
/** Background color */
|
|
23
|
+
background: string;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Pixel comparison configuration
|
|
27
|
+
*/
|
|
28
|
+
export interface DiffConfig {
|
|
29
|
+
/** Pixel color difference threshold (0-1, default: 0.1) */
|
|
30
|
+
threshold: number;
|
|
31
|
+
/** Include anti-aliasing in diff detection */
|
|
32
|
+
includeAA: boolean;
|
|
33
|
+
/** Alpha blend value for diff mask (0-1) */
|
|
34
|
+
alpha: number;
|
|
35
|
+
/** RGB color for highlighted differences */
|
|
36
|
+
diffColor: [number, number, number];
|
|
37
|
+
/** Maximum allowed difference percentage (0-100) */
|
|
38
|
+
maxDiffPercent: number;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Visual diff comparison result
|
|
42
|
+
*/
|
|
43
|
+
export interface VisualDiffResult {
|
|
44
|
+
/** True if difference is within acceptable threshold */
|
|
45
|
+
passed: boolean;
|
|
46
|
+
/** Number of different pixels */
|
|
47
|
+
mismatchCount: number;
|
|
48
|
+
/** Percentage of different pixels (0-100) */
|
|
49
|
+
mismatchPercent: number;
|
|
50
|
+
/** Total pixel count */
|
|
51
|
+
totalPixels: number;
|
|
52
|
+
/** PNG buffer with highlighted differences (if generated) */
|
|
53
|
+
diffImage?: Buffer;
|
|
54
|
+
/** Human-readable summary message */
|
|
55
|
+
message: string;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Options for compareVisually()
|
|
59
|
+
*/
|
|
60
|
+
export interface CompareOptions {
|
|
61
|
+
/** Rendering configuration */
|
|
62
|
+
render?: Partial<RenderConfig>;
|
|
63
|
+
/** Diff comparison configuration */
|
|
64
|
+
diff?: Partial<DiffConfig>;
|
|
65
|
+
/** Path to save diff image (optional) */
|
|
66
|
+
saveDiffImage?: string;
|
|
67
|
+
}
|
|
68
|
+
export declare class VisualDiffError extends Error {
|
|
69
|
+
readonly code: 'RENDER_FAILED' | 'COMPARISON_FAILED' | 'THRESHOLD_EXCEEDED';
|
|
70
|
+
constructor(message: string, code: 'RENDER_FAILED' | 'COMPARISON_FAILED' | 'THRESHOLD_EXCEEDED');
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Render SVG string to PNG buffer
|
|
74
|
+
*
|
|
75
|
+
* @param svgContent - SVG string to render
|
|
76
|
+
* @param config - Rendering configuration
|
|
77
|
+
* @returns PNG buffer
|
|
78
|
+
*/
|
|
79
|
+
export declare function renderSVG(svgContent: string, config?: Partial<RenderConfig>): Promise<Buffer>;
|
|
80
|
+
/**
|
|
81
|
+
* Compare two PNG buffers pixel-by-pixel
|
|
82
|
+
*
|
|
83
|
+
* @param beforePNG - Original PNG buffer
|
|
84
|
+
* @param afterPNG - Optimized PNG buffer
|
|
85
|
+
* @param config - Diff configuration
|
|
86
|
+
* @param generateDiffImage - Whether to generate diff image
|
|
87
|
+
* @returns Comparison result with mismatch count and percentage
|
|
88
|
+
*/
|
|
89
|
+
export declare function comparePixels(beforePNG: Buffer, afterPNG: Buffer, config?: Partial<DiffConfig>, generateDiffImage?: boolean): Promise<{
|
|
90
|
+
mismatchCount: number;
|
|
91
|
+
mismatchPercent: number;
|
|
92
|
+
totalPixels: number;
|
|
93
|
+
diffImage?: Buffer;
|
|
94
|
+
}>;
|
|
95
|
+
/**
|
|
96
|
+
* Compare two SVG strings for visual differences
|
|
97
|
+
*
|
|
98
|
+
* Main entry point for visual diff testing.
|
|
99
|
+
*
|
|
100
|
+
* @param beforeSVG - Original SVG string
|
|
101
|
+
* @param afterSVG - Optimized SVG string
|
|
102
|
+
* @param options - Comparison options
|
|
103
|
+
* @returns Visual diff result
|
|
104
|
+
*
|
|
105
|
+
* @example
|
|
106
|
+
* ```typescript
|
|
107
|
+
* const result = await compareVisually(original, optimized, {
|
|
108
|
+
* diff: { maxDiffPercent: 0.1 },
|
|
109
|
+
* saveDiffImage: './diff.png'
|
|
110
|
+
* });
|
|
111
|
+
*
|
|
112
|
+
* if (result.passed) {
|
|
113
|
+
* console.log('✓ Visual appearance preserved');
|
|
114
|
+
* } else {
|
|
115
|
+
* console.error(`✗ ${result.mismatchPercent.toFixed(2)}% difference detected`);
|
|
116
|
+
* }
|
|
117
|
+
* ```
|
|
118
|
+
*/
|
|
119
|
+
export declare function compareVisually(beforeSVG: string, afterSVG: string, options?: CompareOptions): Promise<VisualDiffResult>;
|
|
120
|
+
/**
|
|
121
|
+
* Safe wrapper for compareVisually that returns null on error
|
|
122
|
+
*
|
|
123
|
+
* @param beforeSVG - Original SVG string
|
|
124
|
+
* @param afterSVG - Optimized SVG string
|
|
125
|
+
* @param options - Comparison options
|
|
126
|
+
* @returns Visual diff result or null on error
|
|
127
|
+
*/
|
|
128
|
+
export declare function safeCompareVisually(beforeSVG: string, afterSVG: string, options?: CompareOptions): Promise<VisualDiffResult | null>;
|
|
129
|
+
/**
|
|
130
|
+
* Format visual diff result as human-readable string
|
|
131
|
+
*
|
|
132
|
+
* @param result - Visual diff result
|
|
133
|
+
* @returns Formatted string
|
|
134
|
+
*/
|
|
135
|
+
export declare function formatDiffResult(result: VisualDiffResult): string;
|
|
136
|
+
/**
|
|
137
|
+
* Batch compare multiple SVG pairs
|
|
138
|
+
*
|
|
139
|
+
* @param pairs - Array of [before, after] SVG pairs
|
|
140
|
+
* @param options - Comparison options
|
|
141
|
+
* @returns Array of results
|
|
142
|
+
*/
|
|
143
|
+
export declare function batchCompare(pairs: Array<{
|
|
144
|
+
name: string;
|
|
145
|
+
before: string;
|
|
146
|
+
after: string;
|
|
147
|
+
}>, options?: CompareOptions): Promise<Array<{
|
|
148
|
+
name: string;
|
|
149
|
+
result: VisualDiffResult;
|
|
150
|
+
}>>;
|
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Phase 6.3: Visual Diff Testing
|
|
3
|
+
*
|
|
4
|
+
* Provides pixel-perfect comparison of SVGs before/after optimization
|
|
5
|
+
* to ensure zero visual regression.
|
|
6
|
+
*
|
|
7
|
+
* Uses:
|
|
8
|
+
* - sharp: SVG → PNG rendering (via librsvg)
|
|
9
|
+
* - pixelmatch: Pixel-by-pixel comparison
|
|
10
|
+
* - pngjs: PNG buffer handling
|
|
11
|
+
*/
|
|
12
|
+
import sharp from 'sharp';
|
|
13
|
+
import pixelmatch from 'pixelmatch';
|
|
14
|
+
import { PNG } from 'pngjs';
|
|
15
|
+
// ============================================================================
|
|
16
|
+
// Default Configurations
|
|
17
|
+
// ============================================================================
|
|
18
|
+
const DEFAULT_RENDER_CONFIG = {
|
|
19
|
+
width: 800,
|
|
20
|
+
height: 600,
|
|
21
|
+
density: 144, // 2x retina for fine details
|
|
22
|
+
background: 'transparent',
|
|
23
|
+
};
|
|
24
|
+
const DEFAULT_DIFF_CONFIG = {
|
|
25
|
+
threshold: 0.1, // 10% color difference per pixel
|
|
26
|
+
includeAA: false, // Ignore anti-aliasing differences
|
|
27
|
+
alpha: 0.1, // 10% alpha blend for diff mask
|
|
28
|
+
diffColor: [255, 0, 255], // Magenta
|
|
29
|
+
maxDiffPercent: 0.1, // 0.1% of pixels can differ
|
|
30
|
+
};
|
|
31
|
+
// ============================================================================
|
|
32
|
+
// Error Handling
|
|
33
|
+
// ============================================================================
|
|
34
|
+
export class VisualDiffError extends Error {
|
|
35
|
+
code;
|
|
36
|
+
constructor(message, code) {
|
|
37
|
+
super(message);
|
|
38
|
+
this.code = code;
|
|
39
|
+
this.name = 'VisualDiffError';
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
// ============================================================================
|
|
43
|
+
// Core Functions
|
|
44
|
+
// ============================================================================
|
|
45
|
+
/**
|
|
46
|
+
* Render SVG string to PNG buffer
|
|
47
|
+
*
|
|
48
|
+
* @param svgContent - SVG string to render
|
|
49
|
+
* @param config - Rendering configuration
|
|
50
|
+
* @returns PNG buffer
|
|
51
|
+
*/
|
|
52
|
+
export async function renderSVG(svgContent, config) {
|
|
53
|
+
const renderConfig = { ...DEFAULT_RENDER_CONFIG, ...config };
|
|
54
|
+
try {
|
|
55
|
+
// Create SVG buffer
|
|
56
|
+
const svgBuffer = Buffer.from(svgContent, 'utf-8');
|
|
57
|
+
// Render to PNG using sharp
|
|
58
|
+
const pngBuffer = await sharp(svgBuffer, { density: renderConfig.density })
|
|
59
|
+
.resize(renderConfig.width, renderConfig.height, {
|
|
60
|
+
fit: 'contain',
|
|
61
|
+
background: renderConfig.background,
|
|
62
|
+
})
|
|
63
|
+
.png()
|
|
64
|
+
.toBuffer();
|
|
65
|
+
return pngBuffer;
|
|
66
|
+
}
|
|
67
|
+
catch (error) {
|
|
68
|
+
throw new VisualDiffError(`Failed to render SVG: ${error instanceof Error ? error.message : String(error)}`, 'RENDER_FAILED');
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Compare two PNG buffers pixel-by-pixel
|
|
73
|
+
*
|
|
74
|
+
* @param beforePNG - Original PNG buffer
|
|
75
|
+
* @param afterPNG - Optimized PNG buffer
|
|
76
|
+
* @param config - Diff configuration
|
|
77
|
+
* @param generateDiffImage - Whether to generate diff image
|
|
78
|
+
* @returns Comparison result with mismatch count and percentage
|
|
79
|
+
*/
|
|
80
|
+
export async function comparePixels(beforePNG, afterPNG, config, generateDiffImage = false) {
|
|
81
|
+
const diffConfig = { ...DEFAULT_DIFF_CONFIG, ...config };
|
|
82
|
+
try {
|
|
83
|
+
// Parse PNG buffers
|
|
84
|
+
const img1 = PNG.sync.read(beforePNG);
|
|
85
|
+
const img2 = PNG.sync.read(afterPNG);
|
|
86
|
+
// Verify dimensions match
|
|
87
|
+
if (img1.width !== img2.width || img1.height !== img2.height) {
|
|
88
|
+
throw new VisualDiffError(`Image dimensions mismatch: ${img1.width}×${img1.height} vs ${img2.width}×${img2.height}`, 'COMPARISON_FAILED');
|
|
89
|
+
}
|
|
90
|
+
const { width, height } = img1;
|
|
91
|
+
const totalPixels = width * height;
|
|
92
|
+
// Create diff image buffer if requested
|
|
93
|
+
const diff = generateDiffImage ? new PNG({ width, height }) : undefined;
|
|
94
|
+
// Compare pixels
|
|
95
|
+
const mismatchCount = pixelmatch(img1.data, img2.data, diff?.data, width, height, {
|
|
96
|
+
threshold: diffConfig.threshold,
|
|
97
|
+
includeAA: diffConfig.includeAA,
|
|
98
|
+
alpha: diffConfig.alpha,
|
|
99
|
+
diffColor: diffConfig.diffColor,
|
|
100
|
+
});
|
|
101
|
+
const mismatchPercent = (mismatchCount / totalPixels) * 100;
|
|
102
|
+
// Generate diff image buffer if requested
|
|
103
|
+
let diffImage;
|
|
104
|
+
if (diff) {
|
|
105
|
+
diffImage = PNG.sync.write(diff);
|
|
106
|
+
}
|
|
107
|
+
return {
|
|
108
|
+
mismatchCount,
|
|
109
|
+
mismatchPercent,
|
|
110
|
+
totalPixels,
|
|
111
|
+
diffImage,
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
catch (error) {
|
|
115
|
+
if (error instanceof VisualDiffError) {
|
|
116
|
+
throw error;
|
|
117
|
+
}
|
|
118
|
+
throw new VisualDiffError(`Pixel comparison failed: ${error instanceof Error ? error.message : String(error)}`, 'COMPARISON_FAILED');
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Compare two SVG strings for visual differences
|
|
123
|
+
*
|
|
124
|
+
* Main entry point for visual diff testing.
|
|
125
|
+
*
|
|
126
|
+
* @param beforeSVG - Original SVG string
|
|
127
|
+
* @param afterSVG - Optimized SVG string
|
|
128
|
+
* @param options - Comparison options
|
|
129
|
+
* @returns Visual diff result
|
|
130
|
+
*
|
|
131
|
+
* @example
|
|
132
|
+
* ```typescript
|
|
133
|
+
* const result = await compareVisually(original, optimized, {
|
|
134
|
+
* diff: { maxDiffPercent: 0.1 },
|
|
135
|
+
* saveDiffImage: './diff.png'
|
|
136
|
+
* });
|
|
137
|
+
*
|
|
138
|
+
* if (result.passed) {
|
|
139
|
+
* console.log('✓ Visual appearance preserved');
|
|
140
|
+
* } else {
|
|
141
|
+
* console.error(`✗ ${result.mismatchPercent.toFixed(2)}% difference detected`);
|
|
142
|
+
* }
|
|
143
|
+
* ```
|
|
144
|
+
*/
|
|
145
|
+
export async function compareVisually(beforeSVG, afterSVG, options) {
|
|
146
|
+
const renderConfig = options?.render;
|
|
147
|
+
const diffConfig = options?.diff;
|
|
148
|
+
const maxDiffPercent = diffConfig?.maxDiffPercent ?? DEFAULT_DIFF_CONFIG.maxDiffPercent;
|
|
149
|
+
const shouldSaveDiff = !!options?.saveDiffImage;
|
|
150
|
+
try {
|
|
151
|
+
// Step 1: Render both SVGs to PNG
|
|
152
|
+
const beforePNG = await renderSVG(beforeSVG, renderConfig);
|
|
153
|
+
const afterPNG = await renderSVG(afterSVG, renderConfig);
|
|
154
|
+
// Step 2: Compare pixels
|
|
155
|
+
const { mismatchCount, mismatchPercent, totalPixels, diffImage } = await comparePixels(beforePNG, afterPNG, diffConfig, shouldSaveDiff);
|
|
156
|
+
// Step 3: Determine pass/fail
|
|
157
|
+
const passed = mismatchPercent <= maxDiffPercent;
|
|
158
|
+
// Step 4: Generate summary message
|
|
159
|
+
const message = passed
|
|
160
|
+
? `Visual diff passed: ${mismatchPercent.toFixed(4)}% difference (threshold: ${maxDiffPercent}%)`
|
|
161
|
+
: `Visual diff failed: ${mismatchPercent.toFixed(4)}% difference exceeds threshold of ${maxDiffPercent}%`;
|
|
162
|
+
// Step 5: Save diff image if requested
|
|
163
|
+
if (options?.saveDiffImage && diffImage) {
|
|
164
|
+
const fs = await import('fs/promises');
|
|
165
|
+
const path = await import('path');
|
|
166
|
+
// Ensure directory exists
|
|
167
|
+
const dir = path.dirname(options.saveDiffImage);
|
|
168
|
+
await fs.mkdir(dir, { recursive: true });
|
|
169
|
+
// Write diff image
|
|
170
|
+
await fs.writeFile(options.saveDiffImage, diffImage);
|
|
171
|
+
}
|
|
172
|
+
return {
|
|
173
|
+
passed,
|
|
174
|
+
mismatchCount,
|
|
175
|
+
mismatchPercent,
|
|
176
|
+
totalPixels,
|
|
177
|
+
diffImage: shouldSaveDiff ? diffImage : undefined,
|
|
178
|
+
message,
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
catch (error) {
|
|
182
|
+
if (error instanceof VisualDiffError) {
|
|
183
|
+
throw error;
|
|
184
|
+
}
|
|
185
|
+
throw new VisualDiffError(`Visual comparison failed: ${error instanceof Error ? error.message : String(error)}`, 'COMPARISON_FAILED');
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Safe wrapper for compareVisually that returns null on error
|
|
190
|
+
*
|
|
191
|
+
* @param beforeSVG - Original SVG string
|
|
192
|
+
* @param afterSVG - Optimized SVG string
|
|
193
|
+
* @param options - Comparison options
|
|
194
|
+
* @returns Visual diff result or null on error
|
|
195
|
+
*/
|
|
196
|
+
export async function safeCompareVisually(beforeSVG, afterSVG, options) {
|
|
197
|
+
try {
|
|
198
|
+
return await compareVisually(beforeSVG, afterSVG, options);
|
|
199
|
+
}
|
|
200
|
+
catch (error) {
|
|
201
|
+
if (error instanceof VisualDiffError) {
|
|
202
|
+
console.warn(`Visual diff error: ${error.message} (${error.code})`);
|
|
203
|
+
return null;
|
|
204
|
+
}
|
|
205
|
+
throw error;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
// ============================================================================
|
|
209
|
+
// Utility Functions
|
|
210
|
+
// ============================================================================
|
|
211
|
+
/**
|
|
212
|
+
* Format visual diff result as human-readable string
|
|
213
|
+
*
|
|
214
|
+
* @param result - Visual diff result
|
|
215
|
+
* @returns Formatted string
|
|
216
|
+
*/
|
|
217
|
+
export function formatDiffResult(result) {
|
|
218
|
+
const status = result.passed ? '✓ PASSED' : '✗ FAILED';
|
|
219
|
+
const percent = result.mismatchPercent.toFixed(4);
|
|
220
|
+
const pixels = result.mismatchCount.toLocaleString();
|
|
221
|
+
const total = result.totalPixels.toLocaleString();
|
|
222
|
+
return [
|
|
223
|
+
`${status}: ${percent}% difference`,
|
|
224
|
+
`Mismatched pixels: ${pixels} / ${total}`,
|
|
225
|
+
result.message,
|
|
226
|
+
].join('\n');
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Batch compare multiple SVG pairs
|
|
230
|
+
*
|
|
231
|
+
* @param pairs - Array of [before, after] SVG pairs
|
|
232
|
+
* @param options - Comparison options
|
|
233
|
+
* @returns Array of results
|
|
234
|
+
*/
|
|
235
|
+
export async function batchCompare(pairs, options) {
|
|
236
|
+
const results = [];
|
|
237
|
+
for (const { name, before, after } of pairs) {
|
|
238
|
+
try {
|
|
239
|
+
const result = await compareVisually(before, after, options);
|
|
240
|
+
results.push({ name, result });
|
|
241
|
+
}
|
|
242
|
+
catch (error) {
|
|
243
|
+
console.error(`Failed to compare ${name}:`, error);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
return results;
|
|
247
|
+
}
|
package/dist/watch.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import path from 'path';
|
|
2
2
|
import { generateSVG } from './builder.js';
|
|
3
3
|
import { isLocked } from './lock.js';
|
|
4
|
-
import { readConfig } from './config.js';
|
|
5
4
|
import { FileSystem, FileWatcher } from './utils/native.js';
|
|
6
5
|
/**
|
|
7
6
|
* Watches a source folder for changes to SVG files and automatically
|
|
@@ -23,7 +22,6 @@ import { FileSystem, FileWatcher } from './utils/native.js';
|
|
|
23
22
|
export async function watchSVGs(config) {
|
|
24
23
|
const srcDir = path.resolve(config.src);
|
|
25
24
|
const outDir = path.resolve(config.out);
|
|
26
|
-
const svgConfig = readConfig();
|
|
27
25
|
if (!(await FileSystem.exists(srcDir))) {
|
|
28
26
|
console.error('❌ Source folder not found:', srcDir);
|
|
29
27
|
process.exit(1);
|