Skip to content

Instantly share code, notes, and snippets.

@christiangenco
Forked from PicchiKevin/migrate.sh
Last active March 29, 2024 11:34
Show Gist options
  • Star 18 You must be signed in to star a gist
  • Fork 6 You must be signed in to fork a gist
  • Save christiangenco/470a99f4823ee81f2b22bad83119f599 to your computer and use it in GitHub Desktop.
Save christiangenco/470a99f4823ee81f2b22bad83119f599 to your computer and use it in GitHub Desktop.
Heroicons v1 to v2

Heroicons v1 to v2 migration script

This script:

  1. Upgrades your heroicons library to the latest version (detecting if you're using heroicons/react or heroicons/vue and yarn or npm)
  2. Upgrades your import statements (from @heroicons/${framework}/{solid|outline} to @heroicons/${framework}/20/{solid|outline})
  3. Upgrades your icon names

Thanks to @steveoh & @ryanburns23 for creating the initial list of changes in tailwindlabs/heroicons#750 and to @PicchiKevin for the initial version of this script.


Run

curl https://gist.githubusercontent.com/christiangenco/470a99f4823ee81f2b22bad83119f599/raw/migrateHeroicons.js | node | bash

It definitely works on macOS and should work on linux too. If not you might have to play with the syntax of sed (maybe by replacing sed -i '' -e with sed -i in the gsub function?).

The script will avoid replacing strings in hidden folders and the node_modules folder.

Happy with this script? Come say hi on Twitter @KevinPicchi / @cgenco

const fs = require("fs");
if (!fs.existsSync("package.json")) {
console.error(
"Cannot find package.json. Please run this script in your project directory."
);
process.exit(1);
}
const package = fs.readFileSync("package.json", "utf8");
let framework = null;
if (package.includes("heroicons/react")) {
console.error("Detected heroicons/react...");
framework = "react";
} else if (package.includes("heroicons/vue")) {
console.error("Detected heroicons/vue...");
framework = "vue";
} else {
console.error(
"It doesn't look like you have either the heroicons/react or heroicons/vue libraries installed in this project."
);
process.exit(1);
}
if (fs.existsSync("yarn.lock")) {
console.error("Detected yarn. Updating heroicons package to latest...");
console.log(`yarn add @heroicons/${framework}@latest`);
} else if (fs.existsSync("package-lock.json")) {
console.error("Detected npm. Updating heroicons package to latest...");
console.log(`npm install @heroicons/${framework}@latest`);
} else {
console.error(
"Error: cannot find evidence of yarn or npm. Please run either 'npm install' or 'yarn install' before using this script."
);
process.exit(1);
}
function gsub(from, to) {
console.log(`echo "${from} => ${to}"`);
console.log(
`find -E . -type f -regex '.*\.(js|jsx|ts|tsx|vue)' -not -path '*/\.*' -not -path '*/node_modules/*' -not -path 'migrateHeroicons.js' -exec sed -i '' -e 's|${from}|${to}|g' {} +`
);
}
console.log(`echo "Upgrading import statements..."`);
gsub(`@heroicons/${framework}/solid`, `@heroicons/${framework}/20/solid`);
gsub(`@heroicons/${framework}/outline`, `@heroicons/${framework}/24/outline`);
const heroiconsV1toV2 = {
AdjustmentsIcon: "AdjustmentsVerticalIcon",
AnnotationIcon: "ChatBubbleBottomCenterTextIcon",
ArchiveIcon: "ArchiveBoxIcon",
ArrowCircleDownIcon: "ArrowDownCircleIcon",
ArrowCircleLeftIcon: "ArrowLeftCircleIcon",
ArrowCircleRightIcon: "ArrowRightCircleIcon",
ArrowCircleUpIcon: "ArrowUpCircleIcon",
ArrowNarrowDownIcon: "ArrowLongDownIcon",
ArrowNarrowLeftIcon: "ArrowLongLeftIcon",
ArrowNarrowRightIcon: "ArrowLongRightIcon",
ArrowNarrowUpIcon: "ArrowLongUpIcon",
ArrowsExpandIcon: "ArrowsPointingOutIcon",
ArrowSmDownIcon: "ArrowSmallDownIcon",
ArrowSmLeftIcon: "ArrowSmallLeftIcon",
ArrowSmRightIcon: "ArrowSmallRightIcon",
ArrowSmUpIcon: "ArrowSmallUpIcon",
BadgeCheckIcon: "CheckBadgeIcon",
BanIcon: "NoSymbolIcon",
BookmarkAltIcon: "BookmarkSquareIcon",
CashIcon: "BanknotesIcon",
ChartSquareBarIcon: "ChartBarSquareIcon",
ChatAlt2Icon: "ChatBubbleLeftRightIcon",
ChatAltIcon: "ChatBubbleLeftEllipsisIcon",
ChatIcon: "ChatBubbleOvalLeftEllipsisIcon",
ChipIcon: "CpuChipIcon",
ClipboardCheckIcon: "ClipboardDocumentCheckIcon",
ClipboardCopyIcon: "ClipboardDocumentIcon",
ClipboardListIcon: "ClipboardDocumentListIcon",
CloudDownloadIcon: "CloudArrowDownIcon",
CloudUploadIcon: "CloudArrowUpIcon",
CodeIcon: "CodeBracketIcon",
CollectionIcon: "RectangleStackIcon",
ColorSwatchIcon: "SwatchIcon",
CursorClickIcon: "CursorArrowRaysIcon",
DatabaseIcon: "CircleStackIcon",
DesktopComputerIcon: "ComputerDesktopIcon",
DeviceMobileIcon: "DevicePhoneMobileIcon",
DocumentAddIcon: "DocumentPlusIcon",
DocumentDownloadIcon: "DocumentArrowDownIcon",
DocumentRemoveIcon: "DocumentMinusIcon",
DocumentReportIcon: "DocumentChartBarIcon",
DocumentSearchIcon: "DocumentMagnifyingGlassIcon",
DotsCircleHorizontalIcon: "EllipsisHorizontalCircleIcon",
DotsHorizontalIcon: "EllipsisHorizontalIcon",
DotsVerticalIcon: "EllipsisVerticalIcon",
DownloadIcon: "ArrowDownTrayIcon",
DuplicateIcon: "Square2StackIcon",
EmojiHappyIcon: "FaceSmileIcon",
EmojiSadIcon: "FaceFrownIcon",
ExclamationIcon: "ExclamationTriangleIcon",
ExternalLinkIcon: "ArrowTopRightOnSquareIcon",
EyeOffIcon: "EyeSlashIcon",
FastForwardIcon: "ForwardIcon",
FilterIcon: "FunnelIcon",
FolderAddIcon: "FolderPlusIcon",
FolderDownloadIcon: "FolderArrowDownIcon",
FolderRemoveIcon: "FolderMinusIcon",
GlobeIcon: "GlobeAmericasIcon",
HandIcon: "HandRaisedIcon",
InboxInIcon: "InboxArrowDownIcon",
LibraryIcon: "BuildingLibraryIcon",
LightningBoltIcon: "BoltIcon",
LocationMarkerIcon: "MapPinIcon",
LoginIcon: "ArrowLeftOnRectangleIcon",
LogoutIcon: "ArrowRightOnRectangleIcon",
MailIcon: "EnvelopeIcon",
MailOpenIcon: "EnvelopeOpenIcon",
MenuAlt1Icon: "Bars3CenterLeftIcon",
MenuAlt2Icon: "Bars3BottomLeftIcon",
MenuAlt3Icon: "Bars3BottomRightIcon",
MenuAlt4Icon: "Bars2Icon",
MenuIcon: "Bars3Icon",
MinusSmIcon: "MinusSmallIcon",
MusicNoteIcon: "MusicalNoteIcon",
OfficeBuildingIcon: "BuildingOfficeIcon",
PencilAltIcon: "PencilSquareIcon",
PhoneIncomingIcon: "PhoneArrowDownLeftIcon",
PhoneMissedCallIcon: "PhoneXMarkIcon",
PhoneOutgoingIcon: "PhoneArrowUpRightIcon",
PhotographIcon: "PhotoIcon",
PlusSmIcon: "PlusSmallIcon",
PuzzleIcon: "PuzzlePieceIcon",
QrcodeIcon: "QrCodeIcon",
ReceiptTaxIcon: "ReceiptPercentIcon",
RefreshIcon: "ArrowPathIcon",
ReplyIcon: "ArrowUturnLeftIcon",
RewindIcon: "BackwardIcon",
SaveAsIcon: "ArrowDownOnSquareStackIcon",
SaveIcon: "ArrowDownOnSquareIcon",
SearchCircleIcon: "MagnifyingGlassCircleIcon",
SearchIcon: "MagnifyingGlassIcon",
SelectorIcon: "ChevronUpDownIcon",
SortAscendingIcon: "BarsArrowUpIcon",
SortDescendingIcon: "BarsArrowDownIcon",
SpeakerphoneIcon: "MegaphoneIcon",
StatusOfflineIcon: "SignalSlashIcon",
StatusOnlineIcon: "SignalIcon",
SupportIcon: "LifebuoyIcon",
SwitchHorizontalIcon: "ArrowsRightLeftIcon",
SwitchVerticalIcon: "ArrowsUpDownIcon",
TableIcon: "TableCellsIcon",
TemplateIcon: "RectangleGroupIcon",
TerminalIcon: "CommandLineIcon",
ThumbDownIcon: "HandThumbDownIcon",
ThumbUpIcon: "HandThumbUpIcon",
TranslateIcon: "LanguageIcon",
TrendingDownIcon: "ArrowTrendingDownIcon",
TrendingUpIcon: "ArrowTrendingUpIcon",
UploadIcon: "ArrowUpTrayIcon",
UserAddIcon: "UserPlusIcon",
UserRemoveIcon: "UserMinusIcon",
ViewBoardsIcon: "ViewColumnsIcon",
ViewGridAddIcon: "SquaresPlusIcon",
ViewGridIcon: "Squares2X2Icon",
ViewListIcon: "Bars4Icon",
VolumeOffIcon: "SpeakerXMarkIcon",
VolumeUpIcon: "SpeakerWaveIcon",
XIcon: "XMarkIcon",
ZoomInIcon: "MagnifyingGlassPlusIcon",
ZoomOutIcon: "MagnifyingGlassMinusIcon",
};
console.log(`echo "Upgrading icon names..."`);
Object.entries(heroiconsV1toV2).map(([from, to]) => {
gsub(from, to);
});
console.log(
`echo "Done. You can thank https://twitter.com/cgenco and https://twitter.com/KevinPicchi for saving you so much time :)"`
);
@ebisbe
Copy link

ebisbe commented Nov 17, 2022

For vue I had to swap on line 43 -path '*.js' to -path '*.vue'.
Edit: gsub('@heroicons/${framework}/outline', '@heroicons/${framework}/20/outline'); should be gsub('@heroicons/${framework}/outline', '@heroicons/${framework}/24/outline');

@christiangenco
Copy link
Author

@ebisbe Updated! Thanks.

@oleksandr-shubin
Copy link

Had to input node processor into the pipeline on linux:

curl https://gist.githubusercontent.com/christiangenco/470a99f4823ee81f2b22bad83119f599/raw/migrateHeroicons.js | node | bash

@ebisbe
Copy link

ebisbe commented Nov 22, 2022

@oleksandr-shubin I had too but just downloaded the file and executed it locally as I was not sure to achieve the same result

@christiangenco
Copy link
Author

@oleksandr-shubin Oh oops—that should be there for every OS. Fixed! Thanks.

@jemikanegara
Copy link

I think the script will be better if it could automatically target jsx, ts & tsx too

@himynameisubik
Copy link

#165 should be a upper case X and not lower case
ViewGridIcon: "Squares2X2Icon",

Else, handy little script. Thanks a lot!

@christiangenco
Copy link
Author

@jemikanegara Updated to automatically target jsx, ts, and tsx too!

@himynameisubik Good catch. Fixed!

@amerritt14
Copy link

amerritt14 commented Jun 8, 2023

This is amazing!
One thing I noticed is that V2 has a CogIcon but it looks significantly different from V1.
If you want to match the same SVG as V1, You would need to map CogIcon: "Cog8ToothIcon"

Thanks so much!

@imam2nd
Copy link

imam2nd commented Oct 24, 2023

Amazing! Thank you so much for your efforts. I really appreciate it.

@clarkmu
Copy link

clarkmu commented Mar 10, 2024

Nice execution. Thanks

@NicoDMTX
Copy link

NicoDMTX commented Mar 29, 2024

Hello, you could add to your script at line 33

else if (fs.existsSync("pnpm-lock.yaml")) {
  console.error("Detected pnpm. Updating heroicons package to latest...");
  console.log(`pnpm install @heroicons/${framework}@latest`);

I use pnpm in my app and had to change this to make it works

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment