trek 0.1.21 → 0.1.22
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/.npmignore +3 -0
- data/Gemfile.lock +76 -74
- data/README.md +8 -0
- data/app/assets/stylesheets/trek/_colors.css +181 -0
- data/app/components/trek/button_component.rb +9 -3
- data/app/components/trek/form/actions_component/actions_component.css +6 -0
- data/app/components/trek/form/image_field_component/image_field_component.css +1 -1
- data/app/components/trek/form/switch_box_component.rb +1 -0
- data/app/components/trek/tabs_component/tabs_component.css +1 -0
- data/app/controllers/concerns/trek/model.rb +4 -1
- data/config/locales/trek.en.yml +2 -0
- data/docs/.vitepress/config.mjs +133 -0
- data/docs/.vitepress/theme/index.js +17 -0
- data/docs/.vitepress/theme/style.css +139 -0
- data/docs/customize.md +63 -7
- data/docs/getting-started.md +160 -0
- data/docs/index.md +39 -0
- data/docs/public/logo.svg +1 -0
- data/docs/reference/components.md +40 -0
- data/docs/reference/concerns/contentable.md +28 -0
- data/docs/reference/concerns/formattable.md +24 -0
- data/docs/reference/concerns/fragmentable.md +33 -0
- data/docs/reference/concerns/keyable.md +18 -0
- data/docs/reference/concerns/orderable.md +26 -0
- data/docs/reference/concerns/pageable.md +35 -0
- data/docs/reference/concerns/pathable.md +28 -0
- data/docs/reference/concerns/phonable.md +28 -0
- data/docs/reference/concerns/search-engine-optimizable.md +19 -0
- data/docs/reference/concerns/searchable.md +22 -0
- data/docs/reference/concerns/sectionable.md +24 -0
- data/docs/reference/concerns/sluggable.md +21 -0
- data/docs/reference/concerns/taggable.md +20 -0
- data/docs/reference/concerns/translatable.md +35 -0
- data/docs/reference/concerns/versionable.md +27 -0
- data/docs/reference/controllers.md +23 -0
- data/docs/reference/environment-variables.md +9 -0
- data/docs/reference/formatters.md +30 -0
- data/docs/reference/forms.md +21 -0
- data/docs/reference/generators/admin-user.md +17 -0
- data/docs/reference/generators/install.md +42 -0
- data/docs/reference/generators/scaffold.md +37 -0
- data/docs/reference/generators/taxonomies.md +21 -0
- data/docs/reference/icons.md +11 -0
- data/docs/reference/index.md +47 -0
- data/docs/reference/models/current.md +11 -0
- data/docs/reference/models/external-link.md +16 -0
- data/docs/reference/models/fragment.md +28 -0
- data/docs/reference/models/menu-node.md +30 -0
- data/docs/reference/models/page-path.md +19 -0
- data/docs/reference/models/page-version.md +30 -0
- data/docs/reference/models/page.md +48 -0
- data/docs/reference/models/tag.md +41 -0
- data/docs/reference/models/user.md +65 -0
- data/docs/reference/policies.md +30 -0
- data/docs/reference/uploaders.md +19 -0
- data/docs/what-is-trek.md +37 -0
- data/esbuild.config.js +10 -7
- data/lib/trek/version.rb +1 -1
- data/netlify.toml +4 -0
- data/package.json +10 -5
- data/renovate.json +4 -0
- data/yarn.lock +2015 -235
- metadata +48 -2
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Trek::Fragmentable
|
|
2
|
+
|
|
3
|
+
Composes a record from reusable [fragments](/reference/models/fragment), based on a configuration matrix mapping record keys to fragment ids.
|
|
4
|
+
|
|
5
|
+
## Configuration
|
|
6
|
+
|
|
7
|
+
```yaml
|
|
8
|
+
# page_fragments configuration
|
|
9
|
+
page_fragments:
|
|
10
|
+
matrix:
|
|
11
|
+
home: [1, 2, 3]
|
|
12
|
+
about: [4, 5]
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Methods
|
|
16
|
+
|
|
17
|
+
| Method | Purpose |
|
|
18
|
+
| --- | --- |
|
|
19
|
+
| `fragments` | the Fragment records configured for this record's `key` |
|
|
20
|
+
| `fragments_attributes=` | bulk-updates fragments from nested form attributes |
|
|
21
|
+
|
|
22
|
+
## Usage
|
|
23
|
+
|
|
24
|
+
```ruby
|
|
25
|
+
class Page < ApplicationRecord
|
|
26
|
+
include Trek::Fragmentable
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
page = Page.find_by(key: "home")
|
|
30
|
+
page.fragments # => [Fragment(1), Fragment(2), Fragment(3)]
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
This is what powers the fragment editing UI on page forms in the admin.
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Trek::Keyable
|
|
2
|
+
|
|
3
|
+
Batch lookup of records by their `key` attribute, preserving the requested order.
|
|
4
|
+
|
|
5
|
+
## Methods
|
|
6
|
+
|
|
7
|
+
| Method | Returns |
|
|
8
|
+
| --- | --- |
|
|
9
|
+
| `Model.take_by_keys(keys)` | the records matching `keys`, **in the same order**, with `nil` for missing keys |
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
```ruby
|
|
14
|
+
Page.take_by_keys(%w[services about missing])
|
|
15
|
+
# => [#<Page key="services">, #<Page key="about">, nil]
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Handy for rendering a fixed set of pages or fragments in a specific order in your views.
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Trek::Orderable
|
|
2
|
+
|
|
3
|
+
Position tracking with [acts_as_list](https://github.com/brendon/acts_as_list), scoped by parent.
|
|
4
|
+
|
|
5
|
+
## What it adds
|
|
6
|
+
|
|
7
|
+
- `acts_as_list scope: :parent, top_of_list: 0`
|
|
8
|
+
- An `ordered` scope (position order)
|
|
9
|
+
- All the `acts_as_list` instance methods: `insert_at`, `move_to_top`, `move_to_bottom`, `move_higher`, `move_lower`…
|
|
10
|
+
|
|
11
|
+
## Requirements
|
|
12
|
+
|
|
13
|
+
- A `position` integer column (and a `parent_id` column for the scope)
|
|
14
|
+
|
|
15
|
+
## Usage
|
|
16
|
+
|
|
17
|
+
```ruby
|
|
18
|
+
class MenuNode < ApplicationRecord
|
|
19
|
+
include Trek::Orderable
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
MenuNode.where(parent: menu).ordered
|
|
23
|
+
node.move_to_top
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
This is what powers drag & drop reordering (SortableJS) in the admin lists.
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Trek::Pageable
|
|
2
|
+
|
|
3
|
+
The bridge between your content models (articles, products…) and their [Page](/reference/models/page) representation. The model owns the data; the page owns the title, slug, SEO and position.
|
|
4
|
+
|
|
5
|
+
## What it adds
|
|
6
|
+
|
|
7
|
+
- `has_one :page, as: :pageable, dependent: :destroy, autosave: true` with `accepts_nested_attributes_for :page`
|
|
8
|
+
- Delegates `title`, `image`, `image_url`, `current_image`, `current_image_url`, `to_s` to the page
|
|
9
|
+
- `before_create` guarantees the page exists
|
|
10
|
+
- `to_param` uses the page slug on the public site (and the id in the admin)
|
|
11
|
+
|
|
12
|
+
## Class macros
|
|
13
|
+
|
|
14
|
+
| Macro | Purpose |
|
|
15
|
+
| --- | --- |
|
|
16
|
+
| `has_position_from_page` | delegates `position` to the page and adds a `by_position` scope |
|
|
17
|
+
| `has_root_scope` | adds a `root` scope finding resources under their index page |
|
|
18
|
+
| `find_with_page_slug(slug)` | class method — resource lookup by page slug |
|
|
19
|
+
|
|
20
|
+
## Navigation helpers
|
|
21
|
+
|
|
22
|
+
`parent?`, `parent`, `children?`, `children` — traverse the page hierarchy from the resource side.
|
|
23
|
+
|
|
24
|
+
## Usage
|
|
25
|
+
|
|
26
|
+
```ruby
|
|
27
|
+
class Article < ApplicationRecord
|
|
28
|
+
include Trek::Pageable
|
|
29
|
+
has_position_from_page
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
article = Article.create(page_attributes: { title: "My Article" })
|
|
33
|
+
article.title # => "My Article" (delegated)
|
|
34
|
+
article.to_param # => "my-article"
|
|
35
|
+
```
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# Trek::Pages::Pathable
|
|
2
|
+
|
|
3
|
+
Manages a page's URL paths across locales: the current path, the full history (for redirects), and automatic regeneration when pages move in the tree.
|
|
4
|
+
|
|
5
|
+
## What it adds
|
|
6
|
+
|
|
7
|
+
- `belongs_to :current_path` and `has_many :paths` → [PagePath](/reference/models/page-path)
|
|
8
|
+
- `after_save_commit`, paths are (re)created for the page **and all its descendants**
|
|
9
|
+
|
|
10
|
+
## Methods
|
|
11
|
+
|
|
12
|
+
| Method | Returns |
|
|
13
|
+
| --- | --- |
|
|
14
|
+
| `Page.find_at_full_path(path)` | the page at this path (raises `ActiveRecord::RecordNotFound`) |
|
|
15
|
+
| `full_path` | the current path string |
|
|
16
|
+
| `full_path_from_tree` | the path computed from ancestor slugs |
|
|
17
|
+
|
|
18
|
+
## Usage
|
|
19
|
+
|
|
20
|
+
```ruby
|
|
21
|
+
parent = Page.create(title: "Services")
|
|
22
|
+
child = Page.create(title: "Design", parent: parent)
|
|
23
|
+
|
|
24
|
+
child.full_path # => "services/design"
|
|
25
|
+
Page.find_at_full_path("services/design") # => child
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Old paths remain in `page.paths`, which lets your front-end controllers redirect outdated URLs to `full_path`.
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# Trek::Phonable
|
|
2
|
+
|
|
3
|
+
Phone number validation, normalization and formatting, backed by [Phonelib](https://github.com/daddyz/phonelib).
|
|
4
|
+
|
|
5
|
+
## API
|
|
6
|
+
|
|
7
|
+
```ruby
|
|
8
|
+
class Organization < ApplicationRecord
|
|
9
|
+
include Trek::Phonable
|
|
10
|
+
phonable_attributes :phone, :fax
|
|
11
|
+
end
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
For each declared attribute:
|
|
15
|
+
|
|
16
|
+
- a validation (`phone: { possible: true, allow_blank: true }`)
|
|
17
|
+
- normalization to E.164 international format on save
|
|
18
|
+
- `formatted_{attr}` — national format (`"01 23 45 67 89"`)
|
|
19
|
+
- `{attr}_with_country_code` — E.164 (`"+33123456789"`)
|
|
20
|
+
|
|
21
|
+
## Usage
|
|
22
|
+
|
|
23
|
+
```ruby
|
|
24
|
+
org = Organization.create(phone: "0123456789")
|
|
25
|
+
org.phone # => "+33123456789"
|
|
26
|
+
org.formatted_phone # => "01 23 45 67 89"
|
|
27
|
+
org.phone_with_country_code # => "+33123456789"
|
|
28
|
+
```
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Trek::Pages::SearchEngineOptimizable
|
|
2
|
+
|
|
3
|
+
SEO metadata with sensible fallbacks: explicit title/description/image when set, model defaults otherwise (including the parent page's image).
|
|
4
|
+
|
|
5
|
+
## Methods
|
|
6
|
+
|
|
7
|
+
| Method | Returns |
|
|
8
|
+
| --- | --- |
|
|
9
|
+
| `seo_values` | `{ title:, description:, image:, slug: }` with fallbacks applied |
|
|
10
|
+
| `meta_tags` | `seo_values` without the slug — ready for your `<head>` |
|
|
11
|
+
| `default_title` / `default_description` / `default_image` | the fallback values |
|
|
12
|
+
|
|
13
|
+
## Usage
|
|
14
|
+
|
|
15
|
+
```slim
|
|
16
|
+
/ app/views/layouts/application.html.slim
|
|
17
|
+
- @page.meta_tags.each do |name, content|
|
|
18
|
+
meta name=name content=content
|
|
19
|
+
```
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# Trek::Searchable
|
|
2
|
+
|
|
3
|
+
Accent-insensitive full-text search on a record's page title, using PostgreSQL's `unaccent` extension.
|
|
4
|
+
|
|
5
|
+
## What it adds
|
|
6
|
+
|
|
7
|
+
- A `search(query)` scope — joins to the associated page and matches the title with an unaccented `ILIKE`; returns everything when the query is blank
|
|
8
|
+
|
|
9
|
+
## Usage
|
|
10
|
+
|
|
11
|
+
```ruby
|
|
12
|
+
class Article < ApplicationRecord
|
|
13
|
+
include Trek::Pageable
|
|
14
|
+
include Trek::Searchable
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
Article.search("élève") # matches "eleve", "Élève"…
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Controller side
|
|
21
|
+
|
|
22
|
+
The `Trek::Search` controller concern wires this into index actions: it filters `@objects` by `params[:search]` whenever the model responds to `search` — that's what powers the search field in admin lists.
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Trek::Sectionable
|
|
2
|
+
|
|
3
|
+
Organizes a record's content into ordered, typed sections (hero, features, testimonials…).
|
|
4
|
+
|
|
5
|
+
## What it adds
|
|
6
|
+
|
|
7
|
+
- `has_many :sections, -> { ordered }, as: :sectionable, dependent: :destroy`
|
|
8
|
+
- `sections_instances` — the unwrapped section objects, in order
|
|
9
|
+
|
|
10
|
+
## Usage
|
|
11
|
+
|
|
12
|
+
```ruby
|
|
13
|
+
class Page < ApplicationRecord
|
|
14
|
+
include Trek::Sectionable
|
|
15
|
+
|
|
16
|
+
SECTIONS = [HeroSection, FeaturesSection].freeze
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
page.sections_instances.each do |section|
|
|
20
|
+
render section_component_for(section)
|
|
21
|
+
end
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Sections are opt-in per page via the `sectioned` boolean column. The including class defines the allowed section types through the `SECTIONS` constant.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Trek::Sluggable
|
|
2
|
+
|
|
3
|
+
Auto-generates locale-aware URL slugs before validation, for every available locale.
|
|
4
|
+
|
|
5
|
+
## Behavior
|
|
6
|
+
|
|
7
|
+
- `before_validation`, the slug is regenerated per locale: from a route translation of the page `key` when one exists, otherwise by parameterizing the SEO title
|
|
8
|
+
- Validates slug presence (except for the root page) and uniqueness among siblings (`scope: :parent_id`)
|
|
9
|
+
|
|
10
|
+
## Requirements
|
|
11
|
+
|
|
12
|
+
- [Translatable](/reference/concerns/translatable) with a translated `slug`
|
|
13
|
+
- A `key` attribute, a `root?` predicate and `seo_values` (provided by [SearchEngineOptimizable](/reference/concerns/search-engine-optimizable))
|
|
14
|
+
|
|
15
|
+
## Usage
|
|
16
|
+
|
|
17
|
+
```ruby
|
|
18
|
+
page = Page.new(key: "services", title: "Our Services")
|
|
19
|
+
page.save
|
|
20
|
+
page.slug # => "our-services"
|
|
21
|
+
```
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Trek::Taggable
|
|
2
|
+
|
|
3
|
+
Tag associations for any model, via the [taxonomy models](/reference/models/tag) (installed by the [taxonomies generator](/reference/generators/taxonomies)).
|
|
4
|
+
|
|
5
|
+
## What it adds
|
|
6
|
+
|
|
7
|
+
- `has_many :taggings, as: :taggable, dependent: :destroy`
|
|
8
|
+
- `has_many :tags, through: :taggings`
|
|
9
|
+
- `tag_names` — the tag names as an array of strings
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
```ruby
|
|
14
|
+
class Article < ApplicationRecord
|
|
15
|
+
include Trek::Taggable
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
article.tags << Tag.find_or_create_by(name: "Ruby", key: "ruby")
|
|
19
|
+
article.tag_names # => ["Ruby"]
|
|
20
|
+
```
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Trek::Translatable
|
|
2
|
+
|
|
3
|
+
Multi-language attributes, backed by [Mobility](https://github.com/shioyama/mobility). Translated values are stored in `jsonb` columns keyed by locale.
|
|
4
|
+
|
|
5
|
+
## API
|
|
6
|
+
|
|
7
|
+
```ruby
|
|
8
|
+
class Page < ApplicationRecord
|
|
9
|
+
include Trek::Translatable
|
|
10
|
+
translate_attributes :title, :description
|
|
11
|
+
end
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
`translate_attributes(*attr_names)` declares the translatable attributes (it delegates to Mobility's `translates`).
|
|
15
|
+
|
|
16
|
+
## Usage
|
|
17
|
+
|
|
18
|
+
```ruby
|
|
19
|
+
page = Page.create(title: "Home")
|
|
20
|
+
I18n.with_locale(:fr) { page.update(title: "Accueil") }
|
|
21
|
+
|
|
22
|
+
page.title # => "Home" (current locale)
|
|
23
|
+
I18n.with_locale(:fr) { page.title } # => "Accueil"
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Stored as:
|
|
27
|
+
|
|
28
|
+
```json
|
|
29
|
+
{ "en": "Home", "fr": "Accueil" }
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Requirements
|
|
33
|
+
|
|
34
|
+
- A `jsonb` column per translated attribute (default `{}`)
|
|
35
|
+
- Used by [Page](/reference/models/page), [PagePath](/reference/models/page-path), [Fragment](/reference/models/fragment) and [MenuNode](/reference/models/menu-node)
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Trek::Pages::Versionable
|
|
2
|
+
|
|
3
|
+
Content versioning for [pages](/reference/models/page): snapshot the current content and image as a [PageVersion](/reference/models/page-version), then keep editing while the snapshot stays live.
|
|
4
|
+
|
|
5
|
+
## What it adds
|
|
6
|
+
|
|
7
|
+
- `has_many :versions` (most recent first) with a `current` sub-scope, plus `accepts_nested_attributes_for :versions`
|
|
8
|
+
|
|
9
|
+
## Methods
|
|
10
|
+
|
|
11
|
+
| Method | Purpose |
|
|
12
|
+
| --- | --- |
|
|
13
|
+
| `create_current_version_from_page!` | snapshots the page's `content` and `image` as the new current version |
|
|
14
|
+
| `current_version` | the live version (or `nil` when not versioned) |
|
|
15
|
+
| `current_content` / `current_sections` | content from the current version, falling back to the page itself |
|
|
16
|
+
| `current_image` / `current_image_url` | image from the current version, falling back to the page, then its parent |
|
|
17
|
+
|
|
18
|
+
## Usage
|
|
19
|
+
|
|
20
|
+
Versioning is opt-in per page via the `versioned` boolean column:
|
|
21
|
+
|
|
22
|
+
```ruby
|
|
23
|
+
page.update(versioned: true)
|
|
24
|
+
page.create_current_version_from_page! # freeze what's live
|
|
25
|
+
page.update(content: new_draft) # keep editing safely
|
|
26
|
+
page.current_content # => still the frozen snapshot
|
|
27
|
+
```
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Controllers
|
|
2
|
+
|
|
3
|
+
- **`Trek::BaseController`** — the base for all admin controllers: authentication, authorization, localization, the `admin` layout and Trek's [form builder](/reference/forms).
|
|
4
|
+
- **`Trek::ResourceController`** — extends `BaseController` with the full CRUD (`index`, `show`, `new`, `create`, `edit`, `update`, `destroy`), wired to ActionPolicy (`authorized_scope`, `authorize!`) and ordering. Scaffolded controllers inherit from it and only need to declare their `model`:
|
|
5
|
+
|
|
6
|
+
```ruby
|
|
7
|
+
module Admin
|
|
8
|
+
class BooksController < Trek::ResourceController
|
|
9
|
+
private
|
|
10
|
+
|
|
11
|
+
def model
|
|
12
|
+
Book
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
- **Panel controllers** (`Trek::Panels::*`) — support endpoints used by the admin UI: image uploads (Uppy), link insertion and content editor prompts.
|
|
19
|
+
|
|
20
|
+
## Mixins
|
|
21
|
+
|
|
22
|
+
- `include Trek::Pagination` — paginates the index with Kaminari
|
|
23
|
+
- `include Trek::Search` — filters the index by `params[:search]` when the model is [Searchable](/reference/concerns/searchable)
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# Environment variables
|
|
2
|
+
|
|
3
|
+
| Variable | Purpose |
|
|
4
|
+
| --- | --- |
|
|
5
|
+
| `ADMIN_EMAIL` / `ADMIN_PASSWORD` | credentials used by [`trek:admin:user`](/reference/generators/admin-user) |
|
|
6
|
+
| `POSTMARK_API_TOKEN` | Postmark email delivery (auto-injected into credentials by the [installer](/reference/generators/install)) |
|
|
7
|
+
| `DEEPL_AUTH_KEY` | automatic locale translation in the [scaffold generator](/reference/generators/scaffold) |
|
|
8
|
+
| `FEATURE_STORAGE` | `local` (development) or `s3` (production) |
|
|
9
|
+
| `S3_BUCKET`, `S3_REGION`, `S3_ENDPOINT`, `S3_ACCESS_KEY_ID`, `S3_SECRET_ACCESS_KEY`, `S3_BASE_URL` | S3 storage configuration for [uploads](/reference/uploaders) |
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Formatters
|
|
2
|
+
|
|
3
|
+
## TypographyFormatter
|
|
4
|
+
|
|
5
|
+
`Trek::TypographyFormatter` applies French typography rules to strings **and** ProseMirror documents (only `text` nodes are modified):
|
|
6
|
+
|
|
7
|
+
- non-breaking spaces before `: ; ! ? % € $ »` and after `«`, dashes, `n°`
|
|
8
|
+
- non-breaking spaces before units (km, kg, h, min, °C…) and between digit groups
|
|
9
|
+
- `...` → `…`, ASCII apostrophes → typographic `'`
|
|
10
|
+
- removes double spaces and spaces before periods/commas
|
|
11
|
+
|
|
12
|
+
Wire it to attributes with [Formattable](/reference/concerns/formattable):
|
|
13
|
+
|
|
14
|
+
```ruby
|
|
15
|
+
include Trek::Formattable
|
|
16
|
+
format_attributes Trek::TypographyFormatter, :title
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## ProseMirror → HTML pipeline
|
|
20
|
+
|
|
21
|
+
`formatted_content` (from [Contentable](/reference/concerns/contentable)) renders ProseMirror JSON to safe HTML through the `prosemirror_to_html` gem, extended with:
|
|
22
|
+
|
|
23
|
+
| Piece | Role |
|
|
24
|
+
| --- | --- |
|
|
25
|
+
| `Nodes::ImageBlock` | renders `image_block` nodes as figures (Shrine image, alt, caption, size) |
|
|
26
|
+
| `Nodes::PromptsBlock` | renders `prompts_block` nodes as call-to-action buttons |
|
|
27
|
+
| `RemoveEmptyParagraphsFormatter` | strips empty `<p></p>` tags |
|
|
28
|
+
| `GlobalIdToLinksFormatter` | resolves `gid://` references in links to real record URLs |
|
|
29
|
+
|
|
30
|
+
The pipeline is orchestrated by the `Prosemirror` model — extend it with your own node renderers when you add custom blocks to the editor.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Forms
|
|
2
|
+
|
|
3
|
+
Trek ships `Trek::FormBuilder`, an extension of [`ViewComponent::Form`](https://github.com/pantographe/view_component-form)'s builder, automatically used in admin views. On top of the standard helpers, it provides:
|
|
4
|
+
|
|
5
|
+
| Helper | Renders |
|
|
6
|
+
| --- | --- |
|
|
7
|
+
| `f.group` | a label + input wrapper with errors |
|
|
8
|
+
| `f.content_editor` | the Tiptap rich text editor |
|
|
9
|
+
| `f.image_field` | an image uploader with thumbnail preview (Uppy + Shrine) |
|
|
10
|
+
| `f.sound_field` | an audio file uploader |
|
|
11
|
+
| `f.switch_box` | a toggle switch |
|
|
12
|
+
| `f.link_select` | a link picker (internal pages & external links) |
|
|
13
|
+
|
|
14
|
+
Each helper renders the matching component from the [`Trek::Form` namespace](/reference/components#form-components).
|
|
15
|
+
|
|
16
|
+
```slim
|
|
17
|
+
= form_with model: [:admin, @book] do |f|
|
|
18
|
+
= f.group :title
|
|
19
|
+
= f.content_editor :intro, floating: false
|
|
20
|
+
= f.switch_box :published
|
|
21
|
+
```
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# Admin user
|
|
2
|
+
|
|
3
|
+
```sh
|
|
4
|
+
rails g trek:admin:user
|
|
5
|
+
# or (soon)
|
|
6
|
+
trek admin:user
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
Creates an admin user with the credentials defined by the `ADMIN_EMAIL` and `ADMIN_PASSWORD` ENV variables, typically set in `.env`:
|
|
10
|
+
|
|
11
|
+
```sh
|
|
12
|
+
# .env
|
|
13
|
+
ADMIN_EMAIL=admin@example.com
|
|
14
|
+
ADMIN_PASSWORD=a-strong-password
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
The created user gets the `admin` [role](/reference/models/user#roles), which makes it `privileged?` and grants it full access in the default [policies](/reference/policies).
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Installer
|
|
2
|
+
|
|
3
|
+
```sh
|
|
4
|
+
rails g trek:install
|
|
5
|
+
# or (soon)
|
|
6
|
+
trek install
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
Trek provides an install generator, that will:
|
|
10
|
+
|
|
11
|
+
- install all dependencies
|
|
12
|
+
- create the `User` model and include Trek's concerns
|
|
13
|
+
- create the `Page`, `PagePath` and `PageVersion` models and include Trek's concerns
|
|
14
|
+
- create the `Fragment` model and include Trek's concerns
|
|
15
|
+
- create the relevant policies
|
|
16
|
+
- generate and run the relevant migrations
|
|
17
|
+
|
|
18
|
+
## Sub-generators
|
|
19
|
+
|
|
20
|
+
The installer orchestrates dedicated sub-generators, all under the `trek:install:*` namespace. Each one can also be run individually, e.g. `rails g trek:install:healthcheck`.
|
|
21
|
+
|
|
22
|
+
| Area | What gets set up |
|
|
23
|
+
| --- | --- |
|
|
24
|
+
| Authentication | Sorcery, the `UserSession` form model, login/logout & password reset panels |
|
|
25
|
+
| Authorization | ActionPolicy and the base policies |
|
|
26
|
+
| Models | `User`, `Page`, `PagePath`, `PageVersion`, `Fragment`, `MenuNode`, `ExternalLink`, `Current` — with migrations |
|
|
27
|
+
| Attachments | Shrine configuration and the uploaders |
|
|
28
|
+
| Emails | Postmark and the user mailer |
|
|
29
|
+
| I18n | rails-i18n, Mobility, i18n-tasks and the locale files |
|
|
30
|
+
| Admin panels | Pages, fragments, users, sessions, password resets, routes, dashboard |
|
|
31
|
+
| Pagination | Kaminari |
|
|
32
|
+
| Tooling | esbuild, PostCSS, EditorConfig, Procfiles, Makefile, health check endpoint |
|
|
33
|
+
| Linting | Standard, ESLint, Stylelint, Prettier, Slim Lint, Lefthook git hooks |
|
|
34
|
+
| Security | Brakeman, bundler-audit, ruby_audit |
|
|
35
|
+
| CI | GitLab CI configuration |
|
|
36
|
+
|
|
37
|
+
## ENV variables read by the installer
|
|
38
|
+
|
|
39
|
+
Define these **before** running the installer to have them injected automatically:
|
|
40
|
+
|
|
41
|
+
- `POSTMARK_API_TOKEN` — injected into the Rails credentials for email delivery
|
|
42
|
+
- `DEEPL_AUTH_KEY` — enables automatic locale translation in the [scaffold generator](/reference/generators/scaffold)
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# Scaffold
|
|
2
|
+
|
|
3
|
+
```sh
|
|
4
|
+
rails g trek:scaffold Book title intro:text
|
|
5
|
+
```
|
|
6
|
+
|
|
7
|
+
Akin to Rails', Trek's scaffold generates, with a single command:
|
|
8
|
+
|
|
9
|
+
- the `Book` model and migration (calling the Rails `model` generator behind the scenes)
|
|
10
|
+
- the `Admin::BooksController`, inheriting from [`Trek::ResourceController`](/reference/controllers)
|
|
11
|
+
- the Slim views: `index`, `show`, `new`, `edit` and the `_form` partial
|
|
12
|
+
- the `Admin::BookPolicy`, inheriting from [`Trek::ResourcePolicy`](/reference/policies)
|
|
13
|
+
- the `resources :books` route in the `admin` namespace
|
|
14
|
+
- the locale files for the model and its admin panel, in every configured locale (auto-translated via DeepL when `DEEPL_AUTH_KEY` is set)
|
|
15
|
+
- the entry in the admin dashboard menu
|
|
16
|
+
|
|
17
|
+
## Field types
|
|
18
|
+
|
|
19
|
+
Standard Rails attribute types are supported (`string`, `text`, `integer`, `float`, `decimal`, `boolean`, `date`, `datetime`, `references`…) and mapped to the matching [form helpers](/reference/forms): `text` renders the content editor, `boolean` a switch box, `references` a collection select, and so on.
|
|
20
|
+
|
|
21
|
+
## Opt-in concerns
|
|
22
|
+
|
|
23
|
+
The generated model ships with commented-out hooks for Trek's most useful [concerns](/reference/), ready to be enabled when needed:
|
|
24
|
+
|
|
25
|
+
```ruby
|
|
26
|
+
class Book < ApplicationRecord
|
|
27
|
+
# include Trek::Formattable
|
|
28
|
+
# format_attributes Trek::TypographyFormatter, :title
|
|
29
|
+
|
|
30
|
+
# include Trek::Translatable
|
|
31
|
+
# translate_attributes :title
|
|
32
|
+
|
|
33
|
+
# include RecordImageUploader::Attachment(:image)
|
|
34
|
+
|
|
35
|
+
strip_attributes
|
|
36
|
+
end
|
|
37
|
+
```
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Taxonomies
|
|
2
|
+
|
|
3
|
+
```sh
|
|
4
|
+
rails g trek:taxonomies
|
|
5
|
+
```
|
|
6
|
+
|
|
7
|
+
Sets up a tagging & categorization system:
|
|
8
|
+
|
|
9
|
+
- the [`Tag`, `TagCategory` and `Tagging` models](/reference/models/tag) with their migrations
|
|
10
|
+
- the admin panel to manage tags and categories
|
|
11
|
+
|
|
12
|
+
Once installed, make any model taggable with the [`Trek::Taggable`](/reference/concerns/taggable) concern:
|
|
13
|
+
|
|
14
|
+
```ruby
|
|
15
|
+
class Article < ApplicationRecord
|
|
16
|
+
include Trek::Taggable
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
article.tags << Tag.find_or_create_by(name: "Ruby")
|
|
20
|
+
article.tag_names # => ["Ruby"]
|
|
21
|
+
```
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# Icons
|
|
2
|
+
|
|
3
|
+
Trek bundles ~40 SVG icons, rendered with `Trek::IconComponent`:
|
|
4
|
+
|
|
5
|
+
```ruby
|
|
6
|
+
render Trek::IconComponent.new(:search)
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
Available keys include: `add`, `arrow-bar-left`, `arrow-bar-right`, `bold`, `check`, `chevron-left`, `chevron-right`, `chevron-double`, `close`, `cursor`, `danger`, `download`, `eraser`, `eye`, `grid`, `hr`, `italic`, `layout`, `link`, `list`, `logout`, `paragraph`, `pic`, `profile`, `quotation`, `rating`, `redo`, `undo`, `search`…
|
|
10
|
+
|
|
11
|
+
[MenuNode](/reference/models/menu-node) records can reference an icon via their `icon_key` to display it in the admin sidebar.
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# Reference manual
|
|
2
|
+
|
|
3
|
+
A comprehensive list of features and settings included in Trek.
|
|
4
|
+
|
|
5
|
+
## Generators
|
|
6
|
+
|
|
7
|
+
- [Installer](/reference/generators/install) — `rails g trek:install`
|
|
8
|
+
- [Admin user](/reference/generators/admin-user) — `rails g trek:admin:user`
|
|
9
|
+
- [Scaffold](/reference/generators/scaffold) — `rails g trek:scaffold`
|
|
10
|
+
- [Taxonomies](/reference/generators/taxonomies) — `rails g trek:taxonomies`
|
|
11
|
+
|
|
12
|
+
## Models
|
|
13
|
+
|
|
14
|
+
Generated into your application — they're yours to read and modify.
|
|
15
|
+
|
|
16
|
+
- [Page](/reference/models/page), [PageVersion](/reference/models/page-version), [PagePath](/reference/models/page-path)
|
|
17
|
+
- [Fragment](/reference/models/fragment)
|
|
18
|
+
- [MenuNode](/reference/models/menu-node), [ExternalLink](/reference/models/external-link)
|
|
19
|
+
- [User](/reference/models/user) (and its session & password-reset form models)
|
|
20
|
+
- [Tag, TagCategory & Tagging](/reference/models/tag) (with the taxonomies generator)
|
|
21
|
+
- [Current](/reference/models/current)
|
|
22
|
+
|
|
23
|
+
## Concerns
|
|
24
|
+
|
|
25
|
+
Trek's behaviors, packaged as concerns you can mix into any model:
|
|
26
|
+
|
|
27
|
+
- Content: [Contentable](/reference/concerns/contentable), [Fragmentable](/reference/concerns/fragmentable), [Sectionable](/reference/concerns/sectionable), [Formattable](/reference/concerns/formattable)
|
|
28
|
+
- I18n & URLs: [Translatable](/reference/concerns/translatable), [Sluggable](/reference/concerns/sluggable), [Pathable](/reference/concerns/pathable)
|
|
29
|
+
- Pages: [Pageable](/reference/concerns/pageable), [Versionable](/reference/concerns/versionable), [SearchEngineOptimizable](/reference/concerns/search-engine-optimizable)
|
|
30
|
+
- Utilities: [Orderable](/reference/concerns/orderable), [Keyable](/reference/concerns/keyable), [Searchable](/reference/concerns/searchable), [Taggable](/reference/concerns/taggable), [Phonable](/reference/concerns/phonable)
|
|
31
|
+
|
|
32
|
+
## Back-office
|
|
33
|
+
|
|
34
|
+
- [Controllers](/reference/controllers) — `Trek::BaseController`, `Trek::ResourceController`, panels
|
|
35
|
+
- [Forms](/reference/forms) — `Trek::FormBuilder` and its custom helpers
|
|
36
|
+
- [Formatters](/reference/formatters) — typography & ProseMirror-to-HTML pipeline
|
|
37
|
+
- [Policies](/reference/policies) — ActionPolicy integration
|
|
38
|
+
- [Uploaders](/reference/uploaders) — Shrine-based attachments
|
|
39
|
+
|
|
40
|
+
## Front-end
|
|
41
|
+
|
|
42
|
+
- [Components](/reference/components) — the ViewComponents powering the admin UI
|
|
43
|
+
- [Icons](/reference/icons) — the bundled SVG icon set
|
|
44
|
+
|
|
45
|
+
## Configuration
|
|
46
|
+
|
|
47
|
+
- [Environment variables](/reference/environment-variables)
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# Current
|
|
2
|
+
|
|
3
|
+
Request-scoped global context, built on `ActiveSupport::CurrentAttributes` and generated into `app/models/current.rb`.
|
|
4
|
+
|
|
5
|
+
Trek uses it to cache per-request data — for instance the loaded icon set:
|
|
6
|
+
|
|
7
|
+
```ruby
|
|
8
|
+
Current.icons
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Extend it with your own request-scoped attributes as your application grows (current user, tenant, locale…).
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# ExternalLink
|
|
2
|
+
|
|
3
|
+
Links pointing outside your application, usable in [menus](/reference/models/menu-node) and content.
|
|
4
|
+
|
|
5
|
+
## Columns
|
|
6
|
+
|
|
7
|
+
| Column | Type | Notes |
|
|
8
|
+
| --- | --- | --- |
|
|
9
|
+
| `key` | string | unique, optional |
|
|
10
|
+
| `url` | string | required |
|
|
11
|
+
|
|
12
|
+
## Behavior
|
|
13
|
+
|
|
14
|
+
- `has_many :menu_nodes, as: :linkable, dependent: :destroy`
|
|
15
|
+
- `key` uniqueness (allow nil), `url` presence
|
|
16
|
+
- `to_s` returns the URL
|