robin_cms 0.1.4 → 0.1.6

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: d3a49ee1ef9d638a300e82352bba65071dc6dfffecfb4cb409fbf8cbb8fbdd69
4
- data.tar.gz: 928887dfc693144ebaaf9f2233a08b161faa7146ab7a037501098052d046fe74
3
+ metadata.gz: 6a9634aa2592fdf851123491cc53c9b1b347b6e6ca3f7f37d4adbd9e0fb494c7
4
+ data.tar.gz: 3885036d121802207eb4ae9cf80c372211ee199f60fa30c7e11f5b916af5c570
5
5
  SHA512:
6
- metadata.gz: 17bcd5f6cc1d057c6740fb3d7cf393432cd823956fcf4e78421b085cfc1ec3ef382c40b776b5f570cfb295af6cae71fd8a0711e5accc118641509bc519947bd9
7
- data.tar.gz: e7f2f736f7535dce94edbe15a41c24201959e1231d0827c542ec3b4560215d1285e49f1d94321a57bdca50c1cfd85015f8a11f74cbd952b967081e7f5b3291a3
6
+ metadata.gz: f38e98b366edb3294b56e2b97c80819149163020d41dd565e893ec3d4d8c84f2332f108de62858a9d55bf135176bf8f042ee28980bd1eb6f6d6ddaf7d330f210
7
+ data.tar.gz: 29d90d7896c8366dbe5373bdd89193d4dcd336577cd8c517d2b5b5082b1aa65ffef18c0b733b5387bb9bf53405c8fcf77b8afdb700e1a682c98bc37ae1c51540
data/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
  > This software is currently in beta. There may be bugs and breaking changes.
5
5
  > If you find a bug, I'd love to hear about it.
6
6
 
7
- ![Robin CMS logo](./assets/robin-logo.png)
7
+ ![Robin CMS logo](./doc/assets/robin-logo.png)
8
8
 
9
9
  Robin CMS is a minimalist flat-file CMS built with Ruby and Sinatra. It is
10
10
  designed to be used by developers for creating custom built websites where the
@@ -61,125 +61,53 @@ that are commonly found in CMS software have been omitted.
61
61
  content. You can however add richtext fields to your content models (see
62
62
  example below).
63
63
 
64
- ## Installation
65
-
66
- Just the usual incantation:
67
-
68
- ```sh
69
- gem install robin_cms
70
- ```
71
-
72
- ## Configuring
73
-
74
- You can define your content model in a `_cms.yml` file like this:
75
-
76
- ```yml
77
- url: https://example.com
78
- title: Example
79
- libraries:
80
- - id: poem
81
- type: collection
82
- label: Poem
83
- location: poems
84
- filetype: html
85
- fields:
86
- - { label: Title, id: title, type: input }
87
- - { label: Author, id: author_name, type: input }
88
- - { label: Content, id: content, type: richtext }
89
- - id: book
90
- type: data
91
- label: Book
92
- location: books
93
- filetype: yml
94
- fields:
95
- - { label: Title, id: title, type: input }
96
- - { label: Author, id: author_name, type: input }
97
- ```
98
-
99
- The admin username and password needs to be set in a `.htpasswd` file in the
100
- root directory of the project. Obviously make sure you `.gitignore` that file.
101
- Also make sure your static site generator is ignoring it because you don't want
102
- it in your public directory! Each line of the `.htpasswd` file should follow
103
- the format `<username>:<password>`, but note that only a single
104
- username/password is supported for now. The password needs to be encrypted with
105
- bcrypt. You can do this in Ruby with the `bcrypt` gem:
106
-
107
- ```sh
108
- ruby -r bcrypt -e "puts BCrypt::Password.create('mypassword')"
109
- ```
110
-
111
- Another thing to note is that if no `.htpasswd` file is found, it will
112
- automatically create one with username "admin" and password "admin". This lets
113
- you play around with it locally without configuring a password. So make sure
114
- you create a `.htpasswd` file before running it in production!
115
-
116
- You'll also need to expose a `SESSION_SECRET` environment variable. If you
117
- don't, it will create one for you, but it creates a new secret each time
118
- the server starts, meaning you will have to log in again whenever you restart
119
- the server. It is recommended to create one via Ruby's SecureRandom package.
120
-
121
- ```sh
122
- ruby -r securerandom -e "puts SecureRandom.hex(64)"
123
- ```
124
-
125
- See the [examples](./examples) folder for a full example. I haven't written any
126
- documentation yet, but the example `_cms.yml` file is thoroughly commented to
127
- explain each of the fields.
128
-
129
64
  ## Usage
