practical-pig 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 65939a635abedfb99cbe01747fdf1c04d8ab6cb0c774b49b2749d9d35ffc763b
4
+ data.tar.gz: 813c4cc9234e4819e10984645e51d8b9d12f53980817376d1f325ed152b4c44f
5
+ SHA512:
6
+ metadata.gz: 3c7c147073f21a667ade272446ef0c4b6dfd125072b1d4aca85240e89cbd1a55b14a48030f6ab22ccb05dea932c069a93ba9b5f334e7971c3c185636ec887d17
7
+ data.tar.gz: 1db1a0657bedd4ff3f0ff48ab0db7f39ef8408370ab95f3bbd5ad0d6e84ae89f454eb32c480f91b15045fa1a67396029ba6e447004d024c166b15b9e663a7a64
@@ -0,0 +1,12 @@
1
+ /tmp/
2
+ **/log
3
+ **/*.log
4
+
5
+ Gemfile.lock
6
+ **/pnpm-lock.yaml
7
+
8
+ **/*.gem
9
+ gemfiles/vendor
10
+ .bundle
11
+
12
+ /test
@@ -0,0 +1,24 @@
1
+ #
2
+ # RuboCop is a Ruby static code analyzer and code formatter that tries to enforce many of
3
+ # the guidelines outlined in the community Ruby and Rails
4
+ # style guides.
5
+ #
6
+ # https://docs.rubocop.org/en/latest/
7
+ # https://rubystyle.guide/
8
+ # https://rails.rubystyle.guide/
9
+ inherit_from: rubocop-base.yaml
10
+ inherit_mode:
11
+ merge:
12
+ - Include
13
+ - Exclude
14
+ - IgnoredMethods
15
+ - AllowedMethods
16
+
17
+ AllCops:
18
+ Exclude:
19
+ - "test/**/*"
20
+
21
+ Metrics/AbcSize:
22
+ IgnoredMethods:
23
+ - new
24
+ - generate
@@ -0,0 +1,47 @@
1
+ language: ruby
2
+ dist: bionic
3
+ os:
4
+ - linux
5
+ - osx
6
+
7
+ cache:
8
+ bundler: true
9
+ npm: true
10
+ directories:
11
+ - "~/.pnpm-store"
12
+ rvm:
13
+ - 2.4.10
14
+ - 2.5.5
15
+ - 2.6.5
16
+ - 2.7.0
17
+ - ruby-head
18
+ gemfile:
19
+ - gemfiles/Gemfile-rails.5.2.x
20
+ - gemfiles/Gemfile-rails.6.0.x
21
+
22
+ addons:
23
+ homebrew:
24
+ packages:
25
+ - postgresql
26
+
27
+ before_install:
28
+ - gem install rubygems-update && update_rubygems
29
+ - yes | rvm @global do gem install bundler -v 2.1.4 || true
30
+ - nvm install --lts
31
+ - curl -L https://raw.githubusercontent.com/pnpm/self-installer/master/install.js | node
32
+ - pnpm config set store-dir ~/.pnpm-store
33
+ - bundle config set path 'vendor/bundle'
34
+ install:
35
+ - bundle install --jobs 3 --retry 3
36
+ - pnpm install --frozen-lockfile
37
+ script:
38
+ - bundle exec rubocop
39
+ - bundle exec ruby ./bin/pig new test/test_app
40
+
41
+ jobs:
42
+ fast_finish: true
43
+ allow_failures:
44
+ - rvm: ruby-head
45
+ exclude:
46
+ - rvm: 2.4.10
47
+ gemfile: gemfiles/Gemfile-rails.6.0.x
@@ -0,0 +1,16 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on Keep a Changelog (<https://keepachangelog.com/en/1.0.0/>). This project adheres to Semantic Versioning (<https://semver.org/spec/v2.0.0.html>).
6
+
7
+ ## [v1.0.0] - 2020-05-23
8
+
9
+ ### Added
10
+
11
+ - Gem specifications and foundational files, generated by Bundler v2.1.4, for defining a Ruby gem.
12
+ - `pig` command for invoking `PracticalPig::CLI` methods.
13
+ - `new` CLI command for generating Practical Pig-based Rails applications, based on `rails new`.
14
+ - Sparse application template with pre-configured gem and Webpacker environments (using `webpacker-pnpm`).
15
+ - Exposed RuboCop config for use in dependent gems.
16
+ - Travis config for CLI and environment testing.
data/Gemfile ADDED
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ source "https://rubygems.org"
4
+ gemspec
5
+
6
+ install_if -> { Gem.win_platform? } do
7
+ gem "tzinfo-data"
8
+ end
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2020 Elias Gabriel
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,62 @@
1
+ # practical-pig
2
+
3
+ [![version](https://img.shields.io/gem/v/practical-pig?label=version&style=flat-square)](https://rubygems.org/gems/practical-pig)
4
+ [![status](https://img.shields.io/travis/thearchitector/practical-pig?style=flat-square)](https://travis-ci.org/github/thearchitector/practical-pig)
5
+ [![downloads](https://img.shields.io/gem/dt/practical-pig?style=flat-square)](https://rubygems.org/gems/practical-pig)
6
+ [![license](https://img.shields.io/badge/license-MIT-green?style=flat-square)](./LICENSE)
7
+
8
+ Practical Pig is an opinionated Ruby on Rails template that makes use of webpacker-pnpm, RuboCop, and Prettier to provide a simple yet robust foundation for any web application.
9
+
10
+ ## Features
11
+
12
+ - Opinionated so you don't have to deal with the nitty-gritty
13
+ - Provides production-ready application templates
14
+ - Agnostic of underlying Rails version
15
+
16
+ ## Installation and Usage
17
+
18
+ Assuming you have `pnpm` installed, simply download the gem to your system and then create a new repository as you would using `rails`.
19
+
20
+ ```sh
21
+ $ gem install practical-pig
22
+ $ pig new APP_PATH
23
+ ```
24
+
25
+ To view the help dialog, you may run `pig help new`, which will yield the following output:
26
+
27
+ ```plaintext
28
+ Usage:
29
+ pig new APP_PATH
30
+
31
+ Options:
32
+ -q, [--quiet], [--no-quiet] # Suppress status output
33
+ [--with-hmr], [--no-with-hmr] # Install Webpack HMR development server
34
+
35
+ Description:
36
+ `pig new` will generate a new Ruby on Rails application and modify it to adhere
37
+ to Practical Pig's application design guidelines.
38
+
39
+ The APP_PATH you provide will be used as the path of the application during
40
+ creation, with its name being the basename (last part of the path). In every
41
+ case, the new application will be generated relative to the current working
42
+ directory (where you execute this command).
43
+
44
+ By design, your application name must start and end with an alphanumeric
45
+ character.
46
+
47
+ This command makes use of `rails new` under the hood but does not accept any
48
+ generator options.
49
+ ```
50
+
51
+ ## License
52
+
53
+ MIT License
54
+
55
+ Copyright (c) 2020 Elias Gabriel
56
+
57
+ Permission is hereby granted, free of charge, to any person obtaining a copy
58
+ of this software and associated documentation files (the "Software"), to deal
59
+ in the Software without restriction, including without limitation the rights
60
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
61
+ copies of the Software, and to permit persons to whom the Software is
62
+ furnished to do so, subject to the conditions outlined in [LICENSE](./LICENSE).
data/bin/pig ADDED
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ git_path = File.expand_path("../.git", __dir__)
5
+
6
+ if File.exist?(git_path)
7
+ railties_path = File.expand_path("../lib", __dir__)
8
+ $:.unshift(railties_path)
9
+ end
10
+
11
+ require "practical/pig/cli"
12
+ PracticalPig::CLI.start(ARGV)
@@ -0,0 +1,9 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec path: "../"
4
+
5
+ gem "rails", "~> 5.2.0"
6
+ gem "rake", ">= 11.1"
7
+ gem "rack-proxy", require: false
8
+ gem "minitest", "~> 5.0"
9
+ gem "byebug"
@@ -0,0 +1,9 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec path: "../"
4
+
5
+ gem "rails", "~> 6.0.0.rc2"
6
+ gem "rake", ">= 11.1"
7
+ gem "rack-proxy", require: false
8
+ gem "minitest", "~> 5.0"
9
+ gem "byebug"
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "pig/version"
4
+ require_relative "pig/cli"
@@ -0,0 +1,144 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "thor"
4
+ require "rails/gem_version"
5
+ require "active_support/core_ext/string/filters"
6
+ require "active_support/core_ext/string/inflections"
7
+
8
+ require "etc"
9
+ require "bundler"
10
+
11
+ module PracticalPig
12
+ class CLI < Thor
13
+ include Thor::Actions
14
+
15
+ NAME_PATTERN = /^[a-z].*[a-z0-9]$/i.freeze
16
+ private_constant :NAME_PATTERN
17
+
18
+ attr_accessor :app_name
19
+
20
+ desc "new APP_PATH", "Generates a Practical Pig Rails application template."
21
+ long_desc <<~HEREDOC
22
+ `pig new` will generate a new Ruby on Rails application and modify it
23
+ to adhere to Practical Pig's application design guidelines.
24
+
25
+ The APP_PATH you provide will be used as the path of the application during
26
+ creation, with its name being the basename (last part of the path). In every
27
+ case, the new application will be generated relative to the current working
28
+ directory (where you execute this command).
29
+
30
+ By design, your application name must start and end with an alphanumeric character.
31
+
32
+ This command makes use of `rails new` under the hood but does not accept
33
+ any generator options.
34
+ HEREDOC
35
+ option :quiet, type: :boolean, aliases: "-q", desc: "Suppress status output"
36
+ option :with_hmr, type: :boolean, desc: "Install Webpack HMR development server"
37
+ def new(app_path)
38
+ # ensure that applications are not requests for help, or that their names follow the
39
+ # appropriate format
40
+ if Thor::HELP_MAPPINGS.include?(app_path) || (flag = !app_path.match?(NAME_PATTERN))
41
+ if flag
42
+ say <<~MSG.squish
43
+ \e[31mBy design, your application name must start and end with an alphanumeric
44
+ character.\e[0m
45
+ MSG
46
+ say
47
+ end
48
+
49
+ help("new")
50
+ return
51
+ end
52
+
53
+ # generate a Rails application, omitting many things
54
+ run(
55
+ <<~CMD.squish
56
+ rails new #{app_path} -GMPCSJB --database=postgresql --skip-gemfile --skip-keeps
57
+ #{" --quiet" if options[:quiet]} --skip-action-mailbox --skip-system-test
58
+ --skip-action-text --skip-active-storage --skip-turbolinks
59
+ CMD
60
+ )
61
+
62
+ app_root = File.join(Dir.pwd, app_path)
63
+ @app_name = File.basename(app_root)
64
+
65
+ generate(app_root)
66
+ end
67
+
68
+ def self.source_root
69
+ File.join(__dir__, "../../template")
70
+ end
71
+
72
+ def self.exit_on_failure?
73
+ true
74
+ end
75
+
76
+ private
77
+
78
+ def generate(app_root)
79
+ # copy all files from PP's template app, evaluating ERBs and forcing
80
+ # file overwrites
81
+ directory(".", app_root, force: true)
82
+
83
+ inside(app_root) do
84
+ remove_file("app/assets/config")
85
+ remove_file("app/assets/stylesheets/application.css")
86
+ remove_file("app/views/layouts/application.html.erb")
87
+
88
+ # concurrently install all JS dependencies using pnpm
89
+ run("pnpm i --child-concurrency=#{Etc.nprocessors}", capture: options[:quiet])
90
+ run("pnpm add webpack-dev-server --save-dev") if options[:with_hmr]
91
+
92
+ # get the system-wide Bundler gem and, within the local environment (application),
93
+ # concurrently install all Ruby gems. we do it in a separate bundler environment
94
+ # because we don't want cross-talk between pig and app dependencies
95
+ cmd = "#{Gem.ruby} #{Gem.bin_path("bundler", "bundle")}"
96
+ Bundler.with_unbundled_env do
97
+ run("#{cmd} install --jobs=#{Etc.nprocessors}", capture: options[:quiet])
98
+
99
+ # install Webpacker's binstubs
100
+ run("#{cmd} exec rake webpacker:binstubs", capture: options[:quiet])
101
+ remove_file("bin/webpack-dev-server") unless options[:with_hmr]
102
+ end
103
+ end
104
+
105
+ print_output
106
+ end
107
+
108
+ def print_output
109
+ # say a nice thing
110
+ if options[:quiet]
111
+ say <<~MSG.squish
112
+ \e[90mYour Practical Pig application (#{app_name}) was generated successfully
113
+ (and quietly)!\e[0m 🤫
114
+ MSG
115
+ else
116
+ say
117
+ say
118
+ say <<~MSG.squish
119
+ \e[32mHooray! Your Practical Pig application (#{app_name}) was generated
120
+ successfully!\e[0m 🥳
121
+ MSG
122
+ # because PP copies a static package.json and pnpm, it is possible that new
123
+ # applications will have an outdated version in their dependency list. to
124
+ # help mitigate that, output a message making users aware of the possibility
125
+ say <<~MSG
126
+ \e[90m> Your application's dependencies might be out of date.\e[0m
127
+ \e[90m> To safely update, run `bundle update --conservative` and `pnpm up`.\e[0m
128
+ \e[90m> To forcefully update, run `bundle update` and `pnpm up -L`.\e[0m
129
+ MSG
130
+ say
131
+ end
132
+ end
133
+
134
+ # https://github.com/rails/rails/blob/master/railties/lib/rails/generators/app_base.rb#L300-L311
135
+ def rails_version_specifier(gem_version = Rails.gem_version)
136
+ if gem_version.segments.size == 3 || gem_version.release.segments.size == 3
137
+ "~> #{gem_version}"
138
+ else
139
+ patch = gem_version.segments[0, 3].join(".")
140
+ "~> #{patch}\", \">= #{gem_version}"
141
+ end
142
+ end
143
+ end
144
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PracticalPig
4
+ VERSION = "1.0.0"
5
+
6
+ public_constant :VERSION
7
+ end
@@ -0,0 +1,2 @@
1
+ shamefully-hoist=true
2
+ resolution-strategy=fewer-dependencies
@@ -0,0 +1,25 @@
1
+ #
2
+ # RuboCop is a Ruby static code analyzer and code formatter that tries to enforce many of
3
+ # the guidelines outlined in the community Ruby and Rails
4
+ # style guides.
5
+ #
6
+ # https://docs.rubocop.org/en/latest/
7
+ # https://rubystyle.guide/
8
+ # https://rails.rubystyle.guide/
9
+ inherit_gem:
10
+ practical-pig: rubocop-base.yaml
11
+ inherit_mode:
12
+ merge:
13
+ - Include
14
+ - Exclude
15
+ - IgnoredMethods
16
+ - AllowedMethods
17
+
18
+ # cop-specific excludes are not inherited for some reason (likely a bug in RuboCop) so we
19
+ # need to manually re-omit the intended files and directories.
20
+ Layout/LineLength:
21
+ Exclude:
22
+ - "**/config/initializers/**/*"
23
+ Style/MethodCallWithArgsParentheses:
24
+ Exclude:
25
+ - "**/Gemfile"
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ source "https://rubygems.org"
4
+
5
+ ruby "<%= RUBY_VERSION %>"
6
+
7
+ gem "bootsnap", require: false # Speeds up loading of individual source files
8
+ gem "puma"
9
+ gem "rails", "<%= rails_version_specifier %>"
10
+ gem "slim-rails" # Replaces ERB templates with Slim templates
11
+ gem "webpacker"
12
+ gem "webpacker-pnpm" # Replaces Yarn with pnpm
13
+
14
+ install_if -> { Gem.win_platform? } do
15
+ gem "tzinfo-data" # Ensures the use of the latest timezone data
16
+ gem "wdm" # Enables the use of a better Windows file update monitor
17
+ end
18
+
19
+ require "rbconfig"
20
+ install_if -> { RbConfig::CONFIG["target_os"] =~ /bsd|dragonfly/i } do
21
+ gem "rb-kqueue" # Wraps BSD's notification interface to manage runtime processes
22
+ end
23
+
24
+ group :development, :test do
25
+ gem "dotenv-rails" # Allows loading ENV values from .env files
26
+ gem "practical-pig", require: false
27
+ gem "rubocop", "~> 0.83.0", require: false # Enables code analysis and linting
28
+ gem "rubocop-minitest", require: false
29
+ gem "rubocop-performance", require: false
30
+ gem "rubocop-rails", require: false
31
+ gem "spring" # Loads a pre-booted Rails process
32
+ end
33
+
34
+ group :development do
35
+ gem "annotate" # Annotates ActiveModel records with DB schemata
36
+ gem "listen"
37
+ gem "pry-rails" # Replaces IRB with pry in the rails console
38
+ gem "spring-watcher-listen" # Enables Spring to use Listen rather than fs polling
39
+ end
40
+
41
+ ##
42
+ ## App-specific Dependencies
43
+ ## (add all your application-specific gems below)
44
+ ##
45
+
46
+ # gem "devise"
47
+ gem "pg"
48
+ # gem "rack-cors"
@@ -0,0 +1,17 @@
1
+ // This file is automatically compiled by Webpack, along with any other files
2
+ // present in this directory. You're encouraged to place your actual application
3
+ // logic in a relevant structure within app/javascript and only use these pack
4
+ // files to reference that code so it'll be compiled.
5
+
6
+ // import 'core-js/stable'
7
+ // import 'regenerator-runtime/runtime'
8
+
9
+ // Uncomment to copy all static images under ../images to the output folder
10
+ // and reference them with the image_pack_tag helper in views or the
11
+ // `imagePath` JavaScript helper below.
12
+ //
13
+ // const images = require.context('../images', true)
14
+ // const imagePath = (name) => images(name, true)
15
+
16
+ import "../javascript/<%= app_name %>";
17
+ import "../stylesheets/<%= app_name %>";
@@ -0,0 +1,12 @@
1
+ doctype html
2
+ html lang="en"
3
+ head
4
+ title <%= app_name.titleize %>
5
+ = csrf_meta_tags
6
+ = csp_meta_tag
7
+
8
+ = stylesheet_pack_tag 'application', media: 'all'
9
+ = javascript_pack_tag 'application', defer: true
10
+
11
+ body
12
+ = yield
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ # path to your application root.
5
+ APP_ROOT = File.expand_path('..', __dir__)
6
+
7
+ def system!(*args)
8
+ system(*args) || abort("\n\e[31m== Command #{args} failed ==\e[0m")
9
+ end
10
+
11
+ Dir.chdir(APP_ROOT) do
12
+ puts "\e[36m\n== Running RuboCop static code formatter ==\e[0m"
13
+ system!("bundle exec rubocop -a")
14
+
15
+ puts "\e[36m\n== Running Prettier style formatter ==\e[0m"
16
+ system!("pnpm run format")
17
+ end
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ # path to your application root.
5
+ APP_ROOT = File.expand_path('..', __dir__)
6
+
7
+ def system!(*args)
8
+ system(*args) || abort("\n\e[31m== Command #{args} failed ==\e[0m")
9
+ end
10
+
11
+ Dir.chdir(APP_ROOT) do
12
+ puts "\e[36m\n== Running RuboCop static code analysis ==\e[0m"
13
+ system!("bundle exec rubocop -P")
14
+
15
+ puts "\e[36m\n== Running Prettier style check ==\e[0m"
16
+ system!("pnpm run lint")
17
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Define an application-wide content security policy.
4
+ #
5
+ # https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy.
6
+ Rails.application.config.content_security_policy do |policy|
7
+ policy.default_src(:none)
8
+ policy.connect_src(:self, :https)
9
+ policy.script_src(:self, :https)
10
+ policy.style_src(:self, Rails.env.development? ? :unsafe_inline : :https)
11
+ policy.form_action(:self, :https)
12
+ end
13
+
14
+ # If you are using UJS then enable automatic nonce generation
15
+ Rails.application.config.content_security_policy_nonce_generator = proc do
16
+ SecureRandom.base64(16)
17
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ Rails.application.config.generators do |g|
4
+ # Disable creation of default generators
5
+ g.stylesheets(false)
6
+ g.javascripts(false)
7
+ g.scaffold_stylesheet(false)
8
+
9
+ # Specify Slim as the templating engine
10
+ g.template_engine(:slim)
11
+ end
@@ -0,0 +1,9 @@
1
+ process.env.NODE_ENV = process.env.NODE_ENV || 'development'
2
+
3
+ const environment = require('./environment')
4
+ const webpack = require('webpack')
5
+
6
+ // enable automatic prefetching to speed incremental built times
7
+ environment.plugins.prepend('AutomaticPrefetch', new webpack.AutomaticPrefetchPlugin())
8
+
9
+ module.exports = environment.toWebpackConfig()
@@ -0,0 +1,13 @@
1
+ const { environment } = require('@rails/webpacker')
2
+ const webpack = require('webpack')
3
+
4
+ // ensure that we expose global variables
5
+ // environment.plugins.prepend('Provide', new webpack.ProvidePlugin({
6
+ // $: 'jquery',
7
+ // jQuery: 'jquery',
8
+ // }))
9
+
10
+ // disable source map emission
11
+ environment.config.merge({ devtool: 'none' })
12
+
13
+ module.exports = environment
@@ -0,0 +1,78 @@
1
+ process.env.NODE_ENV = process.env.NODE_ENV || 'production'
2
+
3
+ const environment = require('./environment')
4
+ const CompressionPlugin = require('compression-webpack-plugin');
5
+ const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin');
6
+ const TerserPlugin = require('terser-webpack-plugin');
7
+
8
+ // delete default webpacker optimization plugins since we want to
9
+ // replace them entirely not append to them
10
+ environment.plugins.delete('Compression')
11
+ environment.plugins.delete('Compression Brotli')
12
+ environment.plugins.delete('OptimizeCSSAssets')
13
+
14
+ // enable asset compression using brotli
15
+ environment.plugins.prepend('Compression', new CompressionPlugin({
16
+ filename: '[path].br[query]',
17
+ algorithm: 'brotliCompress',
18
+ cache: true,
19
+ test: /\.(js|css|html|json|ico|svg|eot|otf|ttf|map)$/,
20
+ compressionOptions: { level: 11 },
21
+ threshold: 0,
22
+ minRatio: 1,
23
+ deleteOriginalAssets: false
24
+ }))
25
+
26
+ // enable advanced css minification
27
+ environment.plugins.prepend('OptimizeCssAssets', new OptimizeCssAssetsPlugin({
28
+ cssProcessor: require('cssnano'),
29
+ cssProcessorPluginOptions: {
30
+ preset: ['advanced']
31
+ },
32
+ canPrint: false
33
+ }))
34
+
35
+ // enable js optimization and minification
36
+ environment.config.optimization = {
37
+ minimize: true,
38
+ minimizer: [
39
+ new TerserPlugin({
40
+ parallel: true,
41
+ cache: true,
42
+ sourceMap: false,
43
+ terserOptions: {
44
+ parse: { ecma: 8 },
45
+ compress: {
46
+ ecma: 6,
47
+ passes: 2,
48
+ drop_console: true,
49
+ arguments: true,
50
+ booleans_as_integers: true,
51
+ keep_fargs: false,
52
+ // enable "unsafe" optimizations - this is really only "unsafe" is your
53
+ // JS is written poorly making use of flawed logic and/or syntactical
54
+ // loopholes). if that's the case, its probably best that it not work
55
+ // anyway...
56
+ unsafe: true,
57
+ unsafe_arrows: true,
58
+ unsafe_comps: true,
59
+ unsafe_Function: true,
60
+ unsafe_math: true,
61
+ unsafe_symbols: true,
62
+ unsafe_methods: true,
63
+ unsafe_proto: true,
64
+ unsafe_regexp: true,
65
+ unsafe_undefined: true
66
+ },
67
+ output: {
68
+ ecma: 6,
69
+ comments: false,
70
+ ascii_only: true,
71
+ beautify: false
72
+ }
73
+ }
74
+ })
75
+ ]
76
+ }
77
+
78
+ module.exports = environment.toWebpackConfig()
@@ -0,0 +1,92 @@
1
+ # Note: You must restart bin/webpack-dev-server for changes to take effect
2
+
3
+ default: &default
4
+ source_path: app/assets
5
+ source_entry_path: packs
6
+ public_root_path: public
7
+ public_output_path: packs
8
+ cache_path: tmp/cache/webpacker
9
+ webpack_compile_output: true
10
+
11
+ # Additional paths webpack should lookup modules
12
+ # ['app/assets', 'engine/foo/app/assets']
13
+ additional_paths: []
14
+
15
+ # Reload manifest.json on all requests so we reload latest compiled packs
16
+ cache_manifest: false
17
+
18
+ # Extract and emit a css file
19
+ extract_css: false
20
+
21
+ static_assets_extensions:
22
+ - .jpg
23
+ - .jpeg
24
+ - .png
25
+ - .gif
26
+ - .tiff
27
+ - .ico
28
+ - .svg
29
+ - .eot
30
+ - .otf
31
+ - .ttf
32
+ - .woff
33
+ - .woff2
34
+
35
+ extensions:
36
+ - .mjs
37
+ - .js
38
+ - .sass
39
+ - .scss
40
+ - .css
41
+ - .module.sass
42
+ - .module.scss
43
+ - .module.css
44
+ - .png
45
+ - .svg
46
+ - .gif
47
+ - .jpeg
48
+ - .jpg
49
+
50
+ development:
51
+ <<: *default
52
+ compile: true
53
+
54
+ # Reference: https://webpack.js.org/configuration/dev-server/
55
+ dev_server:
56
+ https: false
57
+ host: localhost
58
+ port: 3035
59
+ public: localhost:3035
60
+ hmr: false
61
+ # Inline should be set to true if using HMR
62
+ inline: true
63
+ overlay: true
64
+ compress: true
65
+ disable_host_check: true
66
+ use_local_ip: false
67
+ quiet: false
68
+ pretty: false
69
+ headers:
70
+ 'Access-Control-Allow-Origin': '*'
71
+ watch_options:
72
+ ignored: '**/node_modules/**'
73
+
74
+
75
+ test:
76
+ <<: *default
77
+ compile: true
78
+
79
+ # Compile test packs to a separate directory
80
+ public_output_path: packs-test
81
+
82
+ production:
83
+ <<: *default
84
+
85
+ # Production depends on precompilation of packs prior to booting for performance.
86
+ compile: false
87
+
88
+ # Extract and emit a css file
89
+ extract_css: true
90
+
91
+ # Cache manifest.json for performance
92
+ cache_manifest: true
@@ -0,0 +1,24 @@
1
+ {
2
+ "name": "<%= app_name %>",
3
+ "version": "0.1.0",
4
+ "dependencies": {
5
+ "@rails/webpacker": "^5.1.1",
6
+ "compression-webpack-plugin": "^4.0.0",
7
+ "cssnano": "^4.1.10",
8
+ "cssnano-preset-advanced": "^4.0.7",
9
+ "optimize-css-assets-webpack-plugin": "^5.0.3",
10
+ "postcss-fail-on-warn": "^0.1.0",
11
+ "terser-webpack-plugin": "^3.0.1",
12
+ "webpack": "^4.43.0"
13
+ },
14
+ "devDependencies": {
15
+ "prettier": "^2.0.5"
16
+ },
17
+ "browserslist": [
18
+ "defaults"
19
+ ],
20
+ "scripts": {
21
+ "lint": "prettier --check app/assets/**/*",
22
+ "format": "prettier --check --write app/assets/**/*"
23
+ }
24
+ }
@@ -0,0 +1,8 @@
1
+ module.exports = {
2
+ plugins: [
3
+ require('postcss-import'),
4
+ require('postcss-flexbugs-fixes'),
5
+ require('autoprefixer'),
6
+ require('postcss-fail-on-warn')
7
+ ]
8
+ }
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ lib = File.expand_path("lib", __dir__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+ require "practical/pig/version"
6
+
7
+ Gem::Specification.new do |spec|
8
+ spec.name = "practical-pig"
9
+ spec.version = PracticalPig::VERSION
10
+ spec.author = "Elias Gabriel"
11
+ spec.email = "me@eliasfgabriel.com"
12
+ spec.homepage = "https://github.com/thearchitector/practical-pig"
13
+ spec.license = "MIT"
14
+
15
+ spec.summary = <<~HEREDOC.gsub(/[[:space:]]+/, " ").strip
16
+ An opinionated and robust Ruby on Rails application template using RuboCop and pnpm.
17
+ HEREDOC
18
+ spec.description = <<~HEREDOC.gsub(/[[:space:]]+/, " ").strip
19
+ Practical Pig is an opinionated Ruby on Rails template that makes use of webpacker-pnpm, RuboCop, and Prettier to provide a simple yet robust foundation for any web application.
20
+ HEREDOC
21
+
22
+ spec.metadata = {
23
+ "homepage_uri" => spec.homepage,
24
+ "source_code_uri" => "#{spec.homepage}/tree/v#{spec.version}",
25
+ "changelog_uri" => "#{spec.homepage}/blob/v#{spec.version}/CHANGELOG.md",
26
+ "bug_tracker_uri" => "#{spec.homepage}/issues"
27
+ }
28
+
29
+ spec.required_ruby_version = ">= 2.4.0"
30
+
31
+ spec.add_dependency "rails", ">= 5.2"
32
+ spec.add_dependency "thor", "~> 1.0"
33
+
34
+ spec.add_development_dependency "rubocop", "~> 0.83.0"
35
+ spec.add_development_dependency "rubocop-minitest", "~> 0.9"
36
+ spec.add_development_dependency "rubocop-performance", "~> 1.3"
37
+ spec.add_development_dependency "rubocop-rails", "~> 2.5"
38
+
39
+ spec.bindir = "bin"
40
+ spec.executables = ["pig"]
41
+
42
+ spec.files = `git ls-files`.split("\n")
43
+ end
@@ -0,0 +1,206 @@
1
+ #
2
+ # RuboCop is a Ruby static code analyzer and code formatter that tries to enforce many of
3
+ # the guidelines outlined in the community Ruby and Rails
4
+ # style guides.
5
+ #
6
+ # https://docs.rubocop.org/en/latest/
7
+ # https://rubystyle.guide/
8
+ # https://rails.rubystyle.guide/
9
+ require:
10
+ - rubocop-rails
11
+ - rubocop-performance
12
+ - rubocop-minitest
13
+ AllCops:
14
+ Exclude:
15
+ - "**/node_modules/**/*"
16
+ - "**/db/schema.rb"
17
+ - "**/bin/**/*"
18
+ - "**/vendor/**/*"
19
+
20
+ # force length length checking and auto-correction. this is here to enforce
21
+ # standardization; however, it is good practice keep lines <= 90 columns when
22
+ # programming so they remain readable. omit conifg initializers from line-length
23
+ # checking as they are often auto-generated and thus result in tons of comment
24
+ # length conflicts.
25
+ Layout/LineLength:
26
+ Enabled: true
27
+ AutoCorrect: true
28
+ Max: 90
29
+ Exclude:
30
+ - "**/config/initializers/**/*"
31
+
32
+ # when Layout/LineLength triggers, ensure that the output remains human-readable.
33
+ # arguments to methods, pairs in hashes, and array elements should reside on
34
+ # separate lines from the constructor.
35
+ Layout/FirstArgumentIndentation:
36
+ Enabled: true
37
+ EnforcedStyle: special_for_inner_method_call
38
+ Layout/FirstArrayElementIndentation:
39
+ Enabled: true
40
+ EnforcedStyle: consistent
41
+ Layout/FirstHashElementIndentation:
42
+ Enabled: true
43
+ EnforcedStyle: consistent
44
+ Layout/FirstArrayElementLineBreak:
45
+ Enabled: true
46
+ Layout/FirstHashElementLineBreak:
47
+ Enabled: true
48
+
49
+ # case statements should be indended one level from the block to mitigate
50
+ # confusion and make clear possible execution branches
51
+ Layout/CaseIndentation:
52
+ IndentOneStep: true
53
+
54
+ # consistent class structure is important when defining data models and handlers.
55
+ # while it does not affect functionality, consistent organizational patterns make
56
+ # understanding functions and behaviors easier across an entire application.
57
+ #
58
+ # https://docs.rubocop.org/en/latest/cops_layout/#layoutclassstructure
59
+ Layout/ClassStructure:
60
+ Enabled: true
61
+
62
+ # separating variables from their assignments when dealing with multiline expressions
63
+ # disconnects them from their values. to prevent confusion and lack of behavioral
64
+ # clarity, value expressions should always begin (and preferebly end) on the line
65
+ # of assignment.
66
+ Layout/MultilineAssignmentLayout:
67
+ Enabled: true
68
+ EnforcedStyle: same_line
69
+
70
+ Layout/EmptyLinesAroundAttributeAccessor:
71
+ Enabled: true
72
+
73
+ Layout/SpaceAroundMethodCallOperator:
74
+ Enabled: true
75
+
76
+ # this simply doesn't work in a cross-platform development environment. Bit
77
+ # flags across UNIX and Windows platforms are volatile, and thus there is no
78
+ # way to ensure this passes besides explicitly granting execute permissions
79
+ # in CI config (which would defeat the purpose).
80
+ Lint/ScriptPermission:
81
+ Enabled: false
82
+
83
+ Lint/RaiseException:
84
+ Enabled: true
85
+
86
+ Lint/StructNewOverride:
87
+ Enabled: true
88
+
89
+ # functionalization is important, but the Rails' idiom for returning key-value
90
+ # maps can raise a false alarm with the max line number (10). increase the value
91
+ # to something more reasonable given the circumstances.
92
+ Metrics/MethodLength:
93
+ Enabled: true
94
+ Max: 20
95
+
96
+ # omit rake tasks, Gemfiles, and gemspecs from block length checks, as they
97
+ # can be fairly complex and are not subject to segmentation.
98
+ Metrics/BlockLength:
99
+ Enabled: true
100
+ Exclude:
101
+ - "**/*.rake"
102
+ - "**/*.gemspec"
103
+ - "**/Gemfile"
104
+
105
+ # flags methods that violate the an ABC magnitude of >16. The ABC metric
106
+ # quantizes the size of a method, and is calculated based on the number of
107
+ # assignment operations, possible execution branches, and number of conditionals.
108
+ #
109
+ # https://en.wikipedia.org/wiki/ABC_Software_Metric
110
+ Metrics/AbcSize:
111
+ Enabled: true
112
+ Max: 16
113
+
114
+ # disable documentation checking. many classes do not require top-level comments,
115
+ # and their inclusion can actually obscure their function.
116
+ Style/Documentation:
117
+ Enabled: false
118
+
119
+ # flag potential memory leaks, like when opening a file.
120
+ Style/AutoResourceCleanup:
121
+ Enabled: true
122
+
123
+ # single quotes are meant for single characters. double quotes are meant for
124
+ # strings, which are arrays of multiple characters. there are a whole host of
125
+ # other differences and functions; if you're creating a string, you nearly always
126
+ # should use double quotes.
127
+ #
128
+ # https://en.wikipedia.org/wiki/Delimiter#Bracket_delimiters
129
+ # Schwartz, Randal (2005). Learning Perl. ISBN 978-0-596-10105-3.
130
+ Style/StringLiterals:
131
+ Enabled: true
132
+ EnforcedStyle: double_quotes
133
+ Style/StringLiteralsInInterpolation:
134
+ Enabled: true
135
+ EnforcedStyle: double_quotes
136
+
137
+ # by default Ruby makes all defined constants public, which litters the
138
+ # public API of the class or module. Explicitly declaring a visibility makes intent
139
+ # more clear and prevents outside actors from touching private states.
140
+ Style/ConstantVisibility:
141
+ Enabled: true
142
+
143
+ # the bracket idiom [:hi, :bye] is clearer when compared to the percent
144
+ # idiom %i[hi bye] as it does not obfuscate the data structure (an array of symbols).
145
+ Style/SymbolArray:
146
+ Enabled: true
147
+ EnforcedStyle: brackets
148
+
149
+ # the bracket idiom ["hi", "bye"] is clearer when compared to the percent
150
+ # idiom %w[hi bye] as it does not obfuscate the data structure (an array of strings).
151
+ Style/WordArray:
152
+ Enabled: true
153
+ EnforcedStyle: brackets
154
+
155
+ # in Ruby, methods don't have to be called with parantheses. however their omission
156
+ # can cause confusion about which expressions are being passed to the caller,
157
+ # especialy if that method is being called from within an array or hash. force
158
+ Style/MethodCallWithArgsParentheses:
159
+ Enabled: true
160
+ IgnoredMethods:
161
+ - require
162
+ - require_relative
163
+ - puts
164
+ - raise
165
+ - say
166
+ Exclude:
167
+ - "**/Gemfile"
168
+ - "**/*.gemspec"
169
+
170
+ # method signatures should never span multiple lines as that obfuscates the data
171
+ # on which method might depend/function.
172
+ Style/MultilineMethodSignature:
173
+ Enabled: true
174
+
175
+ # by definition, constants should not be mutable. ensure that the constant expression
176
+ # is frozen so that any future modifications raise a runtime exception.
177
+ Style/MutableConstant:
178
+ Enabled: true
179
+ EnforcedStyle: strict
180
+
181
+ # parentheses should be used in situations with complex ternary assignments, as they
182
+ # help distinguish between conditional and expression.
183
+ Style/TernaryParentheses:
184
+ Enabled: true
185
+ EnforcedStyle: require_parentheses_when_complex
186
+
187
+ # methods that manipulate and return multiple values are allowed, as it tends to
188
+ # yield clearer and more concise code and methods.
189
+ Style/RedundantReturn:
190
+ Enabled: true
191
+ AllowMultipleReturnValues: true
192
+
193
+ Style/ExponentialNotation:
194
+ Enabled: true
195
+
196
+ Style/HashEachMethods:
197
+ Enabled: true
198
+
199
+ Style/HashTransformKeys:
200
+ Enabled: true
201
+
202
+ Style/HashTransformValues:
203
+ Enabled: true
204
+
205
+ Style/SlicingWithRange:
206
+ Enabled: true
metadata ADDED
@@ -0,0 +1,166 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: practical-pig
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Elias Gabriel
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2020-05-24 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '5.2'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '5.2'
27
+ - !ruby/object:Gem::Dependency
28
+ name: thor
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rubocop
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 0.83.0
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 0.83.0
55
+ - !ruby/object:Gem::Dependency
56
+ name: rubocop-minitest
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '0.9'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '0.9'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rubocop-performance
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '1.3'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '1.3'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rubocop-rails
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '2.5'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '2.5'
97
+ description: Practical Pig is an opinionated Ruby on Rails template that makes use
98
+ of webpacker-pnpm, RuboCop, and Prettier to provide a simple yet robust foundation
99
+ for any web application.
100
+ email: me@eliasfgabriel.com
101
+ executables:
102
+ - pig
103
+ extensions: []
104
+ extra_rdoc_files: []
105
+ files:
106
+ - ".gitignore"
107
+ - ".rubocop.yml"
108
+ - ".travis.yml"
109
+ - CHANGELOG.md
110
+ - Gemfile
111
+ - LICENSE
112
+ - README.md
113
+ - bin/pig
114
+ - gemfiles/Gemfile-rails.5.2.x
115
+ - gemfiles/Gemfile-rails.6.0.x
116
+ - lib/practical/pig.rb
117
+ - lib/practical/pig/cli.rb
118
+ - lib/practical/pig/version.rb
119
+ - lib/template/.npmrc
120
+ - lib/template/.rubocop.yml
121
+ - lib/template/Gemfile.tt
122
+ - lib/template/app/assets/javascript/%app_name%.js
123
+ - lib/template/app/assets/packs/application.js.tt
124
+ - lib/template/app/assets/stylesheets/%app_name%.scss
125
+ - lib/template/app/views/layouts/application.html.slim.tt
126
+ - lib/template/bin/format
127
+ - lib/template/bin/test
128
+ - lib/template/config/initializers/content_security_policy.rb
129
+ - lib/template/config/initializers/generators.rb
130
+ - lib/template/config/webpack/development.js
131
+ - lib/template/config/webpack/environment.js
132
+ - lib/template/config/webpack/production.js
133
+ - lib/template/config/webpacker.yml
134
+ - lib/template/package.json.tt
135
+ - lib/template/postcss.config.js
136
+ - practical-pig.gemspec
137
+ - rubocop-base.yaml
138
+ homepage: https://github.com/thearchitector/practical-pig
139
+ licenses:
140
+ - MIT
141
+ metadata:
142
+ homepage_uri: https://github.com/thearchitector/practical-pig
143
+ source_code_uri: https://github.com/thearchitector/practical-pig/tree/v1.0.0
144
+ changelog_uri: https://github.com/thearchitector/practical-pig/blob/v1.0.0/CHANGELOG.md
145
+ bug_tracker_uri: https://github.com/thearchitector/practical-pig/issues
146
+ post_install_message:
147
+ rdoc_options: []
148
+ require_paths:
149
+ - lib
150
+ required_ruby_version: !ruby/object:Gem::Requirement
151
+ requirements:
152
+ - - ">="
153
+ - !ruby/object:Gem::Version
154
+ version: 2.4.0
155
+ required_rubygems_version: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - ">="
158
+ - !ruby/object:Gem::Version
159
+ version: '0'
160
+ requirements: []
161
+ rubygems_version: 3.1.3
162
+ signing_key:
163
+ specification_version: 4
164
+ summary: An opinionated and robust Ruby on Rails application template using RuboCop
165
+ and pnpm.
166
+ test_files: []