practical-pig 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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: []