Skip to content

Instantly share code, notes, and snippets.

@selftaught
Last active August 29, 2023 03:00
Show Gist options
  • Save selftaught/b5ce3c0ef6a4015563dff42972bbd403 to your computer and use it in GitHub Desktop.
Save selftaught/b5ce3c0ef6a4015563dff42972bbd403 to your computer and use it in GitHub Desktop.
#!/usr/bin/env perl
# This can be used as part of git pre-commit hooks without the need to install deps
# because FindBin and File::Find are core perl. We use this in .husky/pre-commit.
# This runs on Mac OS, Linux, and WSL
use strict;
use warnings;
use feature 'say';
use FindBin qw($Bin);
use File::Find;
#use Data::Dump qw(dump);
sub write_file {
my ($file, $data) = @_;
open my $fh, '>', $file or die "$!\n";
print $fh $data;
close $fh;
}
sub unbarrel_imports {
my ($src_dir, $from_pattern) = @_;
my @files = ();
die "Missing src_dir parameter!\n" unless $src_dir;
die "Missing from_pattern parameter!\n" unless $from_pattern;
find(sub {
return unless -f;
return unless /\.(js|ts)x?/;
push @files, $File::Find::name;
}, $src_dir);
foreach my $file (@files) {
my $source = do {
local $/ = undef;
open my $fh, '<', $file or die "$!\n";
<$fh>;
};
while ($source =~ /(import\s*{([^}]+)}\s+from ['"]([^'"]+)['"];)/sg) {
my $import = $1;
my $component = $2;
my $from = $3;
next unless $from =~ /$from_pattern/;
$component =~ s/\s//g;
my @components = split /,/, $component;
my $replace = '';
foreach (@components) {
$replace .= "import $_ from '$from/$_';\n";
}
my $search = quotemeta $import;
$source =~ s/$search/$replace/gm;
}
write_file $file, $source;
}
}
# We have this script in a bin directory, in the root of a repo.
# Our JS source is in a directory 'src', also in the root of the repo.
# $Bin is the directory you store the script in.. and the src directory is found
# relative to that. Update ../src to where ever your source lives relative to
# where you put the script.
my $src_dir = "$Bin/../src";
if (my $from_pattern = shift @ARGV) {
unbarrel_imports $src_dir, qr/$from_pattern/;
}
else {
unbarrel_imports $src_dir, qr/\@mui\/(icon-)?material/;
}
# Converts barrel imports in \.jsx?|\.tsx? src files:
# import { Alert, AlertTitle, Button } from '@mui/material'
# Into direct imports:
# import Alert from '@mui/material/Alert';
# import AlertTitle from '@mui/material/AlertTitle';
# import Button from '@mui/material/Button';
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment