moduler 0.3.0 → 0.4.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.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/builds/moduler/tailwind.css +747 -2
  3. data/app/assets/javascripts/moduler/controllers/wysiwyg_controller.js +126 -0
  4. data/app/assets/javascripts/moduler/vendor/marked.esm.js +77 -0
  5. data/app/components/moduler/form/select_component.html.erb +1 -1
  6. data/app/components/moduler/form/textarea_component.html.erb +14 -0
  7. data/app/components/moduler/form/textarea_component.rb +11 -0
  8. data/app/components/moduler/form/wysiwyg_component.html.erb +30 -0
  9. data/app/components/moduler/form/wysiwyg_component.rb +62 -0
  10. data/app/controllers/moduler/administration/articles_controller.rb +57 -0
  11. data/app/controllers/moduler/articles_controller.rb +15 -0
  12. data/app/models/moduler/article.rb +25 -0
  13. data/app/policies/moduler/administration/article_policy.rb +29 -0
  14. data/app/views/layouts/moduler/articles.html.erb +18 -0
  15. data/app/views/moduler/administration/articles/_article.html.erb +13 -0
  16. data/app/views/moduler/administration/articles/_form.html.erb +18 -0
  17. data/app/views/moduler/administration/articles/edit.html.erb +1 -0
  18. data/app/views/moduler/administration/articles/index.html.erb +13 -0
  19. data/app/views/moduler/administration/articles/new.html.erb +1 -0
  20. data/app/views/moduler/articles/_article.html.erb +16 -0
  21. data/app/views/moduler/articles/index.html.erb +15 -0
  22. data/app/views/moduler/articles/show.html.erb +21 -0
  23. data/app/views/moduler/common/_sidebar.html.erb +3 -2
  24. data/app/views/moduler/common/administration/_sidebar.html.erb +6 -0
  25. data/app/views/moduler/common/profile/_sidebar.html.erb +6 -0
  26. data/app/views/moduler/home/index.html.erb +6 -0
  27. data/app/views/moduler/profile/edit.html.erb +1 -1
  28. data/app/views/moduler/profile/sessions/index.html.erb +1 -1
  29. data/config/importmap.rb +2 -0
  30. data/config/locales/moduler/administration/articles/en.yml +37 -0
  31. data/config/locales/moduler/articles/en.yml +13 -0
  32. data/config/locales/moduler/common/en.yml +11 -4
  33. data/config/locales/moduler/components/en.yml +16 -0
  34. data/config/routes.rb +4 -0
  35. data/db/migrate/20261026203827_create_moduler_articles.rb +15 -0
  36. data/lib/moduler/version.rb +1 -1
  37. data/lib/moduler.rb +3 -0
  38. metadata +53 -2
@@ -0,0 +1,16 @@
1
+ <li id="<%= dom_id(article) %>">
2
+ <article class="group relative">
3
+ <%= time_tag article.created_at, l(article.created_at.to_date, format: :long), class: "text-xs text-slate-400" %>
4
+
5
+ <h2 class="mt-2 text-xl font-semibold tracking-tight text-gray-900 group-hover:text-custom">
6
+ <%= link_to moduler.article_path(article.path) do %>
7
+ <span class="absolute inset-0"></span>
8
+ <%= article.title %>
9
+ <% end %>
10
+ </h2>
11
+
12
+ <p class="mt-2 text-sm/6 text-slate-600"><%= article.description %></p>
13
+
14
+ <p class="mt-3 text-sm font-semibold text-gray-900 group-hover:text-custom"><%= t(".action.show") %> <span aria-hidden="true">&rarr;</span></p>
15
+ </article>
16
+ </li>
@@ -0,0 +1,15 @@
1
+ <main class="mx-auto w-full max-w-3xl flex-1 px-4 pb-4 md:mt-8">
2
+ <%= render(Moduler::PageHeaderComponent.new(t(".title"), description: t(".description"))) %>
3
+
4
+ <% if @articles.any? %>
5
+ <ul id="articles" role="list" class="mt-10 space-y-12">
6
+ <%= render partial: "moduler/articles/article", collection: @articles %>
7
+ </ul>
8
+
9
+ <div class="mt-12 flex justify-end">
10
+ <%= paginate @articles %>
11
+ </div>
12
+ <% else %>
13
+ <p class="mt-10 text-sm text-slate-500"><%= t(".empty") %></p>
14
+ <% end %>
15
+ </main>
@@ -0,0 +1,21 @@
1
+ <% content_for :title, @article.title %>
2
+ <% content_for :head do %>
3
+ <meta name="description" content="<%= @article.description %>">
4
+ <meta name="keywords" content="<%= @article.keywords %>">
5
+ <% end %>
6
+
7
+ <main class="mx-auto w-full max-w-3xl flex-1 px-4 pb-4 md:mt-8">
8
+ <%= link_to t(".action.index"), moduler.articles_path, class: "text-sm text-slate-500 hover:text-custom" %>
9
+
10
+ <article id="<%= dom_id(@article) %>" class="mt-6">
11
+ <header class="mb-8 border-b border-slate-200 pb-6">
12
+ <h1 class="text-2xl/9 font-bold tracking-tight text-gray-900"><%= @article.title %></h1>
13
+ <p class="mt-2 text-sm text-slate-500"><%= @article.description %></p>
14
+ <p class="mt-2 text-xs text-slate-400"><%= time_tag @article.created_at, l(@article.created_at.to_date, format: :long) %></p>
15
+ </header>
16
+
17
+ <div class="prose prose-slate prose-100 prose-img:w-full prose-img:max-w-5xl">
18
+ <%= @article.to_html %>
19
+ </div>
20
+ </article>
21
+ </main>
@@ -1,6 +1,7 @@
1
1
  <aside class="-mx-4 border-b border-gray-200 px-2 md:mx-0 md:w-1/8 md:shrink-0 md:border-b-0 md:border-r md:px-0">
2
2
  <nav class="flex gap-1 overflow-x-auto md:flex-col text-sm p-2">
3
- <%= render(Moduler::SidebarActionComponent.new(t(".action.profile"), moduler.edit_profile_path, "moduler/profile")) %>
4
- <%= render(Moduler::SidebarActionComponent.new(t(".action.sessions"), moduler.profile_sessions_path, "moduler/profile/sessions")) %>
3
+ <% Array(Moduler.configuration.dig(:resources)).each do |resource| %>
4
+ <%= render(Moduler::SidebarActionComponent.new(t(".action.#{resource}"), moduler.url_for([resource.to_sym]), "moduler/#{resource}")) %>
5
+ <% end %>
5
6
  </nav>
6
7
  </aside>
@@ -2,5 +2,11 @@
2
2
  <nav class="flex gap-1 overflow-x-auto md:flex-col text-sm p-2">
3
3
  <%= render(Moduler::SidebarActionComponent.new(t(".action.users"), moduler.administration_users_path, "moduler/administration/users")) %>
4
4
  <%= render(Moduler::SidebarActionComponent.new(t(".action.sessions"), moduler.administration_sessions_path, "moduler/administration/sessions")) %>
5
+
6
+ <%= render(Moduler::SidebarActionComponent.new(t(".action.articles"), moduler.administration_articles_path, "moduler/administration/articles")) %>
7
+
8
+ <% Array(Moduler.configuration.dig(:administration, :resources)).each do |resource| %>
9
+ <%= render(Moduler::SidebarActionComponent.new(t(".action.#{resource}"), moduler.url_for([:administration, resource.to_sym]), "moduler/administration/#{resource}")) %>
10
+ <% end %>
5
11
  </nav>
6
12
  </aside>
@@ -0,0 +1,6 @@
1
+ <aside class="-mx-4 border-b border-gray-200 px-2 md:mx-0 md:w-1/8 md:shrink-0 md:border-b-0 md:border-r md:px-0">
2
+ <nav class="flex gap-1 overflow-x-auto md:flex-col text-sm p-2">
3
+ <%= render(Moduler::SidebarActionComponent.new(t(".action.profile"), moduler.edit_profile_path, "moduler/profile")) %>
4
+ <%= render(Moduler::SidebarActionComponent.new(t(".action.sessions"), moduler.profile_sessions_path, "moduler/profile/sessions")) %>
5
+ </nav>
6
+ </aside>
@@ -0,0 +1,6 @@
1
+ <main class="mx-auto flex w-full flex-1 max-w-[120rem] flex-col gap-4 px-4 md:flex-row md:gap-8 md:pl-0 md:pr-6">
2
+ <%= render "moduler/common/sidebar" %>
3
+
4
+ <div class="flex min-w-0 flex-1 flex-col pb-4 md:mt-8">
5
+ </div>
6
+ </main>
@@ -1,5 +1,5 @@
1
1
  <main class="mx-auto flex w-full flex-1 max-w-[120rem] flex-col gap-4 px-4 md:flex-row md:gap-8 md:pl-0 md:pr-6">
2
- <%= render "moduler/common/sidebar" %>
2
+ <%= render "moduler/common/profile/sidebar" %>
3
3
 
4
4
  <div class="flex min-w-0 flex-1 flex-col pb-4 md:mt-8">
5
5
  <div class="mb-4 flex min-h-9 items-center justify-between gap-4">
@@ -1,5 +1,5 @@
1
1
  <main class="mx-auto flex w-full flex-1 max-w-[120rem] flex-col gap-4 px-4 md:flex-row md:gap-8 md:pl-0 md:pr-6">
2
- <%= render "moduler/common/sidebar" %>
2
+ <%= render "moduler/common/profile/sidebar" %>
3
3
 
4
4
  <div class="flex min-w-0 flex-1 flex-col pb-4 md:mt-8">
5
5
  <div class="mb-6 flex flex-col gap-4 sm:flex-row sm:items-start sm:justify-between">
data/config/importmap.rb CHANGED
@@ -3,3 +3,5 @@ pin "@hotwired/turbo-rails", to: "turbo.min.js"
3
3
  pin "@hotwired/stimulus", to: "stimulus.min.js"
4
4
  pin "@hotwired/stimulus-loading", to: "stimulus-loading.js"
5
5
  pin_all_from File.expand_path("../app/assets/javascripts/moduler/controllers", __dir__), under: "moduler/controllers"
6
+ pin "marked", to: "moduler/vendor/marked.esm.js"
7
+ pin "@rails/activestorage", to: "activestorage.esm.js"
@@ -0,0 +1,37 @@
1
+ en:
2
+ moduler:
3
+ administration:
4
+ articles:
5
+ index:
6
+ title: Articles
7
+ description: Posts published on your own public site
8
+ empty: No articles found
9
+ action:
10
+ new: Create
11
+ article:
12
+ created: Created %{time} ago
13
+ action:
14
+ edit: Edit
15
+ destroy: Destroy
16
+ confirmation:
17
+ destroy: Are you sure?
18
+ create:
19
+ notice: Article has been created
20
+ update:
21
+ notice: Article has been updated
22
+ destroy:
23
+ notice: Article has been deleted
24
+ form:
25
+ title: Article
26
+ label:
27
+ title: Title
28
+ path: Path
29
+ description: Description
30
+ keywords: Keywords
31
+ content: Content
32
+ description:
33
+ path: The article's URL -- letters, numbers, and hyphens only.
34
+ description: Shown in search results and social previews.
35
+ keywords: Comma-separated, for search results and social previews.
36
+ action:
37
+ save: Save
@@ -0,0 +1,13 @@
1
+ en:
2
+ moduler:
3
+ articles:
4
+ index:
5
+ title: Articles
6
+ description: Read the latest articles.
7
+ empty: No articles have been published yet.
8
+ article:
9
+ action:
10
+ show: Read more
11
+ show:
12
+ action:
13
+ index: "← All articles"
@@ -1,10 +1,17 @@
1
1
  en:
2
2
  moduler:
3
3
  common:
4
- sidebar:
5
- action:
6
- profile: Profile
7
- sessions: Sessions
4
+ administration:
5
+ sidebar:
6
+ action:
7
+ users: Users
8
+ sessions: Sessions
9
+ articles: Articles
10
+ profile:
11
+ sidebar:
12
+ action:
13
+ profile: Profile
14
+ sessions: Sessions
8
15
  header:
9
16
  nav:
10
17
  administration: Administration
@@ -9,3 +9,19 @@ en:
9
9
  clear: Clear
10
10
  list:
11
11
  empty: No results found.
12
+ form:
13
+ wysiwyg:
14
+ action:
15
+ bold: B
16
+ italic: I
17
+ h1: H1
18
+ h2: H2
19
+ h3: H3
20
+ quote: Quote
21
+ code: Code
22
+ ul: List
23
+ ol: 1. List
24
+ fenced_code: "</>"
25
+ link: Link
26
+ image: Image
27
+ upload: Upload
data/config/routes.rb CHANGED
@@ -1,4 +1,6 @@
1
1
  Moduler::Engine.routes.draw do
