Module: BulletTrain::Themes::Application
- Defined in:
- lib/tasks/application.rb
Class Method Summary collapse
- .ask(string) ⇒ Object
- .clean_theme(theme_name, args) ⇒ Object
- .eject_theme(theme_name, ejected_theme_name) ⇒ Object
- .eject_theme_main_css(theme_name) ⇒ Object
- .install_theme(theme_name) ⇒ Object
- .release_theme(original_theme_name, args) ⇒ Object
Class Method Details
.ask(string) ⇒ Object
320 321 322 323 |
# File 'lib/tasks/application.rb', line 320 def self.ask(string) puts string.blue $stdin.gets.strip end |
.clean_theme(theme_name, args) ⇒ Object
241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 |
# File 'lib/tasks/application.rb', line 241 def self.clean_theme(theme_name, args) light_base_path = `bundle show --paths bullet_train-themes-light`.chomp tailwind_base_path = `bundle show --paths bullet_train-themes-tailwind_css`.chomp theme_base_path = `bundle show --paths bullet_train-themes`.chomp directory_content = `find . | grep 'app/.*#{args[:theme]}'`.lines.map(&:chomp) directory_content = directory_content.reject { |content| content.match?("app/assets/builds/") } files = directory_content.select { |file| file.match?(/(\.erb)|(\.rb)|(\.css)|(\.js)$/) } # Files that exist outside of "./app/" that we need to check. files += [ "tailwind.#{args[:theme]}.config.js", "tailwind.mailer.#{args[:theme]}.config.js", ] # This file doesn't exist under "app/" in its original gem, so we handle it differently. # Also, don't remove this file from the starter repository in case # the developer has any ejected files that have been customized. files.delete("./app/lib/bullet_train/themes/#{args[:theme]}.rb") files.each do |file| original_theme_path = nil # Remove the current directory syntax for concatenation with the gem base path. file.gsub!("./", "") [light_base_path, tailwind_base_path, theme_base_path].each do |theme_path| # Views exist under "base" when the gem is "bullet_train-themes". theme_gem_name = theme_path.scan(/(.*themes-)(.*$)/).flatten.pop || "base" original_theme_path = file.gsub(args[:theme], theme_gem_name) if File.exist?("#{theme_path}/#{original_theme_path}") original_theme_path = "#{theme_path}/#{original_theme_path}" break end end ejected_file_content = File.read(file) # These are the only files where we replace the theme name inside of them when ejecting, # so we revert the contents and check if the file has been changed or not. transformed_files = [ "app/views/themes/foo/layouts/_head.html.erb", "app/assets/stylesheets/foo.tailwind.css", "tailwind.mailer.#{args[:theme]}.config.js" ] ejected_file_content.gsub!(/#{args[:theme]}/i, theme_name) if transformed_files.include?(file) if ejected_file_content == File.read(original_theme_path) puts "No changes in `#{file}` since being ejected. Removing." `rm #{file}` end end # Delete all leftover directories with empty content. [ "./app/assets/stylesheets/", "./app/views/themes/" ].each do |remaining_directory| puts "Cleaning out directory: #{remaining_directory}" remaining_directory_content = Dir.glob(remaining_directory + "**/*") remaining_directories = remaining_directory_content.select { |content| File.directory?(content) } remaining_directories.reverse_each { |dir| Dir.rmdir dir if Dir.empty?(dir) } FileUtils.rmdir(remaining_directory) if Dir.empty?(remaining_directory) end # These are files from the starter repository that need to be set back to the original theme. [ "Procfile.dev", "app/helpers/application_helper.rb", "package.json", "test/system/resolver_system_test.rb" ].each do |file| puts "Reverting changes in #{file}." new_lines = File.open(file).readlines.join.gsub(/#{args[:theme]}/i, theme_name) File.write(file, new_lines) end end |
.eject_theme(theme_name, ejected_theme_name) ⇒ Object
14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 |
# File 'lib/tasks/application.rb', line 14 def self.eject_theme(theme_name, ejected_theme_name) theme_parts = theme_name.humanize.split.map { |str| str.capitalize } constantized_theme = theme_parts.join humanized_theme = theme_parts.join(" ") theme_base_path = `bundle show --paths bullet_train-themes-#{theme_name}`.chomp puts "Ejecting from #{humanized_theme} theme in `#{theme_base_path}`." puts "Ejecting Tailwind configuration into `./tailwind.#{ejected_theme_name}.config.js`." `cp #{theme_base_path}/tailwind.#{theme_name}.config.js #{Rails.root}/tailwind.#{ejected_theme_name}.config.js` puts "Ejecting Tailwind mailer configuration into `./tailwind.mailer.#{ejected_theme_name}.config.js`." `cp #{theme_base_path}/tailwind.mailer.#{theme_name}.config.js #{Rails.root}/tailwind.mailer.#{ejected_theme_name}.config.js` %x(sed -i #{'""' if `echo $OSTYPE`.include?("darwin")} "s/#{theme_name}/#{ejected_theme_name}/g" #{Rails.root}/tailwind.mailer.#{ejected_theme_name}.config.js) puts "Ejecting stylesheets into `./app/assets/stylesheets/#{ejected_theme_name}`." Rails.root.join("app/assets/stylesheets").mkpath `cp -R #{theme_base_path}/app/assets/stylesheets/#{theme_name} #{Rails.root}/app/assets/stylesheets/#{ejected_theme_name}` `cp -R #{theme_base_path}/app/assets/stylesheets/#{theme_name}.tailwind.css #{Rails.root}/app/assets/stylesheets/#{ejected_theme_name}.tailwind.css` %x(sed -i #{'""' if `echo $OSTYPE`.include?("darwin")} "s/light/#{ejected_theme_name}/g" #{Rails.root}/app/assets/stylesheets/#{ejected_theme_name}.tailwind.css) puts "Ejecting JavaScript into `./app/javascript/application.#{ejected_theme_name}.js`." `cp #{theme_base_path}/app/javascript/application.#{theme_name}.js #{Rails.root}/app/javascript/application.#{ejected_theme_name}.js` puts "Ejecting postcss import aliases configuration into `./postcss-import-config.js`." `cp #{theme_base_path}/postcss-import-config.js #{Rails.root}/postcss-import-config.js` `mkdir #{Rails.root}/app/views/themes` new_files = {} { "bullet_train-themes" => "base", "bullet_train-themes-tailwind_css" => "tailwind_css", "bullet_train-themes-light" => "light" }.each do |gem, theme_name| gem_path = `bundle show --paths #{gem}`.chomp showcase_partials = Dir.glob("#{gem_path}/app/views/showcase/**/*.html.erb") `find #{gem_path}/app/views/themes`.lines.map(&:chomp).each do |file_or_directory| target_file_or_directory = file_or_directory.gsub(gem_path, "").gsub("/#{theme_name}", "/#{ejected_theme_name}") target_file_or_directory = Rails.root.to_s + target_file_or_directory if File.directory?(file_or_directory) puts "Creating `#{target_file_or_directory}`." `mkdir #{target_file_or_directory}` else puts "Copying `#{target_file_or_directory}`." `cp #{file_or_directory} #{target_file_or_directory}` gem_with_version = gem_path.split("/").last new_files[target_file_or_directory] = file_or_directory.split(/(?=#{gem_with_version})/).last end # Look for showcase preview. file_name = target_file_or_directory.split("/").last showcase_preview = showcase_partials.find { _1.end_with?(file_name) } if showcase_preview puts "Ejecting showcase preview for #{target_file_or_directory}" partial_relative_path = showcase_preview.scan(/(?=app\/views\/showcase).*/).last directory = partial_relative_path.split("/")[0..-2].join("/") FileUtils.mkdir_p(directory) FileUtils.touch(partial_relative_path) `cp #{showcase_preview} #{partial_relative_path}` new_files[partial_relative_path] = "#{gem_path.scan(/#{gem}.*/).pop}/#{partial_relative_path}" end end end %x(sed -i #{'""' if `echo $OSTYPE`.include?("darwin")} "s/#{theme_name}/#{ejected_theme_name}/g" #{Rails.root}/app/views/themes/#{ejected_theme_name}/layouts/_head.html.erb) %x(sed -i #{'""' if `echo $OSTYPE`.include?("darwin")} "s/#{theme_name}/#{ejected_theme_name}/g" #{Rails.root}/app/views/themes/#{ejected_theme_name}/layouts/_mailer.html.erb) puts "Cutting local `Procfile.dev` over from `#{theme_name}` to `#{ejected_theme_name}`." %x(sed -i #{'""' if `echo $OSTYPE`.include?("darwin")} "s/#{theme_name}/#{ejected_theme_name}/g" #{Rails.root}/Procfile.dev) puts "Cutting local `package.json` over from `#{theme_name}` to `#{ejected_theme_name}`." %x(sed -i #{'""' if `echo $OSTYPE`.include?("darwin")} "s/#{theme_name}/#{ejected_theme_name}/g" #{Rails.root}/package.json) puts "Cutting `test/system/resolver_system_test.rb` over from `#{theme_name}` to `#{ejected_theme_name}`." %x(sed -i #{'""' if `echo $OSTYPE`.include?("darwin")} "s/light/#{ejected_theme_name}/g" #{Rails.root}/test/system/resolver_system_test.rb) # Stub out the class that represents this theme and establishes its inheritance structure. target_path = "#{Rails.root}/app/lib/bullet_train/themes/#{ejected_theme_name}.rb" puts "Stubbing out a class that represents this theme in `.#{target_path}`." `mkdir -p #{Rails.root}/app/lib/bullet_train/themes` `cp #{theme_base_path}/lib/bullet_train/themes/#{theme_name}.rb #{target_path}` %x(sed -i #{'""' if `echo $OSTYPE`.include?("darwin")} "s/module #{constantized_theme}/module #{ejected_theme_name.titlecase}/g" #{target_path}) %x(sed -i #{'""' if `echo $OSTYPE`.include?("darwin")} "s/TailwindCss/#{constantized_theme}/g" #{target_path}) %x(sed -i #{'""' if `echo $OSTYPE`.include?("darwin")} "s/#{theme_name}/#{ejected_theme_name}/g" #{target_path}) theme_file = Pathname.new(target_path) msmn = Masamune::AbstractSyntaxTree.new(theme_file.readlines.join) data_to_skip = msmn.method_calls(token_value: "require") + msmn.method_calls(token_value: "mattr_accessor") + msmn.comments.select { |comment| comment.token_value.match?("TODO") } lines_to_skip = data_to_skip.map { |data| data.line_number - 1 } new_lines = theme_file.readlines.select.with_index do |line, idx| !lines_to_skip.include?(idx) || line.match?("mattr_accessor :colors") end theme_file.write new_lines.join # We add the comment to the ejected files here so the sed calls don't # overwrite package names like `bullet_train-themes-light`. new_files.each do |key, value| file = Pathname.new(key) lines = file.readlines new_lines = case key.split(".").last when "rb", "yml" lines.unshift("# Ejected from #{value}\n\n") when "erb" lines.unshift("<% # Ejected from #{value} %>\n\n") end file.write(new_lines.join) end `standardrb --fix #{target_path}` puts "Cutting local project over from `#{theme_name}` to `#{ejected_theme_name}` in `app/helpers/application_helper.rb`." %x(sed -i #{'""' if `echo $OSTYPE`.include?("darwin")} "s/:#{theme_name}/:#{ejected_theme_name}/g" #{Rails.root}/app/helpers/application_helper.rb) puts "You must restart `bin/dev` at this point, because of the changes to `Procfile.dev` and `package.json`." end |
.eject_theme_main_css(theme_name) ⇒ Object
6 7 8 9 10 11 12 |
# File 'lib/tasks/application.rb', line 6 def self.eject_theme_main_css(theme_name) theme_base_path = `bundle show --paths bullet_train-themes-#{theme_name}`.chomp puts "Ejecting app/assets/stylesheets/#{theme_name}.tailwind.css." Rails.root.join("app/assets/stylesheets").mkpath `cp -R #{theme_base_path}/app/assets/stylesheets/#{theme_name}.tailwind.css #{Rails.root}/app/assets/stylesheets/#{theme_name}.tailwind.css` end |
.install_theme(theme_name) ⇒ Object
224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 |
# File 'lib/tasks/application.rb', line 224 def self.install_theme(theme_name) helper = Pathname.new("./app/helpers/application_helper.rb") msmn = Masamune::AbstractSyntaxTree.new(helper.readlines.join) current_theme_def = msmn.method_definitions(token_value: "current_theme").pop current_theme = msmn.symbols.find { |node| node.line_number > current_theme_def.line_number }.token_value helper.write msmn.replace(type: :symbol, old_token_value: current_theme, new_token_value: theme_name) [Pathname.new("./Procfile.dev"), Pathname.new("./package.json")].each do |file| changed = file.read.gsub! current_theme, theme_name if changed file.write changed end end puts "Finished installing `#{theme_name}`.".blue end |
.release_theme(original_theme_name, args) ⇒ Object
137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 |
# File 'lib/tasks/application.rb', line 137 def self.release_theme(original_theme_name, args) # We only want developers publishing gems off of `bullet_train-themes-light`, so if the task looks # something like `rake bullet_train:themes:foo:release[bar]`, we prevent them from moving any further here. if original_theme_name != "light" puts "You can only release new themes based off of Bullet Train's Light theme. Please eject a new theme from there, and publish your gem once you've finished making changes.".red exit 1 elsif original_theme_name.nil? puts "Please run the command with the name of the theme you want to release.".red puts "For example: > rake bullet_train:themes:light:release[foo]" end puts "Preparing to release your custom theme: ".blue + args[:theme_name] puts "" puts "Before we make a new Ruby gem for your theme, you'll have to set up a GitHub repository first.".blue puts "Hit <Return> and we'll open a browser to GitHub where you can create a new repository.".blue puts "Make sure you name the repository ".blue + "bullet_train-themes-#{args[:theme_name]}" puts "" puts "When you're done, copy the SSH path from the new repository and return here.".blue ask "We'll ask you to paste it to us in the next step." `#{(Gem::Platform.local.os == "linux") ? "xdg-open" : "open"} https://github.com/new` ssh_path = ask "OK, what was the SSH path? (It should look like `git@github.com:your-account/your-new-repo.git`.)" puts "" puts "Great, you're all set.".blue puts "We'll take it from here, so sit back and enjoy the ride 🚄️".blue puts "" puts "Creating a Ruby gem for ".blue + "#{args[:theme_name]}..." Dir.mkdir("local") unless Dir.exist?("./local") if Dir.exist?("./local/bullet_train-themes-#{args[:theme_name]}") raise "You already have a repository named `bullet_train-themes-#{args[:theme_name]}` in `./local`.\n" \ "Make sure you delete it first to create an entirely new gem." end # Pull `bullet_train-themes-light` only from `bullet_train-core` into the new theme directory. # https://www.git-scm.com/docs/git-sparse-checkout `mkdir ./local/bullet_train-themes-#{args[:theme_name]}` `cd ./local/bullet_train-themes-#{args[:theme_name]} && git init && git remote add bullet-train-core git@github.com:bullet-train-co/bullet_train-core.git` `cd ./local/bullet_train-themes-#{args[:theme_name]} && git config core.sparseCheckout true && echo "bullet_train-themes-light/**/*" >> .git/info/sparse-checkout` `cd ./local/bullet_train-themes-#{args[:theme_name]} && git pull bullet-train-core main && git remote rm bullet-train-core` `cd ./local/bullet_train-themes-#{args[:theme_name]} && mv bullet_train-themes-light/* . && mv bullet_train-themes-light/.* .` `cd ./local/bullet_train-themes-#{args[:theme_name]} && rmdir bullet_train-themes-light/` `cd ./local/bullet_train-themes-#{args[:theme_name]} && git config core.sparseCheckout false` BulletTrain::Themes::Light::CustomThemeFileReplacer.new(original_theme_name, args[:theme_name]).replace_theme work_tree_flag = "--work-tree=local/bullet_train-themes-#{args[:theme_name]}" git_dir_flag = "--git-dir=local/bullet_train-themes-#{args[:theme_name]}/.git" path = "./local/bullet_train-themes-#{args[:theme_name]}" # Set up the proper remote. `git #{work_tree_flag} #{git_dir_flag} remote add origin #{ssh_path}` `git #{work_tree_flag} #{git_dir_flag} add .` `git #{work_tree_flag} #{git_dir_flag} commit -m "Add initial files"` `git #{work_tree_flag} #{git_dir_flag} branch -m main` # Build the gem. `(cd #{path} && gem build bullet_train-themes-#{args[:theme_name]}.gemspec)` `git #{work_tree_flag} #{git_dir_flag} add .` `git #{work_tree_flag} #{git_dir_flag} commit -m "Build gem"` # Commit the deleted files on the main application. `git add .` `git commit -m "Remove #{args[:theme_name]} files from application"` # Push the gem's source code, but not the last commit in the main application. `git #{work_tree_flag} #{git_dir_flag} push -u origin main` puts "" puts "" puts "You're all set! Copy and paste the following commands to publish your gem:".blue puts "cd ./local/bullet_train-themes-#{args[:theme_name]}" puts "gem push bullet_train-themes-#{args[:theme_name]}-1.0.gem && cd ../../" puts "" puts "You may have to wait for some time until the gem can be downloaded via the Gemfile.".blue puts "After a few minutes, run the following command in your main application:".blue puts "bundle add bullet_train-themes-#{args[:theme_name]}" puts "" puts "Then you'll be ready to use your custom gem in your Bullet Train application.".blue puts "" puts "Please note that we have deleted the new theme from your main application.".blue puts "run `git log -1` for details." puts "" puts "Use `rake bullet_train:themes:light:install` to revert to the original theme,".blue puts "or run `rake bullet_train:themes:#{args[:theme_name]}:install` whenever you want to use your new theme.".blue end |