coralite-plugin-aggregation 0.6.0 → 0.7.1

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.
package/README.md CHANGED
@@ -1,302 +1,117 @@
1
1
  # Coralite Aggregation Plugin
2
2
 
3
- The **Coralite Aggregation Plugin** is a powerful tool designed to help developers dynamically collect, filter, sort, and display content across multiple sources within a Coralite project.
3
+ A [Coralite](https://coralite.dev) plugin for aggregating pages (like blog posts) with built-in support for filtering, sorting, and pagination.
4
4
 
5
-
6
- - [Installation](#installation)
7
- - [Example](#example)
8
- - [Type definition](#types)
9
- - [Custom pager](#custom-pager)
10
-
11
- ---
12
-
13
- ## Features
14
-
15
- - **Content Aggregation**: Gather content from multiple files or directories using path patterns (e.g., `blog/`, `['products/all','blog/']`).
16
- - **Filtering & Sorting**: Use metadata-based filters and custom sort functions to refine results based on attributes like tags, categories, dates, or tokens.
17
- - **Pagination Support**: Easily create paginated views with customizable templates for navigation controls and visible page links.
18
- - **Token Handling**: Configure token aliases, defaults, and metadata mapping.
19
-
20
- ---
21
-
22
- ## Coralite Aggregation Plugin Guide
23
-
24
- ### Installation
5
+ ## Installation
25
6
 
26
7
  ```bash
8
+ pnpm add coralite-plugin-aggregation
9
+ # or
27
10
  npm install coralite-plugin-aggregation
28
11
  ```
29
12
 
30
- ### Setup Configuration
31
- First, enable the plugin in your `coralite.config.js`:
32
-
33
- ```js
34
- // coralite.config.js
35
- import aggregation from 'coralite-plugin-aggregation'
13
+ ## Usage
36
14
 
37
- export default {
38
- plugins: [aggregation]
39
- }
40
- ```
41
-
42
- > **Note**: The plugin must be imported as `'coralite-plugin-aggregation'` for compatibility with the core Coralite framework.
43
-
44
- ---
45
-
46
- ### Example Implementation
47
-
48
- #### Entry Point: Displaying Aggregated Results
49
- Create a file like `coralite-posts.html` to define your aggregation logic and rendering template:
50
-
51
- ```html
52
- <!-- templates/coralite-posts.html -->
53
- <template id="coralite-posts">
54
- <div>
55
- {{ posts }}
56
- <!-- Pagination controls will be injected automatically if enabled. -->
57
- </div>
58
- </template>
15
+ First, register the plugin in your Coralite configuration (e.g., `coralite.config.js` or wherever you initialize Coralite).
59
16
 
60
- <script type="module">
61
- import { defineComponent, aggregation } from 'coralite/plugins'
17
+ ```javascript
18
+ import { Coralite } from 'coralite'
19
+ import { aggregation } from 'coralite-plugin-aggregation'
62
20
 
63
- export default defineComponent({
64
- tokens: {
65
- // Aggregation function returns an array of content items.
66
- posts() {
67
- return aggregation({
68
- path: ['products'], // Source directory.
69
- template: 'coralite-post', // Template ID for individual items.
70
- limit: 20, // Maximum number of results per page.
71
- recursive: true, // Include subdirectories.
72
- pagination: {
73
- token: 'post_count', // Page size control token.
74
- template: 'coralite-pagination', // Template for pagination controls.
75
- segment: 'page', // Segment for paginated URLs (e.g., `page/1`).
76
- maxVisible: 5 // Max number of visible page links.
77
- },
78
- filter(meta) {
79
- return meta.name === 'category' && meta.content === 'tech'
80
- },
81
- sort(a, b) {
82
- return new Date(b.date) - new Date(a.date)
83
- },
84
- tokens: {
85
- default: {
86
- author: 'Anonymous',
87
- category: 'uncategorized'
88
- },
89
- aliases: {
90
- tags: ['tech', 'news', 'tutorial']
91
- }
92
- }
93
- })
94
- }
95
- }
21
+ const coralite = new Coralite({
22
+ // ... other config
23
+ plugins: [aggregation]
96
24
  })
97
- </script>
98
25
  ```
99
26
 
100
- #### Aggregated Content Files
101
- Each file to be aggregated must include metadata via `<meta>` elements. For example:
27
+ Then, you can use the `aggregation` function within your component templates.
102
28
 
103
- ```html
104
- <!-- pages/products/product-1.html -->
105
- <!DOCTYPE html>
106
- <html lang="en">
107
- <head>
108
- <meta charset="UTF-8" />
109
- <meta name="title" content="Great Barrier Reef" />
110
- <meta name="description" content="The Great Barrier Reef—largest, comprising over 2,900 individual reefs and 900 islands stretching for over 2,600 kilometers." />
111
- <meta name="price" content="1000" />
112
- <meta name="published_time" content="2025-01-08T20:23:07.645Z" />
113
- </head>
114
- <body>
115
- <coralite-header>
116
- <h1>Great Barrier Reef</h1>
117
- </coralite-header>
118
- <coralite-author name="Nemo" datetime="2025-01-08T20:23:07.645Z"></coralite-author>
119
- </body>
120
- </html>
121
- ```
29
+ ### Example: Blog List
122
30
 
123
- #### Single Result Template
124
- Define a `<template>` element for rendering individual items:
31
+ Create a template for individual items (e.g., `templates/coralite-post.html`):
125
32
 
126
33
  ```html
127
- <!-- templates/coralite-post.html -->
128
34
  <template id="coralite-post">
129
- <div class="post-item">
130
- <h2>{{ $title }}</h2>
131
- <p>{{ $description }} - {{ formattedPrice }}</p>
132
- </div>
35
+ <article class="post">
36
+ <h2><a href="{{ $urlPathname }}">{{ meta_title }}</a></h2>
37
+ <p>{{ meta_description }}</p>
38
+ </article>
133
39
  </template>
134
-
135
- <script type="module">
136
- import { defineComponent } from 'coralite/plugins'
137
-
138
- export default defineComponent({
139
- tokens: {
140
- // Custom token to format prices using Intl.NumberFormat.
141
- formattedPrice(values) {
142
- return new Intl.NumberFormat("en-AU", { style: "currency", currency: "AUD" }).format(
143
- values.$price
144
- )
145
- }
146
- }
147
- })
148
- </script>
149
40
  ```
150
41
 
151
- > **Token Syntax**: Metadata attributes are accessed in templates as `$<meta name>`. For example, the `<meta name="title">` element is referenced using `$title`.
152
-
153
-
154
- ### Configuration Options {#types}
155
-
156
- #### `CoraliteAggregate` {#coralite-aggregate}
157
- Configuration object for content aggregation processes.
158
-
159
- | Property | Type | Description | Reference |
160
- |-----------------|----------------------------------------------------------------------|-----------------------------------------------------------------------------------------------|-----------|
161
- | `path` | `string[]` | Array of paths relative to the pages directory (e.g., `['products', 'blog/']`). | - |
162
- | `template` | `CoraliteAggregateTemplate` or `string` | Templates used to display the result. Must match an existing `<template>` element by ID. | [CoraliteAggregateTemplate](#coralite-aggregate-template) |
163
- | `pagination` | `Object` | Pagination settings (optional). | - |
164
- | `filter` | [`CoraliteAggregateFilter`](#coralite-aggregate-filter) | Callback to filter out unwanted elements from the aggregated content. | [CoraliteAggregateFilter](#coralite-aggregate-filter) |
165
- | `recursive` | `boolean` | Whether to recursively search subdirectories. | - |
166
- | `tokens` | [`CoraliteTokenOptions`](#coralite-token-options) | Token configuration options (optional). | [CoraliteTokenOptions](#coralite-token-options) |
167
- | `sort` | [`CoraliteAggregateSort`](#coralite-aggregate-sort) | Sort aggregated pages. | [CoraliteAggregateSort](#coralite-aggregate-sort) |
168
- | `limit` | `number` | Maximum number of results to retrieve (used with pagination). | - |
169
- | `offset` | `number` | Starting index for the results list (used with pagination). | - |
170
-
171
- ---
172
-
173
- #### `CoraliteAggregateTemplate` {#coralite-aggregate-template}
174
- Configuration for templates used to render aggregated results.
175
-
176
- | Property | Type | Description | Reference |
177
- |----------|-----------|-----------------------------------------------------------------------------|-----------|
178
- | `item` | `string` | Unique identifier for the component used for each document (e.g., `'coralite-post'`). | - |
179
-
180
- ---
181
-
182
- #### `CoraliteTokenOptions` {#coralite-token-options}
183
- Configuration options for token handling during processing.
184
-
185
- | Property | Type | Description |
186
- |--------------|-------------------------------------------------------|-----------------------------------------------------------------------------|
187
- | `default` | `Object.<string, string>` | Default token values for properties not explicitly set (e.g., `{ author: 'Anonymous' }`). |
188
- | `aliases` | `Object.<string, string[]>` | Token aliases and their possible values (e.g., `{ tags: ['tech', 'news'] }`). |
189
-
190
- ---
191
-
192
- #### `CoraliteAggregateFilter` {#coralite-aggregate-filter}
193
- Callback function for filtering aggregated content based on metadata.
194
-
195
- | Parameter | Type | Description |
196
- |---------------|-------------------------------------|-----------------------------------------------------------------------------|
197
- | `metadata` | [`CoraliteToken`](#coralite-token) | Aggregated HTML page metadata (e.g., `{ name: 'category', content: 'tech' }`). |
198
-
199
- ---
200
-
201
- #### `CoraliteAggregateSort` {#coralite-aggregate-sort}
202
- Callback function for sorting aggregated results based on metadata.
203
-
204
- | Parameter | Type | Description |
205
- |-----------|-------------------------------------|-----------------------------------------------------------------------------|
206
- | `a` | `Object.<string, string>` | Metadata of the first item being compared (e.g., `{ date: '2025-01-08' }`). |
207
- | `b` | `Object.<string, string>` | Metadata of the second item being compared. |
208
-
209
- ---
210
-
211
- #### `CoraliteToken` {#coralite-token}
212
- A representation of a token with name and value.
213
-
214
- | Property | Type | Description |
215
- |----------|--------|-----------------------------------------------------------------------------|
216
- | `name` | `string` | Token identifier (e.g., `'title'`, `'category'`). |
217
- | `content`| `string` | Token value or content (e.g., `'Great Barrier Reef'`, `'tech'`). |
218
-
219
- ---
220
-
221
- ## Custom Pager Template User Guide for Coralite Pagination Component {#custom-pager}
222
-
223
- This guide explains how to create a custom pagination template using the existing `coralite-pagination` component as a reference. The goal is to define a new pager layout below the default implementation, preserving compatibility with the core logic while enabling customization.
224
-
225
- ---
226
-
227
- ### Create a New Template Element
228
- Define a unique `<template>` element for your custom pager. Use an ID distinct from the default (`coralite-pagination`) to avoid conflicts:
42
+ Create a component to list them (e.g., `templates/blog-list.html`):
229
43
 
230
44
  ```html
231
- <template id="coralite-pagination-custom">
232
- {{ paginationList }}
45
+ <template id="blog-list">
46
+ <div class="posts">
47
+ {{ posts }}
48
+ </div>
233
49
  </template>
234
- ```
235
-
236
- ---
237
50
 
238
- ### Implement Custom Logic in `<script type="module">`
239
- Replace or extend the `paginationList` token function with your custom logic. The core structure remains compatible with Coralite’s API, but you can modify rendering rules (e.g., ellipsis behavior, link formatting).
240
-
241
- #### Example: Basic Custom Token Function
242
- ```javascript
243
51
  <script type="module">
244
52
  import { defineComponent } from 'coralite'
53
+ import { aggregation } from 'coralite/plugins'
245
54
 
246
55
  export default defineComponent({
247
56
  tokens: {
248
- paginationList (values) {
249
- const length = parseInt(values.paginationLength)
250
- if (!length) return ''
57
+ posts: async () => {
58
+ return await aggregation({
59
+ // Path to aggregate pages from (relative to pages directory)
60
+ path: ['blog'],
61
+ // Template ID to render for each item
62
+ template: 'coralite-post',
63
+ // Sort by date descending (assuming meta_date exists)
64
+ sort: (a, b) => new Date(b.meta_date) - new Date(a.meta_date),
65
+ // Limit items per page
66
+ limit: 10,
67
+ // Enable pagination
68
+ pagination: {
69
+ segment: 'page', // URL segment: /blog/page/1
70
+ maxVisible: 5, // Max pagination links to show
71
+ ariaLabel: 'Blog Pagination',
72
+ ellipsis: '...'
73
+ }
74
+ })
75
+ }
76
+ }
77
+ })
78
+ </script>
79
+ ```
251
80
 
252
- // Custom logic: render a simplified pager with only previous/next and current page
253
- const currentPage = parseInt(values.paginationCurrent)
254
- const dirname = values.pagination_dirname[0] === '/' ? values.paginationDirname : '/' + values.pagination_dirname
81
+ ## Configuration
255
82
 
256
- let html = '<ul class="pagination">'
83
+ The `aggregation` function accepts an options object with the following properties:
257
84
 
258
- // Previous link
259
- if (currentPage > 1) {
260
- html += `<li class="page-item"><a class="page-link" href="${dirname}/${currentPage - 1}.html">Previous</a></li>`
261
- } else {
262
- html += '<li class="page-item disabled"><span class="page-link">Previous</span></li>'
263
- }
85
+ | Property | Type | Description |
86
+ |----------|------|-------------|
87
+ | `path` | `string[]` | Array of paths to aggregate pages from, relative to the `pages` directory. |
88
+ | `template` | `string` | The ID of the template component to use for rendering each aggregated item. |
89
+ | `limit` | `number` | Maximum number of items to display per page. |
90
+ | `offset` | `number` | Starting index for the results (default: 0). |
91
+ | `recursive` | `boolean` | Whether to recursively search subdirectories (default: `false`). |
92
+ | `filter` | `function` | Callback to filter pages. Receives page values, returns `true`/`false`. |
93
+ | `sort` | `function` | Callback to sort pages. Receives `(a, b)` values. |
94
+ | `tokens` | `Object` | Map of token names to transform functions or value keys. |
95
+ | `pagination` | `Object` | Pagination configuration object. |
264
96
 
265
- // Current page
266
- html += `<li class="page-item active"><span class="page-link">${currentPage}</span></li>`
97
+ ### Pagination Options
267
98
 
268
- // Next link
269
- if (currentPage < length) {
270
- html += `<li class="page-item"><a class="page-link" href="${dirname}/${currentPage + 1}.html">Next</a></li>`
271
- } else {
272
- html += '<li class="page-item disabled"><span class="page-link">Next</span></li>'
273
- }
99
+ | Property | Type | Default | Description |
100
+ |----------|------|---------|-------------|
101
+ | `segment` | `string` | `'page'` | The URL segment used for pagination (e.g., `/page/2`). |
102
+ | `maxVisible` | `number` | `5` | Maximum number of visible page links in the pagination control. |
103
+ | `ariaLabel` | `string` | `'Pagination'` | Aria label for the navigation element. |
104
+ | `ellipsis` | `string` | `'...'` | Text to display for truncated page links. |
105
+ | `template` | `string` | `'coralite-pagination'` | Custom template ID for the pagination control. |
274
106
 
275
- html += '</ul>'
276
- return html
277
- }
278
- }
279
- })
280
- </script>
281
- ```
107
+ ## How Pagination Works
282
108
 
283
- ---
109
+ When `pagination` is enabled and `limit` is set:
284
110
 
285
- ### Template tokens
286
- The pagination template receives these token values:
111
+ 1. **Automatic Page Generation**: If placed on a root page (e.g., `/blog/index.html`), the plugin automatically generates virtual pages for subsequent pages (e.g., `/blog/page/2.html`, `/blog/page/3.html`).
112
+ 2. **Context Aware**: It detects the current page from the URL to determine the correct offset and active page state.
113
+ 3. **Default Template**: A default Bootstrap-compatible pagination template (`coralite-pagination`) is provided out of the box.
287
114
 
288
- | Property | Description |
289
- |------------------------------|-----------------------------------------------------------------------------|
290
- | `paginationIndexPathname` | The index path name for pagination (e.g., `/blog/index.html`). |
291
- | `paginationSegment` | The current segment of pagination (e.g., "page"). |
292
- | `paginationMaxVisible` | Maximum number of visible pages in the pagination UI. |
293
- | `paginationProcessed` | Indicates whether the pagination has been processed (`true`/`false`). |
294
- | `paginationOffset` | String representation of the offset (used for page calculations). |
295
- | `paginationFilePathname` | The file path name for pagination context (e.g., `/blog/page-2.html`). |
296
- | `paginationFileDirname` | The directory name of the file for pagination context (e.g., `/blog`). |
297
- | `paginationURLPathname` | The URL path name used in pagination (e.g., `/blog/`). |
298
- | `paginationURLDirname` | The URL directory name used in pagination (e.g., `/blog`). |
299
- | `paginationLength` | Total length of the paginated data set (used to determine total page count).|
300
- | `paginationCurrent` | Current page index (as a string, e.g., "2"). |
115
+ ## License
301
116
 
302
- ---
117
+ AGPL-3.0-or-later