130
65
 
131
- You have a few options for using this gem in your project. Firstly, you can use
132
- it directly as a CMS for any Static Site Generator with the following
133
- `config.ru`:
134
-
135
- ```ruby
136
- require 'robin_cms'
137
- map "/admin" { run RobinCMS::CMS.new }
138
- ```
66
+ Robin CMS is packaged as a Ruby gem, so installation is as simple as
139
67
 
140
- Now you should be able to run `rackup`, and go to `http://localhost:9292/admin`
141
- in your browser.
68
+ gem install robin_cms
142
69
 
143
- Alternatively, you can embed it into your own Sinatra project like this:
70
+ It's possible to use the CMS in a few different ways. You can use it as a
71
+ standalone CMS for any Static Site Generator, you can embed it in a dynamic
72
+ Sinatra app, or you can use it as a Jekyll plugin. If you're already using
73
+ Jekyll as your SSG, this is the simplest approach.
144
74
 
145
- ```ruby
146
- require 'robin_cms'
147
- require 'sinatra'
75
+ See the [documentation](./docs/index.adoc) for further information on usage.
148
76
 
149
- use RobinCMS::CMS
150
-
151
- get '/' do
152
- 'Hello, world!'
153
- end
154
-
155
- run Sinatra::Application.new
156
- ```
157
-
158
- Yet another option is to use it as a [Jekyll](https://jekyllrb.com/) plugin. To
159
- do this, you just need to pop `robin_cms` in the `:jekyll_plugins` group of
160
- your `Gemfile` like so:
161
-
162
- ```
163
- gem "jekyll"
164
-
165
- group :jekyll_plugins do
166
- gem "robin_cms"
167
- end
168
- ```
77
+ ## Configuring
169
78
 
170
- After running `bundle exec jekyll serve`, the CMS should be available on your
171
- website under `/admin`. Note that if using it as a Jekyll plugin, you can put
172
- your config in Jekyll's `_config.yml` file under the `cms` field. You also
173
- don't need to specify the `url` and `title` fields, as these are taken from the
174
- Jekyll config.
79
+ Your content model is defined in a single YAML file. It acts as a sort of
80
+ schema for your content. An example YAML file looks like this:
81
+
82
+ url: https://example.com
83
+ title: Example
84
+ libraries:
85
+ - id: poem
86
+ type: collection
87
+ label: Poem
88
+ location: poems
89
+ filetype: html
90
+ fields:
91
+ - { label: Title, id: title, type: input }
92
+ - { label: Author, id: author_name, type: input }
93
+ - { label: Content, id: content, type: richtext }
94
+ - id: book
95
+ type: data
96
+ label: Book
97
+ location: books
98
+ filetype: yml
99
+ fields:
100
+ - { label: Title, id: title, type: input }
101
+ - { label: Author, id: author_name, type: input }
102
+
103
+ See the [docs](./docs/index.adoc) for more details on configuration. You can
104
+ also find some examples [here](./examples).
175
105
 
176
106
  ## Testing
177
107
 
178
108
  Unit test are written in RSpec. To run them:
179
109
 
180
- ```
181
- rspec
182
- ```
110
+ rake test
183
111
 
184
112
  ## Roadmap
185
113
 
data/lib/robin_cms/cms.rb CHANGED
@@ -18,25 +18,18 @@ module RobinCMS
18
18
  set :session_secret, ENV.fetch("SESSION_SECRET", SecureRandom.hex(64))
19
19
 
20
20
  before do
21
- if %w[/login /logout].include?(request.path_info)
22
- pass
23
- end
21
+ pass if %w[/login /logout].include?(request.path_info)
24
22
 
25
23
  redirect to("/login") unless session[:auth_user]
26
24
  end
27
25
 
28
26
  before /\/libraries\/(.*).*/ do
29
27
  kind = params[:captures].first.split("/").first
30
- library_schema = @config.find_library(kind)
28
+ library_schema = @config.get_schema(kind)
31
29
 
32
30
  halt 404 unless library_schema
33
31
 
34
- @library = case library_schema[:type]
35
- when "collection"
36
- CollectionLibrary.new(library_schema)
37
- when "data"
38
- DataLibrary.new(library_schema)
39
- end
32
+ @library = Library.new(library_schema)
40
33
  end
41
34
 
42
35
  after do
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RobinCMS
4
- class CollectionLibrary < Library
4
+ module CollectionLibrary
5
5
  def create(attributes)
6
6
  id = make_slug(attributes[:title], @schema[:pattern])
7
7
  item = Item.new(id, attributes, **@schema)
@@ -69,6 +69,7 @@
69
69
  "options": { "$ref": "#/$defs/options_schema" },
70
70
  "dimensions": { "$ref": "#/$defs/image_dimensions_schema" },
71
71
  "filetype": { "$ref": "#/$defs/image_filetype_schema" },
72
+ "description": { "type": "string" },
72
73
  "order": { "type": "number" }
73
74
  }
74
75
  }
@@ -108,7 +109,8 @@
108
109
  "readonly": { "type": "boolean" },
109
110
  "options": { "$ref": "#/$defs/options_schema" },
110
111
  "dimensions": { "$ref": "#/$defs/image_dimensions_schema" },
111
- "filetype": { "$ref": "#/$defs/image_filetype_schema" }
112
+ "filetype": { "$ref": "#/$defs/image_filetype_schema" },
113
+ "description": { "type": "string" }
112
114
  }
113
115
  }
114
116
  }
@@ -42,6 +42,7 @@ module RobinCMS
42
42
  id: "title",
43
43
  type: "text",
44
44
  required: true,
45
+ description: "Provide a short, descriptive title.",
45
46
  order: 1
46
47
  }, {
47
48
  label: "Published date",
@@ -65,6 +66,9 @@ module RobinCMS
65
66
  label: "Published",
66
67
  value: true
67
68
  }],
69
+ description: "Set this to draft if you're not ready to publish this item
70
+ just yet. Draft items won't appear on your website, even after clicking
71
+ 'Publish site'.",
68
72
  order: 2
69
73
  }].freeze
70
74
 
@@ -74,7 +78,9 @@ module RobinCMS
74
78
  }, {
75
79
  id: "image_alt",
76
80
  type: "text",
77
- label: "Alt text"
81
+ label: "Alt text",
82
+ description: "Provide a descriptive and concise description of your
83
+ image. This helps to improve the accessibility of your website."
78
84
  }].freeze
79
85
 
80
86
  def self.parse(config_file: "_cms.yml", jekyll_plugin: false)
@@ -101,7 +107,7 @@ module RobinCMS
101
107
  hash.each_with_object(new) { |(k, v), h| h[k] = v }
102
108
  end
103
109
 
104
- def find_library(kind)
110
+ def get_schema(kind)
105
111
  self[:libraries].find { |library| library[:id] == kind }
106
112
  end
107
113
 
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RobinCMS
4
- class DataLibrary < Library
4
+ module DataLibrary
5
5
  def create(attributes)
6
6
  item = Item.new(nil, attributes, **@schema)
7
7
  write(item)
@@ -2,20 +2,20 @@
2
2
 
3
3
  module RobinCMS
4
4
  class Item
5
- attr_reader :id, :attributes
5
+ attr_reader :id, :attributes, :schema
6
6
 
7
7
  DATETIME_FORMAT = "%Y-%m-%d"
8
8
 
9
9
  # The keys which we don't want to serialize.
10
10
  FRONTMATTER_IGNORE_KEYS = [:id, :content, :image, :captures].freeze
11
11
 
12
- def initialize(id, attrs = {}, **opts)
12
+ def initialize(id, attrs = {}, **schema)
13
13
  if !attrs.empty? && !attrs.has_key?(:title)
14
14
  raise TypeError, "Missing required field `title'"
15
15
  end
16
16
 
17
17
  @id = id
18
- @opts = opts
18
+ @schema = schema
19
19
 
20
20
  # Be sure to use the setter here so the keys get converted to symbols.
21
21
  self.attributes = attrs
@@ -71,9 +71,9 @@ module RobinCMS
71
71
  end
72
72
 
73
73
  def display_name
74
- return @attributes[:title] unless @opts[:display_name_pattern]
74
+ return @attributes[:title] unless @schema[:display_name_pattern]
75
75
 
76
- @opts[:display_name_pattern].clone.tap do |name|
76
+ @schema[:display_name_pattern].clone.tap do |name|
77
77
  @attributes.each { |key, value| name.gsub!(":#{key}", value) }
78
78
  end
79
79
  end
@@ -96,9 +96,14 @@ module RobinCMS
96
96
  frontmatter.to_h.transform_keys(&:to_s)
97
97
  end
98
98
 
99
- def field_value_or_default(field)
99
+ def field_value_or_default(field_id)
100
+ field = @schema[:fields].find { |f| f[:id] == field_id }
100
101
  value = @attributes[field[:id].to_sym] || field[:default]
101
102
  value.to_s
102
103
  end
104
+
105
+ def can_delete?
106
+ @id && @schema[:can_delete]
107
+ end
103
108
  end
104
109
  end
@@ -8,38 +8,27 @@ module RobinCMS
8
8
 
9
9
  attr_reader :schema
10
10
 
11
+ def self.of_kind(kind, **opts)
12
+ config = Configuration.parse(**opts)
13
+ schema = config.get_schema(kind)
14
+ new(schema)
15
+ end
16
+
11
17
  def initialize(schema)
12
18
  @schema = schema.freeze
19
+
20
+ case schema[:type]
21
+ when "collection"
22
+ extend CollectionLibrary
23
+ when "data"
24
+ extend DataLibrary
25
+ end
13
26
  end
14
27
 
15
28
  def blank
16
29
  Item.new(nil, **@schema)
17
30
  end
18
31
 
19
- def create(attributes)
20
- raise NotImplementedError
21
- end
22
-
23
- def find_one(id)
24
- raise NotImplementedError
25
- end
26
-
27
- def all
28
- raise NotImplementedError
29
- end
30
-
31
- # Writes the specified item to disk.
32
- #
33
- # Returns the path where the item was written.
34
- def write(item)
35
- raise NotImplementedError
36
- end
37
-
38
- # Delete the item specified by +id+.
39
- def delete(id)
40
- raise NotImplementedError
41
- end
42
-
43
32
  def create_static(filename, tempfile)
44
33
  path = File.join(@schema[:static_location], File.basename(make_slug(filename)))
45
34
  FileUtils.mkdir_p(File.dirname(path))
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RobinCMS
4
- VERSION = "0.1.4"
4
+ VERSION = "0.1.6"
5
5
  end
@@ -0,0 +1,9 @@
1
+ <label for="<%= safe_id(field[:id], 'field') %>">
2
+ <%= field[:label] %>
3
+ <% unless field[:required] %>
4
+ <small>(optional)</small>
5
+ <% end %>
6
+ </label>
7
+ <% if field[:description] %>
8
+ <small><%= field[:description] %></small>
9
+ <% end %>
@@ -2,5 +2,5 @@
2
2
  id="<%= safe_id(field[:id], 'field') %>"
3
3
  type="hidden"
4
4
  name="<%= field[:id] %>"
5
- value="<%= @item.field_value_or_default(field) %>"
5
+ value="<%= @item.field_value_or_default(field[:id]) %>"
6
6
  />
@@ -1,9 +1,12 @@
1
- <label for="<%= safe_id('image', 'field') %>"><%= field[:label] %></label>
1
+ <%= erb :field_label, locals: { field: field } %>
2
2
  <%#
3
3
  There is a bug here where if you upload a different image with the
4
4
  same name, it shows the old image due to caching. This is a very
5
5
  low priority because a) the user should be naming things in a
6
6
  reasonable way and b) you can always just do a hard refresh.
7
+
8
+ Also required does nothing here as we're not populating the field with any
9
+ initial values. This one probably needs to be fixed.
7
10
  %>
8
11
  <img
9
12
  id="image-preview"
@@ -15,6 +18,5 @@
15
18
  id="<%= safe_id('image', 'field') %>"
16
19
  type="file"
17
20
  name="image"
18
- accept="image/png, image/jpeg"
19
- <% if field[:required] %>required<% end %>
21
+ accept="image/png,image/jpeg"
20
22
  />
@@ -1,9 +1,9 @@
1
- <label for="<%= safe_id(field[:id], 'field') %>"><%= field[:label] %></label>
1
+ <%= erb :field_label, locals: { field: field } %>
2
2
  <input
3
3
  id="<%= safe_id(field[:id], 'field') %>"
4
4
  type="<%= field[:type] %>"
5
5
  name="<%= field[:id] %>"
6
- value="<%= @item.field_value_or_default(field) %>"
6
+ value="<%= @item.field_value_or_default(field[:id]) %>"
7
7
  <% if field[:required] %>required<% end %>
8
8
  <% if field[:readonly] %>readonly<% end %>
9
9
  />
@@ -28,12 +28,12 @@
28
28
  <table>
29
29
  <thead>
30
30
  <tr>
31
- <th class="grow-column">Name</th>
31
+ <th>Name</th>
32
32
  <% if @library.drafts_enabled? %>
33
33
  <th>Status</th>
34
34
  <% end %>
35
- <th>Created</th>
36
- <th>Last updated</th>
35
+ <th class="date">Created</th>
36
+ <th class="date">Last updated</th>
37
37
  </tr>
38
38
  </thead>
39
39
  <tbody>
@@ -53,12 +53,12 @@
53
53
  </a>
54
54
  </td>
55
55
  <% end %>
56
- <td>
56
+ <td class="date">
57
57
  <a href='<%= url("/libraries/#{@library.kind}/item/#{item.id}") %>'>
58
58
  <%= item.created_at.strftime("%b %d, %Y") %>
59
59
  </a>
60
60
  </td>
61
- <td>
61
+ <td class="date">
62
62
  <a href='<%= url("/libraries/#{@library.kind}/item/#{item.id}") %>'>
63
63
  <%= item.updated_at.strftime("%b %d, %Y") %>
64
64
  </a>
@@ -1,6 +1,6 @@
1
1
  <span class="controls">
2
2
  <a href='<%= url("/libraries/#{@library.kind}") %>'>Back</a>
3
- <button type="submit">Save</button>
3
+ <button form="<%= safe_id(@item.id, 'edit_item') %>" type="submit">Save</button>
4
4
  <% if has_delete %>
5
5
  <%= erb :delete_dialog %>
6
6
  <% end %>
@@ -2,9 +2,10 @@
2
2
  <h2>
3
3
  <% if @item.id %>Edit<% else %>New<% end %> <%= @library[:label_singular].downcase %>
4
4
  </h2>
5
- <%= erb :library_actions, locals: { has_delete: @library[:can_delete] && @item.id } %>
5
+ <%= erb :library_actions, locals: { has_delete: @item.can_delete? } %>
6
6
  </header>
7
7
  <form
8
+ id="<%= safe_id(@item.id, 'edit_item') %>"
8
9
  class="card"
9
10
  <% if @item.id %>
10
11
  action='<%= url("/libraries/#{@library.kind}/item/#{@item.id}") %>'
@@ -1,10 +1,10 @@
1
1
  <link rel="stylesheet" type="text/css" href="https://unpkg.com/trix@2.0.8/dist/trix.css">
2
2
  <script type="text/javascript" src="https://unpkg.com/trix@2.0.8/dist/trix.umd.min.js"></script>
3
- <label for="<%= safe_id(field[:id], 'field') %>"><%= field[:label] %></label>
3
+ <%= erb :field_label, locals: { field: field } %>
4
4
  <input
5
5
  id="richtext-content"
6
6
  type="hidden"
7
7
  name="<%= field[:id] %>"
8
- value="<%= @item.field_value_or_default(field) %>"
8
+ value="<%= @item.field_value_or_default(field[:id]) %>"
9
9
  >
10
10
  <trix-editor input="richtext-content"></trix-editor>
@@ -1,8 +1,8 @@
1
- <label for="<%= safe_id(field[:id], 'field') %>"><%= field[:label] %></label>
1
+ <%= erb :field_label, locals: { field: field } %>
2
2
  <select
3
3
  id="<%= safe_id(field[:id], 'field') %>"
4
4
  name="<%= field[:id] %>"
5
- value="<%= @item.field_value_or_default(field) %>"
5
+ value="<%= @item.field_value_or_default(field[:id]) %>"
6
6
  >
7
7
  <% for option in field[:options] %>
8
8
  <option
@@ -12,7 +12,7 @@
12
12
  selected
13
13
  <% end %>
14
14
  <% else %>
15
- <% if option[:value].to_s == @item.field_value_or_default(field) %>
15
+ <% if option[:value].to_s == @item.field_value_or_default(field[:id]) %>
16
16
  selected
