Skip to content

Instantly share code, notes, and snippets.

@agius
Created January 12, 2016 19:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save agius/d9e7f36565e5d55ffb0d to your computer and use it in GitHub Desktop.
Save agius/d9e7f36565e5d55ffb0d to your computer and use it in GitHub Desktop.
Scan your node_modules directory and report on how many Planck-scale JS libraries you have
=begin
PlanckJS - or: why the FUCK do you have 700+ dependencies?
Planck-scale libraries are not just microlibraries, they're even BETTER! They're so micro
they're beyond nanolibraries. They have _more boilerplate code than actual code!_ So composable.
Such Unix philosophy. Wow.
Back in my day, we called these things "functions" and put them in our code, rather than
descending into package-management hell with a broken tool like npm.
usage:
1. gem install terminal-table
2. gem install colorize
3. navigate to directory of choice
4. run npm install
5. run ruby planckjs.rb
=end
require 'json'
require 'fileutils'
require 'terminal-table'
require 'colorize'
# stolen from
# http://codereview.stackexchange.com/questions/9107/printing-human-readable-number-of-bytes
UNITS = %W(B KiB MiB GiB TiB).freeze
def as_size(number)
if number.to_i < 1024
exponent = 0
else
max_exp = UNITS.size - 1
exponent = ( Math.log( number ) / Math.log( 1024 ) ).to_i # convert to base
exponent = max_exp if exponent > max_exp # we need this to avoid overflow for the highest unit
number /= 1024 ** exponent
end
"#{number} #{UNITS[ exponent ]}"
end
BOILERPLATE = [
# human files every repo has
/LICENSE/, /README/, /CONTRIBUTING/, /CNAME/, /CHANGELOG/, /CODE_OF_CONDUCT/, /PATRONS/,
/AUTHORS/, /FEATURES/, /STYLEGUIDE/, /VERSION/,
# packaging systems
/package\.json/, /bower\.json/, /composer\.json/, /package\.js/, /package\.json/,
/features\.json/, /testem\.json/, /yuidoc\.json/,
# configs
/\.git$/, /_config\.yml$/, /\.babelrc/, /\.eslint/, /\.editorconfig/, /\.bowerrc/,
/\.jshint/, /\.jscsrc/,
# ci systems
/\.travis/, /\.hound/,
# build systems
/Gruntfile/, /Gulpfile/i, /webpack\.config/, /brunch-config/, /Rakefile/,
]
def files_for_dir(path, options = {})
Dir[path].reject do |p|
['..', '.'].include?(p) ||
(options[:dirs] == false && File.ftype(p) == 'directory')
end
end
def planck_stats(path)
boilerplate, actual = [0, 0]
files = files_for_dir File.join(path, '**', '*'), dirs: false
files.each do |file|
# ignore node_modules/package/node_modules/**/*
# wtf why do I even need this?
next if file =~ /.+\/node_modules\/.*/
if BOILERPLATE.any? {|regex| file =~ regex }
boilerplate += File.new(path).size
else
actual += File.new(path).size
end
end
[path.split('/').last,
as_size(boilerplate),
as_size(actual),
is_planck?(boilerplate, actual)]
end
def is_planck?(boilerplate, actual)
if boilerplate > actual
"yes".colorize(:red)
else
"no".colorize(:green)
end
end
def planck_modules(dir, limit = nil)
paths = files_for_dir File.join(dir, '*')
paths = paths.first(limit) if limit
paths.each_with_object([]) do |path, modules|
modules << planck_stats(path)
end
end
def print_modules(modules)
tt = Terminal::Table.new title: "Planck-Scale JS Libraries (boilerplate code > actual code)",
headings: ['Module', 'boilerplate', 'actual', 'planck-scale?'],
rows: modules
puts tt
total_plack = modules.reject {|m| m.last =~ /no/ }.count
puts "total: #{modules.count} | planck-scale: #{total_plack} "
end
print_modules planck_modules('node_modules')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment