discourse_theme 0.4.1 → 0.6.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 +4 -4
- data/lib/discourse_theme/cli.rb +44 -60
- data/lib/discourse_theme/client.rb +18 -12
- data/lib/discourse_theme/scaffold.rb +109 -41
- data/lib/discourse_theme/ui.rb +35 -0
- data/lib/discourse_theme/uploader.rb +5 -5
- data/lib/discourse_theme/version.rb +1 -1
- data/lib/discourse_theme/watcher.rb +6 -6
- data/lib/discourse_theme.rb +9 -8
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d0626e7865ec3b7d06ae9e198351dfd51f111897393bf393aa7da26b52c19777
|
4
|
+
data.tar.gz: 77856b459abd70854c9350960d98eb0887420222732390a22f4f52b69fbcd691
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: adf9a56c7ffb98ea9b14df04220096105c0b2e63074e4dc789984a1c9c01e6162b7118651cb9e1b95ed8a8c64740d97358d5c3fa7fb7614c3ca8416126c8d1dc
|
7
|
+
data.tar.gz: 1550d47250f811999035af55efc28dd3a081a22a5f9961a9e2fdfe9ee522a688de402064ed9df339a6c67395bf41ba6eb76b9db812d8bde4470f8dba8e178e40
|
data/lib/discourse_theme/cli.rb
CHANGED
@@ -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
|
@@ -61,13 +29,12 @@ module DiscourseTheme
|
|
61
29
|
components = settings.components
|
62
30
|
|
63
31
|
if command == "new"
|
64
|
-
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
|
+
|
65
36
|
DiscourseTheme::Scaffold.generate(dir)
|
66
|
-
|
67
|
-
args[0] = "watch"
|
68
|
-
Cli.progress "Running discourse_theme #{args.join(' ')}"
|
69
|
-
run(args)
|
70
|
-
end
|
37
|
+
watch_theme?(args)
|
71
38
|
elsif command == "watch"
|
72
39
|
raise DiscourseTheme::ThemeError.new "'#{dir} does not exist" unless Dir.exists?(dir)
|
73
40
|
client = DiscourseTheme::Client.new(dir, settings, reset: reset)
|
@@ -81,13 +48,13 @@ module DiscourseTheme
|
|
81
48
|
options["Create and sync with a new theme"] = :create
|
82
49
|
options["Select a different theme"] = :select
|
83
50
|
|
84
|
-
choice =
|
51
|
+
choice = UI.select('How would you like to sync this theme?', options.keys)
|
85
52
|
|
86
53
|
if options[choice] == :create
|
87
54
|
theme_id = nil
|
88
55
|
elsif options[choice] == :select
|
89
56
|
themes = render_theme_list(theme_list)
|
90
|
-
choice =
|
57
|
+
choice = UI.select('Which theme would you like to sync with?', themes)
|
91
58
|
theme_id = extract_theme_id(choice)
|
92
59
|
theme = theme_list.find { |t| t["id"] == theme_id }
|
93
60
|
end
|
@@ -102,27 +69,26 @@ module DiscourseTheme
|
|
102
69
|
options["Yes"] = :sync
|
103
70
|
options["No"] = :none
|
104
71
|
options = options.sort_by { |_, b| b == components.to_sym ? 0 : 1 }.to_h if components
|
105
|
-
choice =
|
72
|
+
choice = UI.select('Would you like to update child theme components?', options.keys)
|
106
73
|
settings.components = components = options[choice].to_s
|
107
74
|
end
|
108
75
|
|
109
76
|
uploader = DiscourseTheme::Uploader.new(dir: dir, client: client, theme_id: theme_id, components: components)
|
110
77
|
|
111
|
-
|
78
|
+
UI.progress "Uploading theme from #{dir}"
|
112
79
|
settings.theme_id = theme_id = uploader.upload_full_theme
|
113
80
|
|
114
|
-
|
115
|
-
|
81
|
+
UI.success "Theme uploaded (id:#{theme_id})"
|
82
|
+
UI.info "Preview: #{client.root}/?preview_theme_id=#{theme_id}"
|
116
83
|
if client.is_theme_creator
|
117
|
-
|
84
|
+
UI.info "Manage: #{client.root}/my/themes"
|
118
85
|
else
|
119
|
-
|
86
|
+
UI.info "Manage: #{client.root}/admin/customize/themes/#{theme_id}"
|
120
87
|
end
|
121
88
|
watcher = DiscourseTheme::Watcher.new(dir: dir, uploader: uploader)
|
122
89
|
|
123
|
-
|
90
|
+
UI.progress "Watching for changes in #{dir}..."
|
124
91
|
watcher.watch
|
125
|
-
|
126
92
|
elsif command == "download"
|
127
93
|
client = DiscourseTheme::Client.new(dir, settings, reset: reset)
|
128
94
|
downloader = DiscourseTheme::Downloader.new(dir: dir, client: client)
|
@@ -130,33 +96,51 @@ module DiscourseTheme
|
|
130
96
|
FileUtils.mkdir_p dir unless Dir.exists?(dir)
|
131
97
|
raise DiscourseTheme::ThemeError.new "'#{dir} is not empty" unless Dir.empty?(dir)
|
132
98
|
|
133
|
-
|
99
|
+
UI.progress "Loading theme list..."
|
134
100
|
themes = render_theme_list(client.get_themes_list)
|
135
101
|
|
136
|
-
choice =
|
102
|
+
choice = UI.select('Which theme would you like to download?', themes)
|
137
103
|
theme_id = extract_theme_id(choice)
|
138
104
|
|
139
|
-
|
105
|
+
UI.progress "Downloading theme into #{dir}"
|
140
106
|
|
141
107
|
downloader.download_theme(theme_id)
|
142
108
|
settings.theme_id = theme_id
|
143
109
|
|
144
|
-
|
110
|
+
UI.success "Theme downloaded"
|
145
111
|
|
146
|
-
|
147
|
-
args[0] = "watch"
|
148
|
-
Cli.progress "Running discourse_theme #{args.join(' ')}"
|
149
|
-
run(args)
|
150
|
-
end
|
112
|
+
watch_theme?(args)
|
151
113
|
else
|
152
114
|
usage
|
153
115
|
end
|
154
116
|
|
155
|
-
|
117
|
+
UI.progress "Exiting..."
|
156
118
|
rescue DiscourseTheme::ThemeError => e
|
157
|
-
|
119
|
+
UI.error "#{e.message}"
|
158
120
|
rescue Interrupt, TTY::Reader::InputInterrupt => e
|
159
|
-
|
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
|
160
144
|
end
|
161
145
|
|
162
146
|
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
|
-
|
18
|
-
|
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
|
|
@@ -105,7 +105,7 @@ module DiscourseTheme
|
|
105
105
|
end
|
106
106
|
|
107
107
|
def root
|
108
|
-
@url
|
108
|
+
URI.parse(@url).path
|
109
109
|
end
|
110
110
|
|
111
111
|
def is_theme_creator
|
@@ -116,6 +116,12 @@ module DiscourseTheme
|
|
116
116
|
|
117
117
|
def request(request, never_404: false)
|
118
118
|
uri = URI.parse(@url)
|
119
|
+
|
120
|
+
if uri.userinfo
|
121
|
+
username, password = uri.userinfo.split(":", 2)
|
122
|
+
request.basic_auth username, password
|
123
|
+
end
|
124
|
+
|
119
125
|
http = Net::HTTP.new(uri.host, uri.port)
|
120
126
|
http.use_ssl = URI::HTTPS === uri
|
121
127
|
add_headers(request)
|
@@ -142,26 +148,26 @@ module DiscourseTheme
|
|
142
148
|
def guess_url(settings)
|
143
149
|
url = ENV['DISCOURSE_URL']
|
144
150
|
if url
|
145
|
-
|
151
|
+
UI.progress "Using #{url} from DISCOURSE_URL"
|
146
152
|
end
|
147
153
|
|
148
154
|
if !url && settings.url
|
149
155
|
url = settings.url
|
150
|
-
|
156
|
+
UI.progress "Using #{url} from #{DiscourseTheme::Cli::SETTINGS_FILE}"
|
151
157
|
end
|
152
158
|
|
153
159
|
if !url || @reset
|
154
|
-
url =
|
160
|
+
url = UI.ask("What is the root URL of your Discourse site?", default: url).strip
|
155
161
|
url = "http://#{url}" unless url =~ /^https?:\/\//
|
156
162
|
|
157
163
|
# maybe this is an HTTPS redirect
|
158
164
|
uri = URI.parse(url)
|
159
165
|
if URI::HTTP === uri && uri.port == 80 && is_https_redirect?(url)
|
160
|
-
|
166
|
+
UI.info "Detected that #{url} should be accessed over https"
|
161
167
|
url = url.sub("http", "https")
|
162
168
|
end
|
163
169
|
|
164
|
-
if
|
170
|
+
if UI.yes?("Would you like this site name stored in #{DiscourseTheme::Cli::SETTINGS_FILE}?")
|
165
171
|
settings.url = url
|
166
172
|
else
|
167
173
|
settings.url = nil
|
@@ -174,17 +180,17 @@ module DiscourseTheme
|
|
174
180
|
def guess_api_key(settings)
|
175
181
|
api_key = ENV['DISCOURSE_API_KEY']
|
176
182
|
if api_key
|
177
|
-
|
183
|
+
UI.progress "Using api key from DISCOURSE_API_KEY"
|
178
184
|
end
|
179
185
|
|
180
186
|
if !api_key && settings.api_key
|
181
187
|
api_key = settings.api_key
|
182
|
-
|
188
|
+
UI.progress "Using api key from #{DiscourseTheme::Cli::SETTINGS_FILE}"
|
183
189
|
end
|
184
190
|
|
185
191
|
if !api_key || @reset
|
186
|
-
api_key =
|
187
|
-
if
|
192
|
+
api_key = UI.ask("What is your API key?", default: api_key).strip
|
193
|
+
if UI.yes?("Would you like this API key stored in #{DiscourseTheme::Cli::SETTINGS_FILE}?")
|
188
194
|
settings.api_key = api_key
|
189
195
|
else
|
190
196
|
settings.api_key = nil
|
@@ -1,75 +1,143 @@
|
|
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 =
|
34
|
-
|
35
|
-
|
36
|
-
|
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
|
-
|
51
|
-
|
52
|
-
|
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
|
53
66
|
|
54
67
|
def self.generate(dir)
|
55
|
-
|
68
|
+
UI.progress "Generating a scaffold theme at #{dir}"
|
56
69
|
|
57
|
-
name =
|
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?")
|
58
80
|
|
59
81
|
FileUtils.mkdir_p dir
|
60
82
|
Dir.chdir dir do
|
61
|
-
|
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"
|
62
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"
|
63
117
|
File.write('.gitignore', GIT_IGNORE)
|
64
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
|
+
|
65
130
|
BLANK_FILES.each do |f|
|
66
|
-
|
131
|
+
UI.info "Creating #{f}"
|
67
132
|
FileUtils.mkdir_p File.dirname(f)
|
68
133
|
FileUtils.touch f
|
69
134
|
end
|
70
135
|
|
71
|
-
|
72
|
-
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`
|
73
141
|
end
|
74
142
|
end
|
75
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
|
@@ -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
|
-
|
38
|
-
|
39
|
-
|
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
|
-
|
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
|
-
|
76
|
+
UI.error "(end of errors)"
|
77
77
|
end
|
78
78
|
@theme_id
|
79
79
|
end
|
@@ -23,7 +23,7 @@ module DiscourseTheme
|
|
23
23
|
(resolved = resolve_file(modified[0]))
|
24
24
|
|
25
25
|
target, name, type_id = resolved
|
26
|
-
|
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
|
-
|
37
|
+
UI.progress "Detected changes in #{count} files, uploading theme"
|
38
38
|
else
|
39
39
|
filename = modified[0] || added[0] || removed[0]
|
40
|
-
|
40
|
+
UI.progress "Detected changes in #{filename.gsub(@dir, '')}, uploading theme"
|
41
41
|
end
|
42
42
|
@uploader.upload_full_theme
|
43
43
|
end
|
44
|
-
|
44
|
+
UI.success "Done! Watching for changes..."
|
45
45
|
rescue DiscourseTheme::ThemeError => e
|
46
|
-
|
47
|
-
|
46
|
+
UI.error "#{e.message}"
|
47
|
+
UI.progress "Watching for changes..."
|
48
48
|
end
|
49
49
|
end
|
50
50
|
|
data/lib/discourse_theme.rb
CHANGED
@@ -14,14 +14,15 @@ require 'json'
|
|
14
14
|
require 'yaml'
|
15
15
|
require 'tty/prompt'
|
16
16
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
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'
|
25
26
|
|
26
27
|
module DiscourseTheme
|
27
28
|
class ThemeError < StandardError; end
|
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
|
+
version: 0.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sam Saffron
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-11-23 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
|
@@ -239,7 +240,7 @@ 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.
|
243
|
+
rubygems_version: 3.1.6
|
243
244
|
signing_key:
|
244
245
|
specification_version: 4
|
245
246
|
summary: CLI helper for creating Discourse themes
|