2
+ resources :articles, only: %i[ index show ], param: :path
3
+
2
4
  resource :session, only: %i[new create destroy]
3
5
  resource :user, only: %i[new create]
4
6
 
@@ -14,6 +16,8 @@ Moduler::Engine.routes.draw do
14
16
  resources :users, only: %i[ index new create edit update ]
15
17
  resources :sessions, only: %i[ index destroy ]
16
18
 
19
+ resources :articles
20
+
17
21
  root "home#index"
18
22
  end
19
23
 
@@ -0,0 +1,15 @@
1
+ class CreateModulerArticles < ActiveRecord::Migration[8.1]
2
+ def change
3
+ create_table :moduler_articles do |t|
4
+ t.string :path, null: false
5
+ t.string :title, null: false
6
+ t.string :description, null: false
7
+ t.string :keywords, null: false
8
+ t.text :content, null: false
9
+
10
+ t.timestamps null: false
11
+ end
12
+
13
+ add_index :moduler_articles, :path, unique: true
14
+ end
15
+ end
@@ -1,3 +1,3 @@
1
1
  module Moduler
2
- VERSION = "0.3.0"
2
+ VERSION = "0.4.0"
3
3
  end
data/lib/moduler.rb CHANGED
@@ -1,6 +1,9 @@
1
1
  require "view_component"
2
2
  require "pg_search"
3
3
  require "pundit"
4
+ require "active_storage/engine"
5
+ require "active_storage_validations"
6
+ require "redcarpet"
4
7
 
5
8
  require "moduler/version"
6
9
  require "moduler/engine"
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: moduler
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tomasz Kowalewski
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2026-10-25 00:00:00.000000000 Z
10
+ date: 2026-10-27 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: rails
@@ -179,6 +179,34 @@ dependencies:
179
179
  - - "~>"
180
180
  - !ruby/object:Gem::Version
181
181
  version: '2.5'
182
+ - !ruby/object:Gem::Dependency
183
+ name: active_storage_validations
184
+ requirement: !ruby/object:Gem::Requirement
185
+ requirements:
186
+ - - "~>"
187
+ - !ruby/object:Gem::Version
188
+ version: '4.1'
189
+ type: :runtime
190
+ prerelease: false
191
+ version_requirements: !ruby/object:Gem::Requirement
192
+ requirements:
193
+ - - "~>"
194
+ - !ruby/object:Gem::Version
195
+ version: '4.1'
196
+ - !ruby/object:Gem::Dependency
197
+ name: redcarpet
198
+ requirement: !ruby/object:Gem::Requirement
199
+ requirements:
200
+ - - "~>"
201
+ - !ruby/object:Gem::Version
202
+ version: '3.6'
203
+ type: :runtime
204
+ prerelease: false
205
+ version_requirements: !ruby/object:Gem::Requirement
206
+ requirements:
207
+ - - "~>"
208
+ - !ruby/object:Gem::Version
209
+ version: '3.6'
182
210
  email:
183
211
  - me@tkowalewski.pl
184
212
  executables: []
@@ -192,6 +220,8 @@ files:
192
220
  - app/assets/config/moduler/manifest.js
193
221
  - app/assets/javascripts/moduler/application.js
194
222
  - app/assets/javascripts/moduler/controllers/flash_controller.js
223
+ - app/assets/javascripts/moduler/controllers/wysiwyg_controller.js
224
+ - app/assets/javascripts/moduler/vendor/marked.esm.js
195
225
  - app/assets/stylesheets/moduler/application.css
196
226
  - app/assets/stylesheets/moduler/tailwind.css
197
227
  - app/components/moduler/administration/page_component.html.erb
@@ -218,6 +248,10 @@ files:
218
248
  - app/components/moduler/form/submit_component.rb
219
249
  - app/components/moduler/form/text_component.html.erb
220
250
  - app/components/moduler/form/text_component.rb
251
+ - app/components/moduler/form/textarea_component.html.erb
252
+ - app/components/moduler/form/textarea_component.rb
253
+ - app/components/moduler/form/wysiwyg_component.html.erb
254
+ - app/components/moduler/form/wysiwyg_component.rb
221
255
  - app/components/moduler/list_component.html.erb
222
256
  - app/components/moduler/list_component.rb
223
257
  - app/components/moduler/list_item_component.html.erb
@@ -228,10 +262,12 @@ files:
228
262
  - app/components/moduler/sidebar_action_component.rb
