discourse_theme 0.4.0 → 0.5.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: de1cb65ed52d9dd44bbe0039b0a40f00f55897e68106d5193cfb0717937b4ff9
4
- data.tar.gz: 8192308474973266925422876401c974c3daf0ffb331d7423ac06d2368c3db68
3
+ metadata.gz: 20a594e3cf6429ad7b721ca546710a1f57706a74bb0c8346301dea8b76a58cea
4
+ data.tar.gz: 477808a79184cc9251865a86a77ccfa33a64318a90a774207a5441b683499546
5
5
  SHA512:
6
- metadata.gz: 2dcbaf4918cf88082c27270a05e1fb888d5d2e462160834c7a2b82ab79acfb3eaf62d0732ea5da840f83d1656f36d6aadda4633cdec86b77149d57c5188c0514
7
- data.tar.gz: 3c095bcfcc224691d30405353a06eb6ccf64446331175dc28e7f8eebf1347b8b2707c37313e1c29668a35937a4a550c8ef81bc2701201674a5baf8b525d72211
6
+ metadata.gz: 8d5ad9c41ca00b3172167b1985cdb5da36ef6d8073ad6b4882f6760da05006f550a12447007d64fb8486e078245eab618979c80e18e78eaa4cc1487269dd780a
7
+ data.tar.gz: 7e40d9ec1727422c4875307b35b38a3d178330598c4a0b1c207779564fe8cf4dbbd07864e964e8e7eee1d5ffec47ad9cdc2821f28fd24ebe1bdb44677cd659cf
@@ -1,21 +1,50 @@
1
1
  name: CI
2
2
 
3
3
  on:
4
+ pull_request:
4
5
  push:
5
6
  branches:
6
7
  - master
7
- tags:
8
- - v*
8
+ - main
9
9
 
10
10
  jobs:
11
+ build:
12
+ runs-on: ubuntu-latest
13
+
14
+ strategy:
15
+ matrix:
16
+ ruby:
17
+ - 2.5
18
+ - 2.6
19
+ - 2.7
20
+ - 3.0
21
+
22
+ steps:
23
+ - uses: actions/checkout@v2
24
+
25
+ - name: Setup ruby
26
+ uses: ruby/setup-ruby@v1
27
+ with:
28
+ ruby-version: ${{ matrix.ruby }}
29
+ bundler-cache: true
30
+
31
+ - name: Lint
32
+ run: bundle exec rubocop
33
+
34
+ - name: Tests
35
+ run: bundle exec rake test
36
+
11
37
  publish:
12
- if: contains(github.ref, 'refs/tags/v')
38
+ if: github.event_name == 'push' && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/master')
39
+ needs: build
13
40
  runs-on: ubuntu-latest
14
41
 
15
42
  steps:
16
43
  - uses: actions/checkout@v2
17
44
 
18
45
  - name: Release Gem
19
- uses: CvX/publish-rubygems-action@master
46
+ uses: discourse/publish-rubygems-action@v2-beta
20
47
  env:
21
- RUBYGEMS_API_KEY: ${{secrets.RUBYGEMS_API_KEY}}
48
+ RUBYGEMS_API_KEY: ${{ secrets.RUBYGEMS_API_KEY }}
49
+ GIT_EMAIL: team@discourse.org
50
+ GIT_NAME: discoursebot
data/.gitignore CHANGED
@@ -1,11 +1 @@
1
- /.bundle/
2
- /.yardoc
3
- /_yardoc/
4
- /coverage/
5
- /doc/
6
- /pkg/
7
- /spec/reports/
8
- /tmp/
9
1
  Gemfile.lock
10
-
11
- .rubocop-https---raw-githubusercontent-com-discourse-discourse-master--rubocop-yml
data/.rubocop.yml CHANGED
@@ -1 +1,7 @@
1
- inherit_from: https://raw.githubusercontent.com/discourse/discourse/master/.rubocop.yml
1
+ inherit_gem:
2
+ rubocop-discourse: default.yml
3
+ inherit_mode:
4
+ merge:
5
+ - Exclude
6
+ Discourse/NoChdir:
7
+ Enabled: false
data/Gemfile CHANGED
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  source "https://rubygems.org"
2
3
 
3
4
  git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
data/Guardfile CHANGED
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  directories %w(app lib test) \
2
3
  .select { |d| Dir.exists?(d) ? d : UI.warning("Directory #{d} does not exist") }
3
4
 
data/README.md CHANGED
@@ -20,11 +20,17 @@ For help run:
20
20
  discourse_theme
21
21
  ```
22
22
 
23
- it contains two helpers:
23
+ ### `discourse_theme new PATH`
24
24
 
25
- You can use `discourse_theme new PATH` to crate a new blank theme, the CLI will guide you through the process.
25
+ Creates a new blank theme. The CLI will guide you through the process.
26
26
 
27
- You can use `discourse_theme watch PATH` to monitor your theme or component for changes, when changed the program will synchronize the theme or component to your Discourse of choice.
27
+ ### `discourse_theme download PATH`
28
+
29
+ Downloads a theme from the server and stores in the designated directory.
30
+
31
+ ### `discourse_theme watch PATH`
32
+
33
+ Monitors a theme or component for changes. When changed the program will synchronize the theme or component to your Discourse of choice.
28
34
 
29
35
  ## Contributing
30
36
 
data/Rakefile CHANGED
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require "bundler/gem_tasks"
2
3
  require "rake/testtask"
3
4
 
data/bin/discourse_theme CHANGED
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
 
3
4
  require_relative '../lib/discourse_theme'
4
5
 
@@ -23,18 +23,20 @@ Gem::Specification.new do |spec|
23
23
  spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
24
24
  spec.require_paths = ["lib"]
25
25
 
26
+ spec.required_ruby_version = '>= 2.5.0'
27
+
28
+ spec.add_runtime_dependency "minitar", "~> 0.6"
29
+ spec.add_runtime_dependency "listen", "~> 3.1"
30
+ spec.add_runtime_dependency "multipart-post", "~> 2.0"
31
+ spec.add_runtime_dependency "tty-prompt", "~> 0.18"
32
+ spec.add_runtime_dependency "rubyzip", "~> 1.2"
33
+
26
34
  spec.add_development_dependency "bundler", "~> 2.0"
27
- spec.add_development_dependency "rake", "~> 10.0"
35
+ spec.add_development_dependency "rake", "~> 13.0"
28
36
  spec.add_development_dependency "minitest", "~> 5.0"
29
37
  spec.add_development_dependency "guard", "~> 2.14"
30
38
  spec.add_development_dependency "guard-minitest", "~> 2.4"
31
39
  spec.add_development_dependency "webmock", "~> 3.5"
32
-
33
- spec.add_dependency "minitar", "~> 0.6"
34
- spec.add_dependency "listen", "~> 3.1"
35
- spec.add_dependency "multipart-post", "~> 2.0"
36
- spec.add_dependency "tty-prompt", "~> 0.18"
37
- spec.add_dependency "rubyzip", "~> 1.2"
38
-
39
- spec.required_ruby_version = '>= 2.6.0'
40
+ spec.add_development_dependency "rubocop"
41
+ spec.add_development_dependency "rubocop-discourse"
40
42
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'fileutils'
2
3
  require 'pathname'
3
4
  require 'tempfile'
@@ -13,14 +14,15 @@ require 'json'
13
14
  require 'yaml'
14
15
  require 'tty/prompt'
15
16
 
16
- require 'discourse_theme/version'
17
- require 'discourse_theme/config'
18
- require 'discourse_theme/cli'
19
- require 'discourse_theme/client'
20
- require 'discourse_theme/downloader'
21
- require 'discourse_theme/uploader'
22
- require 'discourse_theme/watcher'
23
- require 'discourse_theme/scaffold'
17
+ require_relative 'discourse_theme/version'
18
+ require_relative 'discourse_theme/config'
19
+ require_relative 'discourse_theme/ui'
20
+ require_relative 'discourse_theme/cli'
21
+ require_relative 'discourse_theme/client'
22
+ require_relative 'discourse_theme/downloader'
23
+ require_relative 'discourse_theme/uploader'
24
+ require_relative 'discourse_theme/watcher'
25
+ require_relative 'discourse_theme/scaffold'
24
26
 
25
27
  module DiscourseTheme
26
28
  class ThemeError < StandardError; end
@@ -1,45 +1,14 @@
1
+ # frozen_string_literal: true
1
2
  module DiscourseTheme
2
3
  class Cli
3
-
4
- @@prompt = ::TTY::Prompt.new(help_color: :cyan)
5
- @@pastel = Pastel.new
6
-
7
- def self.yes?(message)
8
- @@prompt.yes?(@@pastel.cyan("? ") + message)
9
- end
10
-
11
- def self.ask(message, default: nil)
12
- @@prompt.ask(@@pastel.cyan("? ") + message, default: default)
13
- end
14
-
15
- def self.select(message, options)
16
- @@prompt.select(@@pastel.cyan("? ") + message, options)
17
- end
18
-
19
- def self.info(message)
20
- puts @@pastel.blue("i ") + message
21
- end
22
-
23
- def self.progress(message)
24
- puts @@pastel.yellow("» ") + message
25
- end
26
-
27
- def self.error(message)
28
- puts @@pastel.red("✘ #{message}")
29
- end
30
-
31
- def self.success(message)
32
- puts @@pastel.green("✔ #{message}")
33
- end
34
-
35
4
  SETTINGS_FILE = File.expand_path("~/.discourse_theme")
36
5
 
37
6
  def usage
38
7
  puts "Usage: discourse_theme COMMAND [--reset]"
39
8
  puts
40
- puts "discourse_theme new DIR : Creates a new theme in the designated directory"
41
- puts "discourse_theme download DIR : Download a theme from the server, and store in the designated directory"
42
- puts "discourse_theme watch DIR : Watches the theme directory and synchronizes with Discourse"
9
+ puts "discourse_theme new DIR - Creates a new theme in the designated directory"
10
+ puts "discourse_theme download DIR - Downloads a theme from the server and stores in the designated directory"
11
+ puts "discourse_theme watch DIR - Watches the theme directory and synchronizes with Discourse"
43
12
  puts
44
13
  puts "Use --reset to change the configuration for a directory"
45
14
  exit 1
@@ -60,13 +29,12 @@ module DiscourseTheme
60
29
  components = settings.components
61
30
 
62
31
  if command == "new"
63
- raise DiscourseTheme::ThemeError.new "'#{dir} is not empty" if Dir.exists?(dir) && !Dir.empty?(dir)
32
+ raise DiscourseTheme::ThemeError.new "'#{dir}' is not empty" if Dir.exists?(dir) && !Dir.empty?(dir)
33
+ raise DiscourseTheme::ThemeError.new "git is not installed" if !command?("git")
34
+ raise DiscourseTheme::ThemeError.new "yarn is not installed" if !command?("yarn")
35
+
64
36
  DiscourseTheme::Scaffold.generate(dir)
65
- if Cli.yes?("Would you like to start 'watching' this theme?")
66
- args[0] = "watch"
67
- Cli.progress "Running discourse_theme #{args.join(' ')}"
68
- run(args)
69
- end
37
+ watch_theme?(args)
70
38
  elsif command == "watch"
71
39
  raise DiscourseTheme::ThemeError.new "'#{dir} does not exist" unless Dir.exists?(dir)
72
40
  client = DiscourseTheme::Client.new(dir, settings, reset: reset)
@@ -80,13 +48,13 @@ module DiscourseTheme
80
48
  options["Create and sync with a new theme"] = :create
81
49
  options["Select a different theme"] = :select
82
50
 
83
- choice = Cli.select('How would you like to sync this theme?', options.keys)
51
+ choice = UI.select('How would you like to sync this theme?', options.keys)
84
52
 
85
53
  if options[choice] == :create
86
54
  theme_id = nil
87
55
  elsif options[choice] == :select
88
56
  themes = render_theme_list(theme_list)
89
- choice = Cli.select('Which theme would you like to sync with?', themes)
57
+ choice = UI.select('Which theme would you like to sync with?', themes)
90
58
  theme_id = extract_theme_id(choice)
91
59
  theme = theme_list.find { |t| t["id"] == theme_id }
92
60
  end
@@ -101,27 +69,26 @@ module DiscourseTheme
101
69
  options["Yes"] = :sync
102
70
  options["No"] = :none
103
71
  options = options.sort_by { |_, b| b == components.to_sym ? 0 : 1 }.to_h if components
104
- choice = Cli.select('Would you like to update child theme components?', options.keys)
72
+ choice = UI.select('Would you like to update child theme components?', options.keys)
105
73
  settings.components = components = options[choice].to_s
106
74
  end
107
75
 
108
76
  uploader = DiscourseTheme::Uploader.new(dir: dir, client: client, theme_id: theme_id, components: components)
109
77
 
110
- Cli.progress "Uploading theme from #{dir}"
78
+ UI.progress "Uploading theme from #{dir}"
111
79
  settings.theme_id = theme_id = uploader.upload_full_theme
112
80
 
113
- Cli.success "Theme uploaded (id:#{theme_id})"
114
- Cli.info "Preview: #{client.root}/?preview_theme_id=#{theme_id}"
81
+ UI.success "Theme uploaded (id:#{theme_id})"
82
+ UI.info "Preview: #{client.root}/?preview_theme_id=#{theme_id}"
115
83
  if client.is_theme_creator
116
- Cli.info "Manage: #{client.root}/my/themes"
84
+ UI.info "Manage: #{client.root}/my/themes"
117
85
  else
118
- Cli.info "Manage: #{client.root}/admin/customize/themes/#{theme_id}"
86
+ UI.info "Manage: #{client.root}/admin/customize/themes/#{theme_id}"
119
87
  end
120
88
  watcher = DiscourseTheme::Watcher.new(dir: dir, uploader: uploader)
121
89
 
122
- Cli.progress "Watching for changes in #{dir}..."
90
+ UI.progress "Watching for changes in #{dir}..."
123
91
  watcher.watch
124
-
125
92
  elsif command == "download"
126
93
  client = DiscourseTheme::Client.new(dir, settings, reset: reset)
127
94
  downloader = DiscourseTheme::Downloader.new(dir: dir, client: client)
@@ -129,33 +96,51 @@ module DiscourseTheme
129
96
  FileUtils.mkdir_p dir unless Dir.exists?(dir)
130
97
  raise DiscourseTheme::ThemeError.new "'#{dir} is not empty" unless Dir.empty?(dir)
131
98
 
132
- Cli.progress "Loading theme list..."
99
+ UI.progress "Loading theme list..."
133
100
  themes = render_theme_list(client.get_themes_list)
134
101
 
135
- choice = Cli.select('Which theme would you like to download?', themes)
102
+ choice = UI.select('Which theme would you like to download?', themes)
136
103
  theme_id = extract_theme_id(choice)
137
104
 
138
- Cli.progress "Downloading theme into #{dir}"
105
+ UI.progress "Downloading theme into #{dir}"
139
106
 
140
107
  downloader.download_theme(theme_id)
141
108
  settings.theme_id = theme_id
142
109
 
143
- Cli.success "Theme downloaded"
110
+ UI.success "Theme downloaded"
144
111
 
145
- if Cli.yes?("Would you like to start 'watching' this theme?")
146
- args[0] = "watch"
147
- Cli.progress "Running discourse_theme #{args.join(' ')}"
148
- run(args)
149
- end
112
+ watch_theme?(args)
150
113
  else
151
114
  usage
152
115
  end
153
116
 
154
- Cli.progress "Exiting..."
117
+ UI.progress "Exiting..."
155
118
  rescue DiscourseTheme::ThemeError => e
156
- Cli.error "#{e.message}"
119
+ UI.error "#{e.message}"
157
120
  rescue Interrupt, TTY::Reader::InputInterrupt => e
158
- Cli.error "Interrupted"
121
+ UI.error "Interrupted"
122
+ end
123
+
124
+ private
125
+
126
+ def command?(cmd)
127
+ exts = ENV['PATHEXT'] ? ENV['PATHEXT'].split(';') : ['']
128
+ ENV['PATH'].split(File::PATH_SEPARATOR).each do |path|
129
+ exts.each do |ext|
130
+ exe = File.join(path, "#{cmd}#{ext}")
131
+ return true if File.executable?(exe) && !File.directory?(exe)
132
+ end
133
+ end
134
+
135
+ false
136
+ end
137
+
138
+ def watch_theme?(args)
139
+ if UI.yes?("Would you like to start 'watching' this theme?")
140
+ args[0] = "watch"
141
+ UI.progress "Running discourse_theme #{args.join(' ')}"
142
+ run(args)
143
+ end
159
144
  end
160
145
 
161
146
  def render_theme_list(themes)
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module DiscourseTheme
2
3
  class Client
3
4
  THEME_CREATOR_REGEX = /^https:\/\/theme-creator.discourse.org$/i
@@ -13,8 +14,8 @@ module DiscourseTheme
13
14
  @is_theme_creator = !!(THEME_CREATOR_REGEX =~ @url)
14
15
 
15
16
  if !self.class.has_needed_version?(discourse_version, "2.3.0.beta1")
16
- Cli.info "discourse_theme is designed for Discourse 2.3.0.beta1 or above"
17
- Cli.info "download will not function, and syncing destination will be unpredictable"
17
+ UI.info "discourse_theme is designed for Discourse 2.3.0.beta1 or above"
18
+ UI.info "download will not function, and syncing destination will be unpredictable"
18
19
  end
19
20
  end
20
21
 
@@ -141,26 +142,26 @@ module DiscourseTheme
141
142
  def guess_url(settings)
142
143
  url = ENV['DISCOURSE_URL']
143
144
  if url
144
- Cli.progress "Using #{url} from DISCOURSE_URL"
145
+ UI.progress "Using #{url} from DISCOURSE_URL"
145
146
  end
146
147
 
147
148
  if !url && settings.url
148
149
  url = settings.url
149
- Cli.progress "Using #{url} from #{DiscourseTheme::Cli::SETTINGS_FILE}"
150
+ UI.progress "Using #{url} from #{DiscourseTheme::Cli::SETTINGS_FILE}"
150
151
  end
151
152
 
152
153
  if !url || @reset
153
- url = Cli.ask("What is the root URL of your Discourse site?", default: url).strip
154
+ url = UI.ask("What is the root URL of your Discourse site?", default: url).strip
154
155
  url = "http://#{url}" unless url =~ /^https?:\/\//
155
156
 
156
157
  # maybe this is an HTTPS redirect
157
158
  uri = URI.parse(url)
158
159
  if URI::HTTP === uri && uri.port == 80 && is_https_redirect?(url)
159
- Cli.info "Detected that #{url} should be accessed over https"
160
+ UI.info "Detected that #{url} should be accessed over https"
160
161
  url = url.sub("http", "https")
161
162
  end
162
163
 
163
- if Cli.yes?("Would you like this site name stored in #{DiscourseTheme::Cli::SETTINGS_FILE}?")
164
+ if UI.yes?("Would you like this site name stored in #{DiscourseTheme::Cli::SETTINGS_FILE}?")
164
165
  settings.url = url
165
166
  else
166
167
  settings.url = nil
@@ -173,17 +174,17 @@ module DiscourseTheme
173
174
  def guess_api_key(settings)
174
175
  api_key = ENV['DISCOURSE_API_KEY']
175
176
  if api_key
176
- Cli.progress "Using api key from DISCOURSE_API_KEY"
177
+ UI.progress "Using api key from DISCOURSE_API_KEY"
177
178
  end
178
179
 
179
180
  if !api_key && settings.api_key
180
181
  api_key = settings.api_key
181
- Cli.progress "Using api key from #{DiscourseTheme::Cli::SETTINGS_FILE}"
182
+ UI.progress "Using api key from #{DiscourseTheme::Cli::SETTINGS_FILE}"
182
183
  end
183
184
 
184
185
  if !api_key || @reset
185
- api_key = Cli.ask("What is your API key?", default: api_key).strip
186
- if Cli.yes?("Would you like this API key stored in #{DiscourseTheme::Cli::SETTINGS_FILE}?")
186
+ api_key = UI.ask("What is your API key?", default: api_key).strip
187
+ if UI.yes?("Would you like this API key stored in #{DiscourseTheme::Cli::SETTINGS_FILE}?")
187
188
  settings.api_key = api_key
188
189
  else
189
190
  settings.api_key = nil
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  class DiscourseTheme::Config
2
3
 
3
4
  class PathSetting
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'zip'
2
3
 
3
4
  class DiscourseTheme::Downloader
@@ -1,74 +1,143 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+
1
5
  module DiscourseTheme
2
6
  class Scaffold
3
7
 
4
8
  BLANK_FILES = %w{
5
9
  common/common.scss
6
- common/header.html
7
- common/after_header.html
8
- common/footer.html
9
- common/head_tag.html
10
- common/body_tag.html
11
- common/embedded.scss
12
-
13
- desktop/desktop.scss
14
- desktop/header.html
15
- desktop/after_header.html
16
- desktop/footer.html
17
- desktop/head_tag.html
18
- desktop/body_tag.html
19
-
20
- mobile/mobile.scss
21
- mobile/header.html
22
- mobile/after_header.html
23
- mobile/footer.html
24
- mobile/head_tag.html
25
- mobile/body_tag.html
26
-
27
- locales/en.yml
28
10
 
29
11
  settings.yml
30
12
  }
31
13
 
32
- ABOUT_JSON = <<~STR
33
- {
34
- "name": "#NAME#",
35
- "about_url": null,
36
- "license_url": null,
37
- "assets": {
38
- },
39
- "color_schemes": {
40
- }
14
+ ABOUT_JSON = {
15
+ about_url: nil,
16
+ license_url: nil,
17
+ assets: {}
41
18
  }
42
- STR
43
19
 
44
20
  HELP = <<~STR
45
21
  Are you a bit lost? Be sure to read https://meta.discourse.org/t/how-to-develop-custom-themes/60848
46
22
  STR
47
23
 
48
24
  GIT_IGNORE = <<~STR
49
- .discourse-site
50
- HELP
51
- STR
25
+ .discourse-site
26
+ node_modules
27
+ HELP
28
+ STR
29
+
30
+ API_INITIALIZER = <<~STR
31
+ import { apiInitializer } from "discourse/lib/api";
32
+
33
+ export default apiInitializer("0.11.1", api => {
34
+ console.log("hello world from api initializer!");
35
+ });
36
+ STR
37
+
38
+ PACKAGE_JSON = <<~STR
39
+ {
40
+ "author": "#AUTHOR",
41
+ "license": "MIT",
42
+ "devDependencies": {
43
+ "eslint-config-discourse": "latest"
44
+ }
45
+ }
46
+ STR
47
+
48
+ ESLINT_RC = <<~STR
49
+ {
50
+ "extends": "eslint-config-discourse"
51
+ }
52
+ STR
53
+
54
+ TEMPLATE_LINT_RC = <<~STR
55
+ module.exports = {
56
+ plugins: ["ember-template-lint-plugin-discourse"],
57
+ extends: "discourse:recommended",
58
+ };
59
+ STR
60
+
61
+ EN_YML = <<~YAML
62
+ en:
63
+ theme_metadata:
64
+ description: "#DESCRIPTION"
65
+ YAML
52
66
 
53
67
  def self.generate(dir)
54
- Cli.progress "Generating a scaffold theme at #{dir}"
68
+ UI.progress "Generating a scaffold theme at #{dir}"
55
69
 
56
- name = Cli.ask("What would you like to call your theme?").strip
70
+ name = loop do
71
+ input = UI.ask("What would you like to call your theme?").to_s.strip
72
+ if input.empty?
73
+ UI.error("Theme name cannot be empty")
74
+ else
75
+ break input
76
+ end
77
+ end
78
+
79
+ is_component = UI.yes?("Is this a component?")
57
80
 
58
81
  FileUtils.mkdir_p dir
59
82
  Dir.chdir dir do
60
- File.write('about.json', ABOUT_JSON.sub("#NAME#", name))
83
+ author = loop do
84
+ input = UI.ask("Who is authoring the theme?", default: ENV['USER']).to_s.strip
85
+ if input.empty?
86
+ UI.error("Author cannot be empty")
87
+ else
88
+ break input
89
+ end
90
+ end
91
+
92
+ description = UI.ask("How would you describe this theme?").to_s.strip
93
+
94
+ UI.info "Creating about.json"
95
+ about_template = ABOUT_JSON.dup
96
+ about_template[:name] = name
97
+ if is_component
98
+ about_template[:component] = true
99
+ else
100
+ about_template[:color_schemes] = {}
101
+ end
102
+ File.write('about.json', JSON.pretty_generate(about_template))
103
+
104
+ UI.info "Creating HELP"
61
105
  File.write('HELP', HELP)
106
+
107
+ UI.info "Creating package.json"
108
+ File.write('package.json', PACKAGE_JSON.sub("#AUTHOR", author))
109
+
110
+ UI.info "Creating .template-lintrc.js"
111
+ File.write('.template-lintrc.js', TEMPLATE_LINT_RC)
112
+
113
+ UI.info "Creating .eslintrc"
114
+ File.write('.eslintrc', ESLINT_RC)
115
+
116
+ UI.info "Creating .gitignore"
62
117
  File.write('.gitignore', GIT_IGNORE)
63
118
 
119
+ locale = "locales/en.yml"
120
+ UI.info "Creating #{locale}"
121
+ FileUtils.mkdir_p(File.dirname(locale))
122
+ File.write(locale, EN_YML.sub("#DESCRIPTION", description))
123
+
124
+ encoded_name = name.downcase.gsub(/[^\w_-]+/, '_')
125
+ initializer = "javascripts/discourse/api-initializers/#{encoded_name}.js"
126
+ UI.info "Creating #{initializer}"
127
+ FileUtils.mkdir_p(File.dirname(initializer))
128
+ File.write(initializer, API_INITIALIZER)
129
+
64
130
  BLANK_FILES.each do |f|
65
- Cli.info "Creating #{f}"
131
+ UI.info "Creating #{f}"
66
132
  FileUtils.mkdir_p File.dirname(f)
67
133
  FileUtils.touch f
68
134
  end
69
135
 
70
- Cli.info "Initializing git repo"
71
- puts `git init .`
136
+ UI.info "Initializing git repo"
137
+ puts `git init . --initial-branch=main`
138
+
139
+ UI.info "Installing dependencies"
140
+ puts `yarn`
72
141
  end
73
142
  end
74
143
  end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+ module DiscourseTheme
3
+ class UI
4
+ @@prompt = ::TTY::Prompt.new(help_color: :cyan)
5
+ @@pastel = Pastel.new
6
+
7
+ def self.yes?(message)
8
+ @@prompt.yes?(@@pastel.cyan("? ") + message)
9
+ end
10
+
11
+ def self.ask(message, default: nil)
12
+ @@prompt.ask(@@pastel.cyan("? ") + message, default: default)
13
+ end
14
+
15
+ def self.select(message, options)
16
+ @@prompt.select(@@pastel.cyan("? ") + message, options)
17
+ end
18
+
19
+ def self.info(message)
20
+ puts @@pastel.blue("i ") + message
21
+ end
22
+
23
+ def self.progress(message)
24
+ puts @@pastel.yellow("» ") + message
25
+ end
26
+
27
+ def self.error(message)
28
+ puts @@pastel.red("✘ #{message}")
29
+ end
30
+
31
+ def self.success(message)
32
+ puts @@pastel.green("✔ #{message}")
33
+ end
34
+ end
35
+ end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module DiscourseTheme
2
3
  class Uploader
3
4
 
@@ -33,9 +34,9 @@ module DiscourseTheme
33
34
  json["theme"]["theme_fields"].each do |row|
34
35
  if (error = row["error"]) && error.length > 0
35
36
  count += 1
36
- Cli.error ""
37
- Cli.error "Error in #{row["target"]} #{row["name"]}: #{row["error"]}"
38
- Cli.error ""
37
+ UI.error ""
38
+ UI.error "Error in #{row["target"]} #{row["name"]}: #{row["error"]}"
39
+ UI.error ""
39
40
  end
40
41
  end
41
42
  count
@@ -58,7 +59,7 @@ module DiscourseTheme
58
59
  response = @client.update_theme(@theme_id, args)
59
60
  json = JSON.parse(response.body)
60
61
  if diagnose_errors(json) != 0
61
- Cli.error "(end of errors)"
62
+ UI.error "(end of errors)"
62
63
  end
63
64
  end
64
65
 
@@ -72,7 +73,7 @@ module DiscourseTheme
72
73
  json = JSON.parse(response.body)
73
74
  @theme_id = json["theme"]["id"]
74
75
  if diagnose_errors(json) != 0
75
- Cli.error "(end of errors)"
76
+ UI.error "(end of errors)"
76
77
  end
77
78
  @theme_id
78
79
  end
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module DiscourseTheme
3
- VERSION = "0.4.0"
3
+ VERSION = "0.5.2"
4
4
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module DiscourseTheme
2
3
  class Watcher
3
4
  def self.return_immediately!
@@ -22,7 +23,7 @@ module DiscourseTheme
22
23
  (resolved = resolve_file(modified[0]))
23
24
 
24
25
  target, name, type_id = resolved
25
- Cli.progress "Fast updating #{target}.scss"
26
+ UI.progress "Fast updating #{target}.scss"
26
27
 
27
28
  @uploader.upload_theme_field(
28
29
  target: target,
@@ -33,17 +34,17 @@ module DiscourseTheme
33
34
  else
34
35
  count = modified.length + added.length + removed.length
35
36
  if count > 1
36
- Cli.progress "Detected changes in #{count} files, uploading theme"
37
+ UI.progress "Detected changes in #{count} files, uploading theme"
37
38
  else
38
39
  filename = modified[0] || added[0] || removed[0]
39
- Cli.progress "Detected changes in #{filename.gsub(@dir, '')}, uploading theme"
40
+ UI.progress "Detected changes in #{filename.gsub(@dir, '')}, uploading theme"
40
41
  end
41
42
  @uploader.upload_full_theme
42
43
  end
43
- Cli.success "Done! Watching for changes..."
44
+ UI.success "Done! Watching for changes..."
44
45
  rescue DiscourseTheme::ThemeError => e
45
- Cli.error "#{e.message}"
46
- Cli.progress "Watching for changes..."
46
+ UI.error "#{e.message}"
47
+ UI.progress "Watching for changes..."
47
48
  end
48
49
  end
49
50
 
metadata CHANGED
@@ -1,169 +1,197 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: discourse_theme
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.5.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sam Saffron
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-11-24 00:00:00.000000000 Z
11
+ date: 2021-07-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: bundler
14
+ name: minitar
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '2.0'
20
- type: :development
19
+ version: '0.6'
20
+ type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '2.0'
26
+ version: '0.6'
27
27
  - !ruby/object:Gem::Dependency
28
- name: rake
28
+ name: listen
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '10.0'
34
- type: :development
33
+ version: '3.1'
34
+ type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '10.0'
40
+ version: '3.1'
41
41
  - !ruby/object:Gem::Dependency
42
- name: minitest
42
+ name: multipart-post
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '5.0'
48
- type: :development
47
+ version: '2.0'
48
+ type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: '5.0'
54
+ version: '2.0'
55
55
  - !ruby/object:Gem::Dependency
56
- name: guard
56
+ name: tty-prompt
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: '2.14'
62
- type: :development
61
+ version: '0.18'
62
+ type: :runtime
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: '2.14'
68
+ version: '0.18'
69
69
  - !ruby/object:Gem::Dependency
70
- name: guard-minitest
70
+ name: rubyzip
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
73
  - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: '2.4'
76
- type: :development
75
+ version: '1.2'
76
+ type: :runtime
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
- version: '2.4'
82
+ version: '1.2'
83
83
  - !ruby/object:Gem::Dependency
84
- name: webmock
84
+ name: bundler
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
87
  - - "~>"
88
88
  - !ruby/object:Gem::Version
89
- version: '3.5'
89
+ version: '2.0'
90
90
  type: :development
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
94
  - - "~>"
95
95
  - !ruby/object:Gem::Version
96
- version: '3.5'
96
+ version: '2.0'
97
97
  - !ruby/object:Gem::Dependency
98
- name: minitar
98
+ name: rake
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
101
  - - "~>"
102
102
  - !ruby/object:Gem::Version
103
- version: '0.6'
104
- type: :runtime
103
+ version: '13.0'
104
+ type: :development
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
108
  - - "~>"
109
109
  - !ruby/object:Gem::Version
110
- version: '0.6'
110
+ version: '13.0'
111
111
  - !ruby/object:Gem::Dependency
112
- name: listen
112
+ name: minitest
113
113
  requirement: !ruby/object:Gem::Requirement
114
114
  requirements:
115
115
  - - "~>"
116
116
  - !ruby/object:Gem::Version
117
- version: '3.1'
118
- type: :runtime
117
+ version: '5.0'
118
+ type: :development
119
119
  prerelease: false
120
120
  version_requirements: !ruby/object:Gem::Requirement
121
121
  requirements:
122
122
  - - "~>"
123
123
  - !ruby/object:Gem::Version
124
- version: '3.1'
124
+ version: '5.0'
125
125
  - !ruby/object:Gem::Dependency
126
- name: multipart-post
126
+ name: guard
127
127
  requirement: !ruby/object:Gem::Requirement
128
128
  requirements:
129
129
  - - "~>"
130
130
  - !ruby/object:Gem::Version
131
- version: '2.0'
132
- type: :runtime
131
+ version: '2.14'
132
+ type: :development
133
133
  prerelease: false
134
134
  version_requirements: !ruby/object:Gem::Requirement
135
135
  requirements:
136
136
  - - "~>"
137
137
  - !ruby/object:Gem::Version
138
- version: '2.0'
138
+ version: '2.14'
139
139
  - !ruby/object:Gem::Dependency
140
- name: tty-prompt
140
+ name: guard-minitest
141
141
  requirement: !ruby/object:Gem::Requirement
142
142
  requirements:
143
143
  - - "~>"
144
144
  - !ruby/object:Gem::Version
145
- version: '0.18'
146
- type: :runtime
145
+ version: '2.4'
146
+ type: :development
147
147
  prerelease: false
148
148
  version_requirements: !ruby/object:Gem::Requirement
149
149
  requirements:
150
150
  - - "~>"
151
151
  - !ruby/object:Gem::Version
152
- version: '0.18'
152
+ version: '2.4'
153
153
  - !ruby/object:Gem::Dependency
154
- name: rubyzip
154
+ name: webmock
155
155
  requirement: !ruby/object:Gem::Requirement
156
156
  requirements:
157
157
  - - "~>"
158
158
  - !ruby/object:Gem::Version
159
- version: '1.2'
160
- type: :runtime
159
+ version: '3.5'
160
+ type: :development
161
161
  prerelease: false
162
162
  version_requirements: !ruby/object:Gem::Requirement
163
163
  requirements:
164
164
  - - "~>"
165
165
  - !ruby/object:Gem::Version
166
- version: '1.2'
166
+ version: '3.5'
167
+ - !ruby/object:Gem::Dependency
168
+ name: rubocop
169
+ requirement: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - ">="
172
+ - !ruby/object:Gem::Version
173
+ version: '0'
174
+ type: :development
175
+ prerelease: false
176
+ version_requirements: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - ">="
179
+ - !ruby/object:Gem::Version
180
+ version: '0'
181
+ - !ruby/object:Gem::Dependency
182
+ name: rubocop-discourse
183
+ requirement: !ruby/object:Gem::Requirement
184
+ requirements:
185
+ - - ">="
186
+ - !ruby/object:Gem::Version
187
+ version: '0'
188
+ type: :development
189
+ prerelease: false
190
+ version_requirements: !ruby/object:Gem::Requirement
191
+ requirements:
192
+ - - ">="
193
+ - !ruby/object:Gem::Version
194
+ version: '0'
167
195
  description: CLI helper for creating Discourse themes
168
196
  email:
169
197
  - sam.saffron@gmail.com
@@ -175,7 +203,6 @@ files:
175
203
  - ".github/workflows/ci.yml"
176
204
  - ".gitignore"
177
205
  - ".rubocop.yml"
178
- - ".travis.yml"
179
206
  - CODE_OF_CONDUCT.md
180
207
  - Gemfile
181
208
  - Guardfile
@@ -190,6 +217,7 @@ files:
190
217
  - lib/discourse_theme/config.rb
191
218
  - lib/discourse_theme/downloader.rb
192
219
  - lib/discourse_theme/scaffold.rb
220
+ - lib/discourse_theme/ui.rb
193
221
  - lib/discourse_theme/uploader.rb
194
222
  - lib/discourse_theme/version.rb
195
223
  - lib/discourse_theme/watcher.rb
@@ -205,14 +233,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
205
233
  requirements:
206
234
  - - ">="
207
235
  - !ruby/object:Gem::Version
208
- version: 2.6.0
236
+ version: 2.5.0
209
237
  required_rubygems_version: !ruby/object:Gem::Requirement
210
238
  requirements:
211
239
  - - ">="
212
240
  - !ruby/object:Gem::Version
213
241
  version: '0'
214
242
  requirements: []
215
- rubygems_version: 3.0.3
243
+ rubygems_version: 3.1.6
216
244
  signing_key:
217
245
  specification_version: 4
218
246
  summary: CLI helper for creating Discourse themes
data/.travis.yml DELETED
@@ -1,5 +0,0 @@
1
- sudo: false
2
- language: ruby
3
- rvm:
4
- - 2.4.2
5
- before_install: gem install bundler -v 1.16.1