17
17
  <% end %>
18
18
  <% end %>
@@ -3,6 +3,7 @@
3
3
  --border-radius: 8px;
4
4
  --bg-color: rgb(246, 246, 247);
5
5
  --font-color: #141414;
6
+ --font-color-light: #44474a;
6
7
  --link-color: rgb(71, 95, 145);
7
8
  --accent-color: <%= @config[:accent_color] %>;
8
9
  --accent-color-light: <%= @config[:accent_color] %>1e;
@@ -24,10 +25,6 @@
24
25
  --box-shadow-input: inset rgba(0, 0, 0, 0.1) 0px 1px 0px 0px;
25
26
  }
26
27
 
27
- test {
28
- te
29
- }
30
-
31
28
  @media only screen and (max-width: 1250px) {
32
29
  :root {
33
30
  --content-left-margin: 3rem;
@@ -80,11 +77,10 @@ th {
80
77
  font-weight: 500;
81
78
  }
82
79
 
83
- th,
84
- td {
85
- white-space: nowrap;
86
- overflow: hidden;
87
- text-overflow: ellipsis;
80
+ th.date,
81
+ td.date > * {
82
+ width: 7rem;
83
+ text-align: right;
88
84
  }
89
85
 
90
86
  td a {
@@ -153,7 +149,10 @@ tbody tr:hover td {
153
149
 
154
150
  label {
155
151
  display: block;
156
- margin-bottom: var(--padding-xs);
152
+ }
153
+
154
+ small {
155
+ color: var(--font-color-light);
157
156
  }
158
157
 
159
158
  input {
@@ -190,6 +189,14 @@ select {
190
189
  box-shadow: var(--box-shadow-input);
191
190
  }
192
191
 
192
+ input,
193
+ select,
194
+ trix-toolbar,
195
+ img#image-preview {
196
+ display: block;
197
+ margin-top: var(--padding-xs);
198
+ }
199
+
193
200
  button {
194
201
  padding: var(--padding-xxs) var(--padding-xs);
195
202
  color: var(--accent-color);
@@ -405,10 +412,6 @@ hr {
405
412
  padding: 2rem;
406
413
  }
407
414
 
408
- .grow-column {
409
- width: 100%;
410
- }
411
-
412
415
  .image-preview {
413
416
  width: 8rem;
414
417
  height: 8rem;
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: robin_cms
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.4
4
+ version: 0.1.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Aron Lebani
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-10-17 00:00:00.000000000 Z
11
+ date: 2025-11-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bcrypt
@@ -66,7 +66,7 @@ dependencies:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
68
  version: '2.2'
69
- description:
69
+ description: Robin CMS is a simple, flat-file CMS for Static Site Generators.
70
70
  email:
71
71
  - aron@lebani.dev
72
72
  executables: []
@@ -94,6 +94,7 @@ files:
94
94
  - lib/robin_cms/views/change_password.erb
95
95
  - lib/robin_cms/views/delete_dialog.erb
96
96
  - lib/robin_cms/views/error.erb
97
+ - lib/robin_cms/views/field_label.erb
97
98
  - lib/robin_cms/views/filter_form.erb
98
99
  - lib/robin_cms/views/flash.erb
99
100
  - lib/robin_cms/views/hidden_field.erb
@@ -111,11 +112,11 @@ files:
111
112
  - lib/robin_cms/views/richtext_field.erb
112
113
  - lib/robin_cms/views/select_field.erb
113
114
  - lib/robin_cms/views/stylesheet.css.erb
114
- homepage: https://codeberg.org/evencuriouser/robin_cms
115
+ homepage: https://robincms.org
115
116
  licenses:
116
117
  - MIT
117
118
  metadata:
118
- homepage_uri: https://codeberg.org/evencuriouser/robin_cms
119
+ homepage_uri: https://robincms.org
119
120
  source_code_uri: https://codeberg.org/evencuriouser/robin_cms
120
121
  post_install_message:
121
122
  rdoc_options: []
@@ -135,5 +136,5 @@ requirements: []
135
136
  rubygems_version: 3.5.16
136
137
  signing_key:
137
138
  specification_version: 4
138
- summary: A minimalist, headless, rack-based flat-file CMS.
139
+ summary: A simple, flat-file CMS for Static Site Generators.
139
140
  test_files: []