pagecord-cli 0.2.2 → 0.3.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/README.md +25 -0
- data/lib/pagecord_cli/cli.rb +128 -0
- data/lib/pagecord_cli/client.rb +21 -0
- data/lib/pagecord_cli/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 4e6a9d37234707507835ff1e87b324bccfacc7d680515b9674f0f0fa454cd704
|
|
4
|
+
data.tar.gz: d0628c7e0c4e1273cb24a870f9db83e9ec25da7f01395eae3503f4aa1900f130
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 300fd7fe1c31e8ab0196b8a8c0d8509819ec2d0882ea3bbbc98a4c34d4aaac22d05325a4197b4fcd5f1ff79480566c7d764acbd1ee173926e31c004f4b91b510
|
|
7
|
+
data.tar.gz: d016d8f89cf2150b0a25872543603e19fdf87322ec5a9206c3aa532bf50de98f916df3a83de59c9815d530287ffcddae9236b9f4195ee8ad0c3fb3839b2dede6
|
data/README.md
CHANGED
|
@@ -8,6 +8,12 @@ Publish local Markdown and HTML files to [Pagecord](https://pagecord.com).
|
|
|
8
8
|
gem install pagecord-cli
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
+
Needs Ruby 3.2 or newer. The Ruby that ships with macOS is too old, so:
|
|
12
|
+
|
|
13
|
+
- **macOS**: `brew install ruby`, or a version manager like [mise](https://mise.jdx.dev)
|
|
14
|
+
- **Windows**: [RubyInstaller](https://rubyinstaller.org)
|
|
15
|
+
- **Linux**: your package manager, if it offers 3.2 or newer; otherwise [mise](https://mise.jdx.dev)
|
|
16
|
+
|
|
11
17
|
## Login
|
|
12
18
|
|
|
13
19
|
Generate an API key from **Settings > API** in Pagecord, then save it locally:
|
|
@@ -54,6 +60,25 @@ Remove a saved blog:
|
|
|
54
60
|
pagecord logout myblog
|
|
55
61
|
```
|
|
56
62
|
|
|
63
|
+
## Posts and pages
|
|
64
|
+
|
|
65
|
+
Read and change posts directly, without a local file:
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
pagecord post list # published posts, newest first
|
|
69
|
+
pagecord post list --drafts
|
|
70
|
+
pagecord post show TOKEN # fields, then the HTML content
|
|
71
|
+
pagecord post update TOKEN --content-file post.html --status draft
|
|
72
|
+
pagecord post create --title "Hello" --content-file hello.md
|
|
73
|
+
pagecord post delete TOKEN # add --permanent to skip the bin
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
`pagecord page` takes the same commands. Lists are paged 15 at a time; pass
|
|
77
|
+
`--page N` for more. `--content-file` sends Markdown when the file ends `.md`,
|
|
78
|
+
and HTML otherwise. Other flags: `--title`, `--status draft|published`,
|
|
79
|
+
`--slug`, `--published-at`, `--tags`, `--canonical-url`, `--locale` and
|
|
80
|
+
`--hidden`/`--no-hidden`. `--json` prints the full response.
|
|
81
|
+
|
|
57
82
|
## Choosing a blog
|
|
58
83
|
|
|
59
84
|
With one blog configured, every command uses it. With several, set a default
|
data/lib/pagecord_cli/cli.rb
CHANGED
|
@@ -45,6 +45,8 @@ module PagecordCLI
|
|
|
45
45
|
when "blog" then blog
|
|
46
46
|
when "appearance" then appearance
|
|
47
47
|
when "custom-code" then custom_code
|
|
48
|
+
when "post" then records("posts")
|
|
49
|
+
when "page" then records("pages")
|
|
48
50
|
when "publish" then publish("published")
|
|
49
51
|
when "draft" then publish("draft")
|
|
50
52
|
else
|
|
@@ -193,9 +195,119 @@ module PagecordCLI
|
|
|
193
195
|
|
|
194
196
|
settings = client_for(resolve_blog).update_custom_code(params)
|
|
195
197
|
options[:json] ? print_json(settings) : say("Updated custom code")
|
|
198
|
+
0
|
|
199
|
+
rescue Client::Error => e
|
|
200
|
+
raise unless e.status == 422 && params.key?("custom_css")
|
|
201
|
+
|
|
202
|
+
raise Error, "#{e.message}.\nCommon causes: nested CSS, or @import from a host other than Google Fonts or Bunny Fonts.\nSee https://help.pagecord.com/custom-css"
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
def records(resource)
|
|
206
|
+
noun = resource.chomp("s")
|
|
207
|
+
|
|
208
|
+
case argv.shift
|
|
209
|
+
when "list" then list_records(resource)
|
|
210
|
+
when "show" then show_record(resource)
|
|
211
|
+
when "create" then create_record(resource, noun)
|
|
212
|
+
when "update" then update_record(resource, noun)
|
|
213
|
+
when "delete" then delete_record(resource, noun)
|
|
214
|
+
else fail_with("Usage: pagecord #{noun} list|show|create|update|delete")
|
|
215
|
+
end
|
|
216
|
+
rescue Client::Error => e
|
|
217
|
+
raise unless e.status == 404
|
|
218
|
+
|
|
219
|
+
raise Error, "No #{noun} with that token"
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
def list_records(resource)
|
|
223
|
+
status = nil
|
|
224
|
+
page = nil
|
|
225
|
+
parser do |opts|
|
|
226
|
+
opts.on("--drafts") { status = "draft" }
|
|
227
|
+
opts.on("--published") { status = "published" }
|
|
228
|
+
opts.on("--page N", Integer) { |value| page = value }
|
|
229
|
+
end.parse!(argv)
|
|
230
|
+
|
|
231
|
+
records = client_for(resolve_blog).list(resource, status: status, page: page)
|
|
232
|
+
|
|
233
|
+
if options[:json]
|
|
234
|
+
print_json(records)
|
|
235
|
+
else
|
|
236
|
+
records.each do |record|
|
|
237
|
+
date = record["published_at"].to_s[0, 10]
|
|
238
|
+
output.puts [ record["token"], date.empty? ? record["status"] : date, record["title"] ].join(" ")
|
|
239
|
+
end
|
|
240
|
+
end
|
|
241
|
+
|
|
196
242
|
0
|
|
197
243
|
end
|
|
198
244
|
|
|
245
|
+
def show_record(resource)
|
|
246
|
+
parser.parse!(argv)
|
|
247
|
+
token = argv.shift
|
|
248
|
+
return fail_with("Usage: pagecord #{resource.chomp("s")} show TOKEN") unless token
|
|
249
|
+
|
|
250
|
+
record = client_for(resolve_blog).show(resource, token)
|
|
251
|
+
|
|
252
|
+
if options[:json]
|
|
253
|
+
print_json(record)
|
|
254
|
+
else
|
|
255
|
+
record.except("content").each { |key, value| output.puts "#{key}: #{value.is_a?(Array) ? value.join(", ") : value}" }
|
|
256
|
+
output.puts
|
|
257
|
+
output.puts record["content"]
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
0
|
|
261
|
+
end
|
|
262
|
+
|
|
263
|
+
def create_record(resource, noun)
|
|
264
|
+
params = record_params
|
|
265
|
+
record = client_for(resolve_blog).create(resource, params)
|
|
266
|
+
options[:json] ? print_json(record) : say("Created #{noun} #{record["token"]}")
|
|
267
|
+
0
|
|
268
|
+
end
|
|
269
|
+
|
|
270
|
+
def update_record(resource, noun)
|
|
271
|
+
params = record_params
|
|
272
|
+
token = argv.shift
|
|
273
|
+
return fail_with("Usage: pagecord #{noun} update TOKEN [options]") unless token
|
|
274
|
+
return fail_with("Nothing to update") if params.empty?
|
|
275
|
+
|
|
276
|
+
record = client_for(resolve_blog).update(resource, token, params)
|
|
277
|
+
options[:json] ? print_json(record) : say("Updated #{noun} #{record["token"]}")
|
|
278
|
+
0
|
|
279
|
+
end
|
|
280
|
+
|
|
281
|
+
def delete_record(resource, noun)
|
|
282
|
+
permanent = false
|
|
283
|
+
parser { |opts| opts.on("--permanent") { permanent = true } }.parse!(argv)
|
|
284
|
+
token = argv.shift
|
|
285
|
+
return fail_with("Usage: pagecord #{noun} delete TOKEN [--permanent]") unless token
|
|
286
|
+
|
|
287
|
+
client_for(resolve_blog).delete(resource, token, permanent: permanent)
|
|
288
|
+
say "Deleted #{noun} #{token}"
|
|
289
|
+
0
|
|
290
|
+
end
|
|
291
|
+
|
|
292
|
+
def record_params
|
|
293
|
+
params = {}
|
|
294
|
+
parser do |opts|
|
|
295
|
+
opts.on("--title TITLE") { |value| params[:title] = value }
|
|
296
|
+
opts.on("--content-file PATH") do |path|
|
|
297
|
+
params[:content] = read_file("content-file", path)
|
|
298
|
+
params[:content_format] = "markdown" if PostFile::MARKDOWN_EXTENSIONS.include?(File.extname(path).downcase)
|
|
299
|
+
end
|
|
300
|
+
opts.on("--status STATUS", %w[draft published]) { |value| params[:status] = value }
|
|
301
|
+
opts.on("--slug SLUG") { |value| params[:slug] = value }
|
|
302
|
+
opts.on("--published-at TIME") { |value| params[:published_at] = value }
|
|
303
|
+
opts.on("--tags TAGS") { |value| params[:tags] = value }
|
|
304
|
+
opts.on("--canonical-url URL") { |value| params[:canonical_url] = value }
|
|
305
|
+
opts.on("--[no-]hidden") { |value| params[:hidden] = value }
|
|
306
|
+
opts.on("--locale LOCALE") { |value| params[:locale] = value }
|
|
307
|
+
end.parse!(argv)
|
|
308
|
+
params
|
|
309
|
+
end
|
|
310
|
+
|
|
199
311
|
def publish(status)
|
|
200
312
|
overrides = {}
|
|
201
313
|
parser do |opts|
|
|
@@ -311,6 +423,12 @@ module PagecordCLI
|
|
|
311
423
|
pagecord appearance update [options]
|
|
312
424
|
pagecord custom-code show [--css|--footer-html|--head-html|--body-html]
|
|
313
425
|
pagecord custom-code update [options]
|
|
426
|
+
pagecord post list [--drafts|--published] [--page N]
|
|
427
|
+
pagecord post show TOKEN
|
|
428
|
+
pagecord post create [options]
|
|
429
|
+
pagecord post update TOKEN [options]
|
|
430
|
+
pagecord post delete TOKEN [--permanent]
|
|
431
|
+
pagecord page list|show|create|update|delete (as for post)
|
|
314
432
|
pagecord publish FILE [SUBDOMAIN] [options]
|
|
315
433
|
pagecord draft FILE [SUBDOMAIN] [options]
|
|
316
434
|
|
|
@@ -328,6 +446,13 @@ module PagecordCLI
|
|
|
328
446
|
--hidden
|
|
329
447
|
--locale LOCALE
|
|
330
448
|
|
|
449
|
+
Post and page options:
|
|
450
|
+
--title TITLE
|
|
451
|
+
--content-file PATH (HTML, or Markdown if it ends .md)
|
|
452
|
+
--status draft|published
|
|
453
|
+
--slug, --published-at, --tags, --canonical-url, --locale
|
|
454
|
+
--hidden, --no-hidden
|
|
455
|
+
|
|
331
456
|
Appearance options:
|
|
332
457
|
--theme, --font, --width, --layout
|
|
333
458
|
--custom-theme-bg-light, --custom-theme-text-light, --custom-theme-accent-light
|
|
@@ -337,6 +462,9 @@ module PagecordCLI
|
|
|
337
462
|
Custom code options:
|
|
338
463
|
--css, --footer-html, --head-html, --body-html (each takes a file path)
|
|
339
464
|
--enabled true|false
|
|
465
|
+
|
|
466
|
+
Custom CSS reference:
|
|
467
|
+
https://help.pagecord.com/custom-css
|
|
340
468
|
HELP
|
|
341
469
|
0
|
|
342
470
|
end
|
data/lib/pagecord_cli/client.rb
CHANGED
|
@@ -30,6 +30,27 @@ module PagecordCLI
|
|
|
30
30
|
true
|
|
31
31
|
end
|
|
32
32
|
|
|
33
|
+
def list(resource, status: nil, page: nil)
|
|
34
|
+
query = URI.encode_www_form({ status: status, page: page }.compact)
|
|
35
|
+
request(Net::HTTP::Get.new(uri_for(query.empty? ? resource : "#{resource}?#{query}")))
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def show(resource, token)
|
|
39
|
+
request(Net::HTTP::Get.new(uri_for("#{resource}/#{token}")))
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def create(resource, params)
|
|
43
|
+
request(json_request(Net::HTTP::Post, resource, params))
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def update(resource, token, params)
|
|
47
|
+
request(json_request(Net::HTTP::Patch, "#{resource}/#{token}", params))
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def delete(resource, token, permanent: false)
|
|
51
|
+
request(Net::HTTP::Delete.new(uri_for("#{resource}/#{token}#{"?permanent=true" if permanent}")))
|
|
52
|
+
end
|
|
53
|
+
|
|
33
54
|
def create_post(params)
|
|
34
55
|
request(json_request(Net::HTTP::Post, "/posts", params))
|
|
35
56
|
end
|
data/lib/pagecord_cli/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: pagecord-cli
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.3.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Olly Headey
|
|
@@ -46,7 +46,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
46
46
|
- !ruby/object:Gem::Version
|
|
47
47
|
version: '0'
|
|
48
48
|
requirements: []
|
|
49
|
-
rubygems_version: 4.0.
|
|
49
|
+
rubygems_version: 4.0.16
|
|
50
50
|
specification_version: 4
|
|
51
51
|
summary: Publish local files to Pagecord
|
|
52
52
|
test_files: []
|