Skip to content

Instantly share code, notes, and snippets.

@ErikBernskiold
Created October 18, 2023 14:33
Show Gist options
  • Save ErikBernskiold/fd98a87a211593db5dcc94c9c7f9f794 to your computer and use it in GitHub Desktop.
Save ErikBernskiold/fd98a87a211593db5dcc94c9c7f9f794 to your computer and use it in GitHub Desktop.
Heroicons V2 Upgrade Command
<?php
namespace App\Console\Commands;
use Closure;
use Illuminate\Console\Command;
use Illuminate\Filesystem\FilesystemAdapter;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Storage;
class HeroiconsUpgrade extends Command
{
protected $signature = 'heroicons-upgrade';
protected $description = 'Upgrades Heroicons from V1 to V2, replacing all the old icon names with new.';
protected array $map = [
'adjustments' => 'adjustments-vertical',
'annotation' => 'chat-bubble-bottom-center-text',
'archive' => 'archive-box',
'arrow-circle-down' => 'arrow-down-circle',
'arrow-circle-left' => 'arrow-left-circle',
'arrow-circle-right' => 'arrow-right-circle',
'arrow-circle-up' => 'arrow-up-circle',
'arrow-narrow-down' => 'arrow-long-down',
'arrow-narrow-left' => 'arrow-long-left',
'arrow-narrow-right' => 'arrow-long-right',
'arrow-narrow-up' => 'arrow-long-up',
'arrow-sm-left' => 'arrow-small-left',
'arrow-sm-right' => 'arrow-small-right',
'arrow-sm-up' => 'arrow-small-up',
'arrow-sm-down' => 'arrow-small-down',
'arrows-expand' => 'arrows-pointing-out',
'badge-check' => 'check-badge',
'ban' => 'no-symbol',
'bookmark-alt' => 'bookmark-square',
'cash' => 'banknotes',
'chart-square-bar' => 'chart-bar-square',
'chat-alt-2' => 'chat-bubble-left-right',
'chat-alt' => 'chat-bubble-left-ellipsis',
'chat' => 'chat-bubble-oval-left-ellipsis',
'chip' => 'cpu-chip',
'clipboard-check' => 'clipboard-document-check',
'clipboard-copy' => 'clipboard-document',
'clipboard-list' => 'clipboard-document-list',
'cloud-download' => 'cloud-arrow-down',
'cloud-upload' => 'cloud-arrow-up',
'code' => 'code-bracket',
'collection' => 'rectangle-stack',
'color-swatch' => 'swatch',
'cursor-click' => 'cursor-arrow-rays',
'database' => 'circle-stack',
'desktop-computer' => 'computer-desktop',
'device-mobile' => 'device-phone-mobile',
'document-add' => 'document-plus',
'document-download' => 'document-arrow-down',
'document-remove' => 'document-minus',
'document-report' => 'document-chart-bar',
'document-search' => 'document-magnifying-glass',
'dots-circle-horizontal' => 'ellipsis-horizontal-circle',
'dots-horizontal' => 'ellipsis-horizontal',
'dots-vertical' => 'ellipsis-vertical',
'download' => 'arrow-down-tray',
'duplicate' => 'square-2-stack',
'emoji-happy' => 'face-smile',
'emoji-sad' => 'face-frown',
'external-link' => 'arrow-top-right-on-square',
'exclamation' => 'exclamation-triangle',
'eye-off' => 'eye-slash',
'fast-forward' => 'forward',
'filter' => 'funnel',
'folder-add' => 'folder-plus',
'folder-download' => 'folder-arrow-down',
'folder-remove' => 'folder-minus',
'globe' => 'globe-americas',
'hand' => 'hand-raised',
'inbox-in' => 'inbox-arrow-down',
'library' => 'building-library',
'lightning-bolt' => 'bolt',
'location-marker' => 'map-pin',
'login' => 'arrow-left-on-rectangle',
'logout' => 'arrow-right-on-rectangle',
'mail-open' => 'envelope-open',
'mail' => 'envelope',
'menu-alt-1' => 'bars-3-center-left',
'menu-alt-2' => 'bars-3-bottom-left',
'menu-alt-3' => 'bars-3-bottom-right',
'menu-alt-4' => 'bars-2',
'menu' => 'bars-3',
'minus-sm' => 'minus-small',
'music-note' => 'musical-note',
'office-building' => 'building-office',
'pencil-alt' => 'pencil-square',
'phone-incoming' => 'phone-arrow-down-left',
'phone-missed-call' => 'phone-x-mark',
'phone-outgoing' => 'phone-arrow-up-right',
'photograph' => 'photo',
'plus-sm' => 'plus-small',
'puzzle' => 'puzzle-piece',
'qrcode' => 'qr-code',
'receipt-tax' => 'receipt-percent',
'refresh' => 'arrow-path',
'reply' => 'arrow-uturn-left',
'rewind' => 'backward',
'save-as' => 'arrow-down-on-square-stack',
'save' => 'arrow-down-on-square',
'search-circle' => 'magnifying-glass-circle',
'search' => 'magnifying-glass',
'selector' => 'chevron-up-down',
'sort-ascending' => 'bars-arrow-up',
'sort-descending' => 'bars-arrow-down',
'speakerphone' => 'megaphone',
'status-offline' => 'signal-slash',
'status-online' => 'signal',
'support' => 'lifebuoy',
'switch-horizontal' => 'arrows-right-left',
'switch-vertical' => 'arrows-up-down',
'table' => 'table-cells',
'template' => 'rectangle-group',
'terminal' => 'command-line',
'thumb-down' => 'hand-thumb-down',
'thumb-up' => 'hand-thumb-up',
'translate' => 'language',
'trending-down' => 'arrow-trending-down',
'trending-up' => 'arrow-trending-up',
'upload' => 'arrow-up-tray',
'user-add' => 'user-plus',
'user-remove' => 'user-minus',
'view-boards' => 'view-columns',
'view-grid-add' => 'squares-plus',
'view-grid' => 'squares-2x2',
'view-list' => 'bars-4',
'volume-off' => 'speaker-x-mark',
'volume-up' => 'speaker-wave',
'x' => 'x-mark',
'zoom-in' => 'magnifying-glass-plus',
'zoom-out' => 'magnifying-glass-minus',
];
public function handle()
{
$this->patternReplacement(
pattern: '/heroicon-s-([a-z-0-9]+)/',
replacement: function ($matches) {
// If the icon name isn't in the map, we'll just return the original.
if (!isset($this->map[$matches[1]])) {
return $matches[0];
}
return "heroicon-s-{$this->map[$matches[1]]}";
}
);
$this->patternReplacement(
pattern: '/heroicon-o-([a-z-0-9]+)/',
replacement: function ($matches) {
// If the icon name isn't in the map, we'll just return the original.
if (!isset($this->map[$matches[1]])) {
return $matches[0];
}
return "heroicon-s-{$this->map[$matches[1]]}";
}
);
}
public function patternReplacement(
$pattern,
$replacement,
$directories = 'resources/views',
$files = [],
$mode = 'auto'
)
{
// If the mode is auto, we'll just get all the files in the directories
if ($mode === 'auto') {
$files = collect(Arr::wrap($directories))->map(function ($directory) {
return collect($this->filesystem()->allFiles($directory))->map(function ($path) {
return [
'path' => $path,
'content' => $this->filesystem()->get($path),
];
});
})->flatten(1);
}
// If the mode is manual, we'll just use the files passed in
if ($mode === 'manual') {
$files = collect(Arr::wrap($files))->map(function ($path) {
return [
'path' => $path,
'content' => $this->filesystem()->get($path),
];
});
}
return $files->map(function ($file) use ($pattern, $replacement) {
if ($replacement instanceof Closure) {
$file['content'] = preg_replace_callback($pattern, $replacement, $file['content'], -1, $count);
} else {
$file['content'] = preg_replace($pattern, $replacement, $file['content'], -1, $count);
}
$file['occurrences'] = $count;
return $count > 0 ? $file : null;
})
->filter()
->values()
->map(function ($file) {
$this->filesystem()->put($file['path'], $file['content']);
return [
$file['path'], $file['occurrences'],
];
});
}
public function filesystem(): FilesystemAdapter
{
return Storage::build([
'driver' => 'local',
'root' => base_path(),
]);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment