discourse_theme 0.4.1 → 0.5.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b049cb77cb8542cd1991928a60dab7567f11e8a89c8c4ddaba8e297c05938f6c
4
- data.tar.gz: c799d67427d340e1ce920c8deaebd9ae34b0af598905bf6176421ed816c3eade
3
+ metadata.gz: 0a1f5b1cee83b53b139cb01af57e7e7ea7687cd1a97cc55ef293703d5500f17c
4
+ data.tar.gz: c67b2363cba3ab789eb20f987775c90f0821105dbbf32ddf3a7e564e77d35d7f
5
5
  SHA512:
6
- metadata.gz: 6936df70b44ba83c191cb2b37a0897fa9caaf00614e3d1caa70d9f033e796eba29b8c9276e90ec8b9523af200d1f18b053c06957cefa3a6b3ab435a91b748c87
7
- data.tar.gz: 0d7f183e24fb26fefed3000b4b7d681bfb51326dd1c7a9e5693fcc940dd077eb5bf31a79fa6ec287a76dd4989c60e135e3b23fb08dbce26a953aefd26d5486d4
6
+ metadata.gz: a93ecd60d0cab2284697e183595fe5caf76c0a137e476551461ee189a81382ec9ea34480b1c3ac78058641aa4ca391d4fd567373bf81c700cc5843a90685aa6a
7
+ data.tar.gz: eefffe552afaf7a461c55a04258714a2204be39b0190c4337f2ed928ffd8ed15e27fd09c9b6f5889fb1e5e4c0162810b850194819542daaa9cef7187072c731c
@@ -1,38 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
  module DiscourseTheme
3
3
  class Cli
4
-
5
- @@prompt = ::TTY::Prompt.new(help_color: :cyan)
6
- @@pastel = Pastel.new
7
-
8
- def self.yes?(message)
9
- @@prompt.yes?(@@pastel.cyan("? ") + message)
10
- end
11
-
12
- def self.ask(message, default: nil)
13
- @@prompt.ask(@@pastel.cyan("? ") + message, default: default)
14
- end
15
-
16
- def self.select(message, options)
17
- @@prompt.select(@@pastel.cyan("? ") + message, options)
18
- end
19
-
20
- def self.info(message)
21
- puts @@pastel.blue("i ") + message
22
- end
23
-
24
- def self.progress(message)
25
- puts @@pastel.yellow("» ") + message
26
- end
27
-
28
- def self.error(message)
29
- puts @@pastel.red("✘ #{message}")
30
- end
31
-
32
- def self.success(message)
33
- puts @@pastel.green("✔ #{message}")
34
- end
35
-
36
4
  SETTINGS_FILE = File.expand_path("~/.discourse_theme")
37
5
 
38
6
  def usage
@@ -63,11 +31,7 @@ module DiscourseTheme
63
31
  if command == "new"
64
32
  raise DiscourseTheme::ThemeError.new "'#{dir} is not empty" if Dir.exists?(dir) && !Dir.empty?(dir)
65
33
  DiscourseTheme::Scaffold.generate(dir)
66
- if Cli.yes?("Would you like to start 'watching' this theme?")
67
- args[0] = "watch"
68
- Cli.progress "Running discourse_theme #{args.join(' ')}"
69
- run(args)
70
- end
34
+ watch_theme?(args)
71
35
  elsif command == "watch"
72
36
  raise DiscourseTheme::ThemeError.new "'#{dir} does not exist" unless Dir.exists?(dir)
73
37
  client = DiscourseTheme::Client.new(dir, settings, reset: reset)
@@ -81,13 +45,13 @@ module DiscourseTheme
81
45
  options["Create and sync with a new theme"] = :create
82
46
  options["Select a different theme"] = :select
83
47
 
84
- choice = Cli.select('How would you like to sync this theme?', options.keys)
48
+ choice = UI.select('How would you like to sync this theme?', options.keys)
85
49
 
86
50
  if options[choice] == :create
87
51
  theme_id = nil
88
52
  elsif options[choice] == :select
89
53
  themes = render_theme_list(theme_list)
90
- choice = Cli.select('Which theme would you like to sync with?', themes)
54
+ choice = UI.select('Which theme would you like to sync with?', themes)
91
55
  theme_id = extract_theme_id(choice)
92
56
  theme = theme_list.find { |t| t["id"] == theme_id }
93
57
  end
@@ -102,27 +66,26 @@ module DiscourseTheme
102
66
  options["Yes"] = :sync
103
67
  options["No"] = :none
104
68
  options = options.sort_by { |_, b| b == components.to_sym ? 0 : 1 }.to_h if components
105
- choice = Cli.select('Would you like to update child theme components?', options.keys)
69
+ choice = UI.select('Would you like to update child theme components?', options.keys)
106
70
  settings.components = components = options[choice].to_s
107
71
  end
108
72
 
109
73
  uploader = DiscourseTheme::Uploader.new(dir: dir, client: client, theme_id: theme_id, components: components)
110
74
 
111
- Cli.progress "Uploading theme from #{dir}"
75
+ UI.progress "Uploading theme from #{dir}"
112
76
  settings.theme_id = theme_id = uploader.upload_full_theme
113
77
 
114
- Cli.success "Theme uploaded (id:#{theme_id})"
115
- Cli.info "Preview: #{client.root}/?preview_theme_id=#{theme_id}"
78
+ UI.success "Theme uploaded (id:#{theme_id})"
79
+ UI.info "Preview: #{client.root}/?preview_theme_id=#{theme_id}"
116
80
  if client.is_theme_creator
117
- Cli.info "Manage: #{client.root}/my/themes"
81
+ UI.info "Manage: #{client.root}/my/themes"
118
82
  else
119
- Cli.info "Manage: #{client.root}/admin/customize/themes/#{theme_id}"
83
+ UI.info "Manage: #{client.root}/admin/customize/themes/#{theme_id}"
120
84
  end
121
85
  watcher = DiscourseTheme::Watcher.new(dir: dir, uploader: uploader)
122
86
 
123
- Cli.progress "Watching for changes in #{dir}..."
87
+ UI.progress "Watching for changes in #{dir}..."
124
88
  watcher.watch
125
-
126
89
  elsif command == "download"
127
90
  client = DiscourseTheme::Client.new(dir, settings, reset: reset)
128
91
  downloader = DiscourseTheme::Downloader.new(dir: dir, client: client)
@@ -130,33 +93,39 @@ module DiscourseTheme
130
93
  FileUtils.mkdir_p dir unless Dir.exists?(dir)
131
94
  raise DiscourseTheme::ThemeError.new "'#{dir} is not empty" unless Dir.empty?(dir)
132
95
 
133
- Cli.progress "Loading theme list..."
96
+ UI.progress "Loading theme list..."
134
97
  themes = render_theme_list(client.get_themes_list)
135
98
 
136
- choice = Cli.select('Which theme would you like to download?', themes)
99
+ choice = UI.select('Which theme would you like to download?', themes)
137
100
  theme_id = extract_theme_id(choice)
138
101
 
139
- Cli.progress "Downloading theme into #{dir}"
102
+ UI.progress "Downloading theme into #{dir}"
140
103
 
141
104
  downloader.download_theme(theme_id)
142
105
  settings.theme_id = theme_id
143
106
 
144
- Cli.success "Theme downloaded"
107
+ UI.success "Theme downloaded"
145
108
 
146
- if Cli.yes?("Would you like to start 'watching' this theme?")
147
- args[0] = "watch"
148
- Cli.progress "Running discourse_theme #{args.join(' ')}"
149
- run(args)
150
- end
109
+ watch_theme?(args)
151
110
  else
152
111
  usage
153
112
  end
154
113
 
155
- Cli.progress "Exiting..."
114
+ UI.progress "Exiting..."
156
115
  rescue DiscourseTheme::ThemeError => e
157
- Cli.error "#{e.message}"
116
+ UI.error "#{e.message}"
158
117
  rescue Interrupt, TTY::Reader::InputInterrupt => e
159
- Cli.error "Interrupted"
118
+ UI.error "Interrupted"
119
+ end
120
+
121
+ private
122
+
123
+ def watch_theme?(args)
124
+ if UI.yes?("Would you like to start 'watching' this theme?")
125
+ args[0] = "watch"
126
+ UI.progress "Running discourse_theme #{args.join(' ')}"
127
+ run(args)
128
+ end
160
129
  end
161
130
 
162
131
  def render_theme_list(themes)
@@ -14,8 +14,8 @@ module DiscourseTheme
14
14
  @is_theme_creator = !!(THEME_CREATOR_REGEX =~ @url)
15
15
 
16
16
  if !self.class.has_needed_version?(discourse_version, "2.3.0.beta1")
17
- Cli.info "discourse_theme is designed for Discourse 2.3.0.beta1 or above"
18
- 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"
19
19
  end
20
20
  end
21
21
 
@@ -142,26 +142,26 @@ module DiscourseTheme
142
142
  def guess_url(settings)
143
143
  url = ENV['DISCOURSE_URL']
144
144
  if url
145
- Cli.progress "Using #{url} from DISCOURSE_URL"
145
+ UI.progress "Using #{url} from DISCOURSE_URL"
146
146
  end
147
147
 
148
148
  if !url && settings.url
149
149
  url = settings.url
150
- Cli.progress "Using #{url} from #{DiscourseTheme::Cli::SETTINGS_FILE}"
150
+ UI.progress "Using #{url} from #{DiscourseTheme::Cli::SETTINGS_FILE}"
151
151
  end
152
152
 
153
153
  if !url || @reset
154
- 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
155
155
  url = "http://#{url}" unless url =~ /^https?:\/\//
156
156
 
157
157
  # maybe this is an HTTPS redirect
158
158
  uri = URI.parse(url)
159
159
  if URI::HTTP === uri && uri.port == 80 && is_https_redirect?(url)
160
- Cli.info "Detected that #{url} should be accessed over https"
160
+ UI.info "Detected that #{url} should be accessed over https"
161
161
  url = url.sub("http", "https")
162
162
  end
163
163
 
164
- 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}?")
165
165
  settings.url = url
166
166
  else
167
167
  settings.url = nil
@@ -174,17 +174,17 @@ module DiscourseTheme
174
174
  def guess_api_key(settings)
175
175
  api_key = ENV['DISCOURSE_API_KEY']
176
176
  if api_key
177
- Cli.progress "Using api key from DISCOURSE_API_KEY"
177
+ UI.progress "Using api key from DISCOURSE_API_KEY"
178
178
  end
179
179
 
180
180
  if !api_key && settings.api_key
181
181
  api_key = settings.api_key
182
- Cli.progress "Using api key from #{DiscourseTheme::Cli::SETTINGS_FILE}"
182
+ UI.progress "Using api key from #{DiscourseTheme::Cli::SETTINGS_FILE}"
183
183
  end
184
184
 
185
185
  if !api_key || @reset
186
- api_key = Cli.ask("What is your API key?", default: api_key).strip
187
- 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}?")
188
188
  settings.api_key = api_key
189
189
  else
190
190
  settings.api_key = nil
@@ -1,75 +1,128 @@
1
1
  # frozen_string_literal: true
2
+
3
+ require 'json'
4
+
2
5
  module DiscourseTheme
3
6
  class Scaffold
4
7
 
5
8
  BLANK_FILES = %w{
6
9
  common/common.scss
7
- common/header.html
8
- common/after_header.html
9
- common/footer.html
10
- common/head_tag.html
11
- common/body_tag.html
12
- common/embedded.scss
13
-
14
- desktop/desktop.scss
15
- desktop/header.html
16
- desktop/after_header.html
17
- desktop/footer.html
18
- desktop/head_tag.html
19
- desktop/body_tag.html
20
-
21
- mobile/mobile.scss
22
- mobile/header.html
23
- mobile/after_header.html
24
- mobile/footer.html
25
- mobile/head_tag.html
26
- mobile/body_tag.html
27
-
28
- locales/en.yml
29
10
 
30
11
  settings.yml
31
12
  }
32
13
 
33
- ABOUT_JSON = <<~STR
34
- {
35
- "name": "#NAME#",
36
- "about_url": null,
37
- "license_url": null,
38
- "assets": {
39
- },
40
- "color_schemes": {
41
- }
14
+ ABOUT_JSON = {
15
+ about_url: nil,
16
+ license_url: nil,
17
+ assets: {}
42
18
  }
43
- STR
44
19
 
45
20
  HELP = <<~STR
46
21
  Are you a bit lost? Be sure to read https://meta.discourse.org/t/how-to-develop-custom-themes/60848
47
22
  STR
48
23
 
49
24
  GIT_IGNORE = <<~STR
50
- .discourse-site
51
- HELP
52
- 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
+ #my_locale_key: My Translation
64
+ theme_metadata:
65
+ description: "#DESCRIPTION"
66
+ settings:
67
+ # my_setting_name: My Setting Description
68
+ YAML
53
69
 
54
70
  def self.generate(dir)
55
- Cli.progress "Generating a scaffold theme at #{dir}"
71
+ UI.progress "Generating a scaffold theme at #{dir}"
56
72
 
57
- name = Cli.ask("What would you like to call your theme?").strip
73
+ name = UI.ask("What would you like to call your theme?").strip
74
+ is_component = UI.yes?("Is this a component?")
58
75
 
59
76
  FileUtils.mkdir_p dir
60
77
  Dir.chdir dir do
61
- File.write('about.json', ABOUT_JSON.sub("#NAME#", name))
78
+ UI.info "Creating about.json"
79
+ about_template = ABOUT_JSON.dup
80
+ about_template[:name] = name
81
+ if is_component
82
+ about_template[:component] = true
83
+ else
84
+ about_template[:color_schemes] = {}
85
+ end
86
+ File.write('about.json', JSON.pretty_generate(about_template))
87
+
88
+ UI.info "Creating HELP"
62
89
  File.write('HELP', HELP)
90
+
91
+ UI.info "Creating package.json"
92
+ author = UI.ask("Who is authoring the theme?").strip
93
+ File.write('package.json', PACKAGE_JSON.sub("#AUTHOR", author))
94
+
95
+ UI.info "Creating .template-lintrc.js"
96
+ File.write('.template-lintrc.js', TEMPLATE_LINT_RC)
97
+
98
+ UI.info "Creating .eslintrc"
99
+ File.write('.eslintrc', ESLINT_RC)
100
+
101
+ UI.info "Creating .gitignore"
63
102
  File.write('.gitignore', GIT_IGNORE)
64
103
 
104
+ locale = "locales/en.yml"
105
+ UI.info "Creating #{locale}"
106
+ FileUtils.mkdir_p(File.dirname(locale))
107
+ description = UI.ask("How would you describe this theme?").strip
108
+ File.write(locale, EN_YML.sub("#DESCRIPTION", description))
109
+
110
+ initializer = "javascripts/discourse/api-initializers/#{name}.js"
111
+ UI.info "Creating #{initializer}"
112
+ FileUtils.mkdir_p(File.dirname(initializer))
113
+ File.write(initializer, API_INITIALIZER)
114
+
65
115
  BLANK_FILES.each do |f|
66
- Cli.info "Creating #{f}"
116
+ UI.info "Creating #{f}"
67
117
  FileUtils.mkdir_p File.dirname(f)
68
118
  FileUtils.touch f
69
119
  end
70
120
 
71
- Cli.info "Initializing git repo"
121
+ UI.info "Initializing git repo"
72
122
  puts `git init .`
123
+
124
+ UI.info "Installing dependencies"
125
+ puts `yarn`
73
126
  end
74
127
  end
75
128
  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
@@ -34,9 +34,9 @@ module DiscourseTheme
34
34
  json["theme"]["theme_fields"].each do |row|
35
35
  if (error = row["error"]) && error.length > 0
36
36
  count += 1
37
- Cli.error ""
38
- Cli.error "Error in #{row["target"]} #{row["name"]}: #{row["error"]}"
39
- Cli.error ""
37
+ UI.error ""
38
+ UI.error "Error in #{row["target"]} #{row["name"]}: #{row["error"]}"
39
+ UI.error ""
40
40
  end
41
41
  end
42
42
  count
@@ -59,7 +59,7 @@ module DiscourseTheme
59
59
  response = @client.update_theme(@theme_id, args)
60
60
  json = JSON.parse(response.body)
61
61
  if diagnose_errors(json) != 0
62
- Cli.error "(end of errors)"
62
+ UI.error "(end of errors)"
63
63
  end
64
64
  end
65
65
 
@@ -73,7 +73,7 @@ module DiscourseTheme
73
73
  json = JSON.parse(response.body)
74
74
  @theme_id = json["theme"]["id"]
75
75
  if diagnose_errors(json) != 0
76
- Cli.error "(end of errors)"
76
+ UI.error "(end of errors)"
77
77
  end
78
78
  @theme_id
79
79
  end
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module DiscourseTheme
3
- VERSION = "0.4.1"
3
+ VERSION = "0.5.0"
4
4
  end
@@ -23,7 +23,7 @@ module DiscourseTheme
23
23
  (resolved = resolve_file(modified[0]))
24
24
 
25
25
  target, name, type_id = resolved
26
- Cli.progress "Fast updating #{target}.scss"
26
+ UI.progress "Fast updating #{target}.scss"
27
27
 
28
28
  @uploader.upload_theme_field(
29
29
  target: target,
@@ -34,17 +34,17 @@ module DiscourseTheme
34
34
  else
35
35
  count = modified.length + added.length + removed.length
36
36
  if count > 1
37
- Cli.progress "Detected changes in #{count} files, uploading theme"
37
+ UI.progress "Detected changes in #{count} files, uploading theme"
38
38
  else
39
39
  filename = modified[0] || added[0] || removed[0]
40
- Cli.progress "Detected changes in #{filename.gsub(@dir, '')}, uploading theme"
40
+ UI.progress "Detected changes in #{filename.gsub(@dir, '')}, uploading theme"
41
41
  end
42
42
  @uploader.upload_full_theme
43
43
  end
44
- Cli.success "Done! Watching for changes..."
44
+ UI.success "Done! Watching for changes..."
45
45
  rescue DiscourseTheme::ThemeError => e
46
- Cli.error "#{e.message}"
47
- Cli.progress "Watching for changes..."
46
+ UI.error "#{e.message}"
47
+ UI.progress "Watching for changes..."
48
48
  end
49
49
  end
50
50
 
@@ -16,6 +16,7 @@ require 'tty/prompt'
16
16
 
17
17
  require 'discourse_theme/version'
18
18
  require 'discourse_theme/config'
19
+ require 'discourse_theme/ui'
19
20
  require 'discourse_theme/cli'
20
21
  require 'discourse_theme/client'
21
22
  require 'discourse_theme/downloader'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: discourse_theme
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.1
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sam Saffron
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-03-11 00:00:00.000000000 Z
11
+ date: 2021-05-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: minitar
@@ -217,6 +217,7 @@ files:
217
217
  - lib/discourse_theme/config.rb
218
218
  - lib/discourse_theme/downloader.rb
219
219
  - lib/discourse_theme/scaffold.rb
220
+ - lib/discourse_theme/ui.rb
220
221
  - lib/discourse_theme/uploader.rb
221
222
  - lib/discourse_theme/version.rb
222
223
  - lib/discourse_theme/watcher.rb
@@ -224,7 +225,7 @@ homepage: https://github.com/discourse/discourse_theme
224
225
  licenses:
225
226
  - MIT
226
227
  metadata: {}
227
- post_install_message:
228
+ post_install_message:
228
229
  rdoc_options: []
229
230
  require_paths:
230
231
  - lib
@@ -239,8 +240,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
239
240
  - !ruby/object:Gem::Version
240
241
  version: '0'
241
242
  requirements: []
242
- rubygems_version: 3.1.4
243
- signing_key:
243
+ rubygems_version: 3.0.3
244
+ signing_key:
244
245
  specification_version: 4
245
246
  summary: CLI helper for creating Discourse themes
246
247
  test_files: []