229
263
  - app/controllers/concerns/moduler/authentication.rb
230
264
  - app/controllers/moduler/administration/application_controller.rb
265
+ - app/controllers/moduler/administration/articles_controller.rb
231
266
  - app/controllers/moduler/administration/home_controller.rb
232
267
  - app/controllers/moduler/administration/sessions_controller.rb
233
268
  - app/controllers/moduler/administration/users_controller.rb
234
269
  - app/controllers/moduler/application_controller.rb
270
+ - app/controllers/moduler/articles_controller.rb
235
271
  - app/controllers/moduler/home_controller.rb
236
272
  - app/controllers/moduler/profile/sessions/revocation_controller.rb
237
273
  - app/controllers/moduler/profile/sessions_controller.rb
@@ -245,9 +281,11 @@ files:
245
281
  - app/lib/moduler/form_builder.rb
246
282
  - app/mailers/moduler/application_mailer.rb
247
283
  - app/models/moduler/application_record.rb
284
+ - app/models/moduler/article.rb
248
285
  - app/models/moduler/current.rb
249
286
  - app/models/moduler/session.rb
250
287
  - app/models/moduler/user.rb
288
+ - app/policies/moduler/administration/article_policy.rb
251
289
  - app/policies/moduler/administration/base_policy.rb
252
290
  - app/policies/moduler/administration/home_policy.rb
253
291
  - app/policies/moduler/administration/session_policy.rb
@@ -259,6 +297,12 @@ files:
259
297
  - app/views/kaminari/_paginator.html.erb
260
298
  - app/views/kaminari/_prev_page.html.erb
261
299
  - app/views/layouts/moduler/application.html.erb
300
+ - app/views/layouts/moduler/articles.html.erb
301
+ - app/views/moduler/administration/articles/_article.html.erb
302
+ - app/views/moduler/administration/articles/_form.html.erb
303
+ - app/views/moduler/administration/articles/edit.html.erb
304
+ - app/views/moduler/administration/articles/index.html.erb
305
+ - app/views/moduler/administration/articles/new.html.erb
262
306
  - app/views/moduler/administration/home/index.html.erb
263
307
  - app/views/moduler/administration/sessions/_session.html.erb
264
308
  - app/views/moduler/administration/sessions/index.html.erb
@@ -266,10 +310,14 @@ files:
266
310
  - app/views/moduler/administration/users/edit.html.erb
267
311
  - app/views/moduler/administration/users/index.html.erb
268
312
  - app/views/moduler/administration/users/new.html.erb
313
+ - app/views/moduler/articles/_article.html.erb
314
+ - app/views/moduler/articles/index.html.erb
315
+ - app/views/moduler/articles/show.html.erb
269
316
  - app/views/moduler/common/_flash.html.erb
270
317
  - app/views/moduler/common/_header.html.erb
271
318
  - app/views/moduler/common/_sidebar.html.erb
272
319
  - app/views/moduler/common/administration/_sidebar.html.erb
320
+ - app/views/moduler/common/profile/_sidebar.html.erb
273
321
  - app/views/moduler/home/index.html.erb
274
322
  - app/views/moduler/profile/edit.html.erb
275
323
  - app/views/moduler/profile/sessions/_session.html.erb
@@ -277,8 +325,10 @@ files:
277
325
  - app/views/moduler/sessions/new.html.erb
278
326
  - app/views/moduler/users/new.html.erb
279
327
  - config/importmap.rb
328
+ - config/locales/moduler/administration/articles/en.yml
280
329
  - config/locales/moduler/administration/sessions/en.yml
281
330
  - config/locales/moduler/administration/users/en.yml
331
+ - config/locales/moduler/articles/en.yml
282
332
  - config/locales/moduler/common/en.yml
283
333
  - config/locales/moduler/components/en.yml
284
334
  - config/locales/moduler/en.yml
@@ -291,6 +341,7 @@ files:
291
341
  - db/migrate/20260322153744_create_moduler_sessions.rb
292
342
  - db/migrate/20261015171504_add_role_to_moduler_users.rb
293
343
  - db/migrate/20261020191709_enable_pg_trgm.rb
344
+ - db/migrate/20261026203827_create_moduler_articles.rb
294
345
  - lib/moduler.rb
295
346
  - lib/moduler/configuration.rb
296
347
  - lib/moduler/engine.rb