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.
@@ -1,5 +1,9 @@
1
1
  <template id="coralite-pagination">
2
- {{ paginationList }}
2
+ <nav aria-label="{{ ariaLabel }}">
3
+ <ul class="pagination">
4
+ {{ paginationLinks }}
5
+ </ul>
6
+ </nav>
3
7
  </template>
4
8
 
5
9
  <script type="module">
@@ -7,96 +11,113 @@
7
11
 
8
12
  export default defineComponent({
9
13
  tokens: {
10
- paginationList(values) {
11
- const length = parseInt(values.paginationLength)
12
-
13
- if (!length) return ''
14
-
15
- const maxVisible = parseInt(values.paginationMaxVisible)
16
- const currentPage = parseInt(values.paginationCurrent)
17
- const segment = values.paginationSegment
18
- const indexUrl = values.paginationIndexURLPathname
19
- const isIndexPage = values.$filePathname === values.paginationIndexPathname
20
- let baseDir = values.$urlDirname
21
-
22
- if (!isIndexPage) {
23
- baseDir = values.$urlDirname.replace(`/${segment}`, '')
24
- } else if (!values.$urlPathname.endsWith('index.html')) {
25
- // use filename as a directory
26
- baseDir = '/' + values.$filename.replace('.html', '')
27
- }
28
-
29
- if (baseDir === '/') {
30
- baseDir = ''
31
- }
32
-
14
+ ariaLabel(context) {
15
+ return context['aria-label'] || 'Page navigation'
16
+ },
17
+ /**
18
+ * Generates HTML pagination links based on the provided context.
19
+ *
20
+ * @param {Object} context - The context object containing pagination details.
21
+ * @param {string} context['current-page'] - The current page number (1-based).
22
+ * @param {string} context['total-pages'] - The total number of pages.
23
+ * @param {string} context['base-url'] - The explicit URL for Page 1 (e.g., '/blog.html').
24
+ * @param {string} context['url-prefix'] - The directory prefix for paginated segments (e.g., '/blog').
25
+ * @param {string} [context.segment='page'] - The URL segment for pagination (default: 'page').
26
+ * @param {string} [context.max-visible='5'] - Max number of direct page links to show.
27
+ * @param {string} [context.ellipsis='...'] - Text to display for skipped pages.
28
+ * @returns {string} - A string containing the HTML <li> elements.
29
+ */
30
+ paginationLinks(context) {
31
+ // Parse inputs with defaults
32
+ const currentPage = parseInt(context['current-page'] || '1', 10)
33
+ const totalPages = parseInt(context['total-pages'] || '1', 10)
34
+ const maxVisible = parseInt(context['max-visible'] || '5', 10)
35
+
36
+ const baseUrl = context['base-url'] || ''
37
+ const urlPrefix = context['url-prefix'] || ''
38
+ const segment = context['segment'] || 'page'
39
+ const ellipsis = context['ellipsis'] || '...'
40
+
41
+ /**
42
+ * Constructs the URL for a specific page.
43
+ * 1. Page 1 links strictly to `base-url` (canonical root).
44
+ * 2. Pages > 1 follow the pattern: `{url-prefix}/{segment}/{page}.html`.
45
+ */
33
46
  const getPageUrl = (page) => {
34
47
  if (page === 1) {
35
- return indexUrl
48
+ return baseUrl
36
49
  }
37
- return `${baseDir}/${segment}/${page}.html`
50
+
51
+ // Ensure prefix has a trailing slash for concatenation
52
+ const cleanPrefix = urlPrefix.endsWith('/') ? urlPrefix : `${urlPrefix}/`
53
+ return `${cleanPrefix}${segment}/${page}.html`
38
54
  }
39
55
 
40
- const pages = []
41
- if (maxVisible >= length) {
42
- for (let i = 1; i <= length; i++) pages.push(i)
43
- } else {
44
- // Center the active page
45
- let start = currentPage - Math.floor(maxVisible / 2)
46
- start = Math.max(1, start)
47
- let end = start + maxVisible - 1
48
-
49
- // Shift window if we hit the end bound
50
- if (end > length) {
51
- end = length
52
- start = Math.max(1, end - maxVisible + 1)
53
- }
56
+ // Helper to generate list items
57
+ const createItem = (page, text, isActive, isDisabled) => {
58
+ let className = 'page-item'
59
+ if (isActive) className += ' active'
60
+ if (isDisabled) className += ' disabled'
54
61
 
55
- if (start > 1) {
56
- pages.push(1)
57
- if (start > 2) pages.push('...')
58
- }
62
+ let attr = ''
63
+ if (isActive) attr += ' aria-current="page"'
64
+ if (isDisabled) attr += ' tabindex="-1" aria-disabled="true"'
59
65
 
60
- for (let i = start; i <= end; i++) {
61
- pages.push(i)
62
- }
66
+ const href = isDisabled ? '#' : getPageUrl(page)
63
67
 
64
- if (end < length) {
65
- if (end < length - 1) pages.push('...')
66
- pages.push(length)
67
- }
68
+ return `<li class="${className}"><a class="page-link" href="${href}"${attr}>${text}</a></li>`
68
69
  }
69
70
 
70
- const buildItem = (label, pageNum, isDisabled = false, isActive = false) => {
71
- if (isDisabled) {
72
- return `<li class="page-item disabled"><span class="page-link">${label}</span></li>`
73
- }
74
- const activeClass = isActive ? ' active' : ''
75
- const aria = isActive ? ' aria-current="page"' : ''
76
- return `<li class="page-item${activeClass}"><a class="page-link"${aria} href="${getPageUrl(pageNum)}">${label}</a></li>`
71
+ let links = ''
72
+
73
+ // Previous Link
74
+ links += createItem(currentPage - 1, 'Previous', false, currentPage <= 1)
75
+
76
+ // Calculate Window (Start/End)
77
+ const half = Math.floor(maxVisible / 2)
78
+ let start = currentPage - half
79
+ let end = currentPage + half
80
+
81
+ if (start < 1) {
82
+ start = 1
83
+ end = Math.min(totalPages, maxVisible)
77
84
  }
78
85
 
79
- let html = '<ul class="pagination">'
86
+ if (end > totalPages) {
87
+ end = totalPages
88
+ start = Math.max(1, totalPages - maxVisible + 1)
89
+ }
80
90
 
81
- // Previous
82
- html += buildItem('Previous', currentPage - 1, currentPage <= 1)
91
+ // Render Pages with ellipsis
92
+ const showFirst = start > 1
93
+ const showLast = end < totalPages
83
94
 
84
- // Numbered items
85
- pages.forEach(page => {
86
- if (page === '...') {
87
- html += buildItem('...', null, true)
88
- } else {
89
- html += buildItem(page, page, false, page === currentPage)
95
+ // First page + ellipsis if window doesn't touch start
96
+ if (showFirst) {
97
+ links += createItem(1, '1', false, false)
98
+ if (start > 2) {
99
+ links += `<li class="page-item disabled"><span class="page-link">${ellipsis}</span></li>`
90
100
  }
91
- })
101
+ }
92
102
 
93
- // Next
94
- html += buildItem('Next', currentPage + 1, currentPage >= length)
103
+ // Main window loop
104
+ for (let i = start; i <= end; i++) {
105
+ links += createItem(i, i, i === currentPage, false)
106
+ }
107
+
108
+ // Last page + ellipsis if window doesn't touch end
109
+ if (showLast) {
110
+ if (end < totalPages - 1) {
111
+ links += `<li class="page-item disabled"><span class="page-link">${ellipsis}</span></li>`
112
+ }
113
+ links += createItem(totalPages, totalPages, false, false)
114
+ }
95
115
 
96
- html += '</ul>'
116
+ // Next Link
117
+ links += createItem(currentPage + 1, 'Next', false, currentPage >= totalPages)
97
118
 
98
- return html
119
+ return links
99
120
  }
100
121
  }
101
122
  })
102
- </script>
123
+ </script>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "coralite-plugin-aggregation",
3
- "version": "0.6.0",
3
+ "version": "0.7.1",
4
4
  "description": "A Coralite plugin for dynamically collecting, filtering, sorting, and displaying content across multiple sources. Build database-free Coralite websites with automated content aggregation.",
5
5
  "type": "module",
6
6
  "keywords": [
@@ -39,25 +39,16 @@
39
39
  "lib",
40
40
  "types"
41
41
  ],
42
+ "scripts": {
43
+ "test": "node --test ./tests/index.spec.js"
44
+ },
45
+ "peerDependencies": {
46
+ "coralite": "^0.22.1"
47
+ },
42
48
  "license": "AGPL-3.0-only",
49
+ "packageManager": "pnpm@10.30.0+sha512.2b5753de015d480eeb88f5b5b61e0051f05b4301808a82ec8b840c9d2adf7748eb352c83f5c1593ca703ff1017295bc3fdd3119abb9686efc96b9fcb18200937",
43
50
  "devDependencies": {
44
- "@playwright/test": "^1.52.0",
45
51
  "@stylistic/eslint-plugin-js": "^4.2.0",
46
- "@stylistic/eslint-plugin-plus": "^4.2.0",
47
- "commander": "^14.0.3",
48
- "coralite": "^0.20.1",
49
- "premove": "^4.0.0",
50
- "sirv-cli": "^3.0.1"
51
- },
52
- "dependencies": {
53
- "dom-serializer": "^2.0.0",
54
- "htmlparser2": "^10.0.0"
55
- },
56
- "scripts": {
57
- "build-test": "premove ./dist && coralite -t tests/fixtures/templates -p tests/fixtures/pages -o dist",
58
- "test-e2e": "playwright test --reporter=list",
59
- "test-e2e-report": "playwright show-report",
60
- "test-e2e-ui": "playwright test --ui",
61
- "server": "sirv dist --dev --port 3000"
52
+ "@stylistic/eslint-plugin-plus": "^4.2.0"
62
53
  }
63
54
  }
package/types/index.js CHANGED
@@ -1,56 +1,23 @@
1
1
  /**
2
- * @import {CoraliteToken, CoraliteDocument } from 'coralite/types'
2
+ * @typedef {Object} AggregationPaginationOptions
3
+ * @property {string} [segment='page'] - The URL segment used for pagination (e.g., /blog/page/2).
4
+ * @property {string} [template='coralite-pagination'] - The ID of the component template to use for rendering pagination controls.
5
+ * @property {number} [maxVisible=5] - The maximum number of pagination links to display.
6
+ * @property {string} [ariaLabel='Pagination'] - The ARIA label for the pagination navigation element.
7
+ * @property {string} [ellipsis='...'] - The text to display for truncated page numbers.
3
8
  */
4
9
 
5
10
  /**
6
- * Configuration for templates used to render aggregated results.
7
- * @typedef {Object} CoraliteAggregateTemplate - Templates used to display the result
8
- * @property {string} item - Unique identifier for the component used for each document
9
- */
10
-
11
- /**
12
- * Callback function for filtering aggregated content based on metadata.
13
- * @callback CoraliteAggregateFilter
14
- * @param {CoraliteToken} metadata - Aggregated HTML page metadata
15
- */
16
-
17
- /**
18
- * Callback function for sorting aggregated results based on metadata.
19
- * @callback CoraliteAggregateSort
20
- * @param {Object.<string, (string | CoraliteToken[])>} a - Aggregated HTML page metadata
21
- * @param {Object.<string, (string | CoraliteToken[])>} b - Aggregated HTML page metadata
22
- */
23
-
24
- /**
25
- * Configuration object for content aggregation processes.
26
- * @typedef {Object} CoraliteAggregate – Configuration object for the aggregation process
27
- * @property {string[]} path - The path to aggregate, relative to pages directory
28
- * @property {CoraliteAggregateTemplate | string} template - Templates used to display the result
29
- * @property {Object} [pagination]
30
- * @property {CoraliteAggregateTemplate | string} pagination.template - Pagination template ID
31
- * @property {string} [pagination.segment='page'] - Pagination page segment (e.g. 'page' will result in 'page/1')
32
- * @property {number} pagination.maxVisible - Maximum visible number of pages.
33
- * @property {CoraliteAggregateFilter} [filter] - Callback to filter out unwanted elements from the aggregated content.
34
- * @property {boolean} [recursive] - Whether to recursively search subdirectories
35
- * @property {CoraliteToken} [tokens] - Token configuration options
36
- * @property {CoraliteAggregateSort} [sort] - Sort aggregated pages
37
- * @property {number} [limit] - Specifies the maximum number of results to retrieve.
38
- * @property {number} [offset] - Specifies the starting index for the results list.
39
- */
40
-
41
- /**
42
- * @typedef {Object} PaginationMetadata
43
- * @property {string} paginationIndexPathname - The index path name for pagination.
44
- * @property {string} paginationSegment - The current segment of pagination.
45
- * @property {number} paginationMaxVisible - Maximum number of visible pages in the pagination UI.
46
- * @property {boolean} paginationProcessed - Indicates whether the pagination has been processed.
47
- * @property {string} paginationOffset - String representation of the offset.
48
- * @property {string} paginationFilePathname - The file path name for pagination context.
49
- * @property {string} paginationFileDirname - The directory name of the file for pagination context.
50
- * @property {string} paginationURLPathname - The URL path name used in pagination.
51
- * @property {string} paginationURLDirname - The URL directory name used in pagination.
52
- * @property {number} paginationLength - Total length of the paginated data set.
53
- * @property {number} paginationCurrent - Current page index (as a string).
11
+ * @typedef {Object} AggregationOptions
12
+ * @property {string[]} [path=[]] - An array of relative paths to search for pages within `pagesRoot`.
13
+ * @property {string} [template] - The component ID to use for rendering each item found.
14
+ * @property {AggregationPaginationOptions} [pagination] - Configuration for pagination logic and controls. If present, pagination logic is enabled.
15
+ * @property {function(Object): boolean} [filter] - A callback function to filter pages. It receives the page values object and should return `true` to keep the item.
16
+ * @property {function(Object, Object): number} [sort] - A comparison function for sorting pages. It receives two page value objects (a, b) and should return a number.
17
+ * @property {number} [limit] - The maximum number of items to return (or items per page if pagination is used).
18
+ * @property {number} [offset=0] - The starting index for fetching items.
19
+ * @property {boolean} [recursive=false] - If true, searches subdirectories of the specified paths.
20
+ * @property {Object.<string, (string|function(Object): *)>} [tokens] - A map of key transformations. Keys are the new property names. Values can be a string (source property name) or a function (receiving page values and returning the new value).
54
21
  */
55
22
 
56
23
  export default {}
@@ -1,75 +0,0 @@
1
- <!DOCTYPE html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="UTF-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>Blog posts</title>
7
- <meta name="name" content="coralite">
8
- <meta name="description" content="look mum, no database!">
9
- </head>
10
- <body>
11
- <h1>Build database free websites</h1>
12
- <hr>
13
-
14
- <section id="pagination">
15
- <h2>Paginated blog posts</h2>
16
-
17
-
18
-
19
- <a href="/blog/post-1.html">
20
- <h3>Great Barrier Reef</h3>
21
- </a>
22
-
23
-
24
- <span>Nemo</span>
25
- <time datetime="2025-01-08T20:23:07.645Z" data-coralite-ref="coralite-author__time-0">
26
- Wed, 8 Jan 25
27
- </time>
28
-
29
-
30
-
31
- <ul class="pagination"><li class="page-item disabled"><span class="page-link">Previous</span></li><li class="page-item active"><a class="page-link" aria-current="page" href="/blog/all/index.html">1</a></li><li class="page-item"><a class="page-link" href="/blog/all/page/2.html">2</a></li><li class="page-item"><a class="page-link" href="/blog/all/page/3.html">3</a></li><li class="page-item disabled"><span class="page-link">...</span></li><li class="page-item"><a class="page-link" href="/blog/all/page/5.html">5</a></li><li class="page-item"><a class="page-link" href="/blog/all/page/2.html">Next</a></li></ul>
32
-
33
-
34
- </section>
35
- <script type="module">(async () => {
36
- const coraliteTemplateScriptHelpers = { "refs": function refs({ refs }) {
37
- const elements = {};
38
- return function(id) {
39
- if (elements[id]) {
40
- return elements[id];
41
- }
42
- const refId = refs[id];
43
- if (!refId) {
44
- return null;
45
- }
46
- const element = document.querySelector('[data-coralite-ref="' + refId + '"]');
47
- if (element) {
48
- elements[id] = element;
49
- }
50
- return element;
51
- };
52
- } };
53
- const getHelpers = (context) => {
54
- const helpers = {};
55
- for (const key in coraliteTemplateScriptHelpers) {
56
- if (!Object.hasOwn(coraliteTemplateScriptHelpers, key)) continue;
57
- helpers[key] = coraliteTemplateScriptHelpers[key](context);
58
- }
59
- return helpers;
60
- };
61
- const coraliteTemplateFunctions = {
62
- "coralite-author": function script({ values }, { refs }) {
63
- const timeElement = refs("time");
64
- timeElement.setAttribute("data-was-here", values.datetime);
65
- }
66
- };
67
- ;
68
- (async () => {
69
- const context = { "instanceId": "tests/fixtures/pages/blog/all/index.html0coralite-posts0coralite-post0coralite-author", "templateId": "coralite-author", "refs": { "time": "coralite-author__time-0" }, "values": { "datetime": "2025-01-08T20:23:07.645Z" }, "document": {} };
70
- const helpers = getHelpers(context);
71
- await coraliteTemplateFunctions["coralite-author"](context, helpers);
72
- })();
73
- })();
74
- </script></body>
75
- </html>
@@ -1,75 +0,0 @@
1
- <!DOCTYPE html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="UTF-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>Blog posts</title>
7
- <meta name="name" content="coralite">
8
- <meta name="description" content="look mum, no database!">
9
- </head>
10
- <body>
11
- <h1>Build database free websites</h1>
12
- <hr>
13
-
14
- <section id="pagination">
15
- <h2>Paginated blog posts</h2>
16
-
17
-
18
-
19
- <a href="/blog/post-1.html">
20
- <h3>Great Barrier Reef</h3>
21
- </a>
22
-
23
-
24
- <span>Nemo</span>
25
- <time datetime="2025-01-08T20:23:07.645Z" data-coralite-ref="coralite-author__time-0">
26
- Wed, 8 Jan 25
27
- </time>
28
-
29
-
30
-
31
- <ul class="pagination"><li class="page-item disabled"><span class="page-link">Previous</span></li><li class="page-item active"><a class="page-link" aria-current="page" href="/blog/all/index.html">1</a></li><li class="page-item"><a class="page-link" href="/blog/all/page/2.html">2</a></li><li class="page-item"><a class="page-link" href="/blog/all/page/3.html">3</a></li><li class="page-item disabled"><span class="page-link">...</span></li><li class="page-item"><a class="page-link" href="/blog/all/page/5.html">5</a></li><li class="page-item"><a class="page-link" href="/blog/all/page/2.html">Next</a></li></ul>
32
-
33
-
34
- </section>
35
- <script type="module">(async () => {
36
- const coraliteTemplateScriptHelpers = { "refs": function refs({ refs }) {
37
- const elements = {};
38
- return function(id) {
39
- if (elements[id]) {
40
- return elements[id];
41
- }
42
- const refId = refs[id];
43
- if (!refId) {
44
- return null;
45
- }
46
- const element = document.querySelector('[data-coralite-ref="' + refId + '"]');
47
- if (element) {
48
- elements[id] = element;
49
- }
50
- return element;
51
- };
52
- } };
53
- const getHelpers = (context) => {
54
- const helpers = {};
55
- for (const key in coraliteTemplateScriptHelpers) {
56
- if (!Object.hasOwn(coraliteTemplateScriptHelpers, key)) continue;
57
- helpers[key] = coraliteTemplateScriptHelpers[key](context);
58
- }
59
- return helpers;
60
- };
61
- const coraliteTemplateFunctions = {
62
- "coralite-author": function script({ values }, { refs }) {
63
- const timeElement = refs("time");
64
- timeElement.setAttribute("data-was-here", values.datetime);
65
- }
66
- };
67
- ;
68
- (async () => {
69
- const context = { "instanceId": "tests/fixtures/pages/blog/all/page/2.html0coralite-posts0coralite-post0coralite-author", "templateId": "coralite-author", "refs": { "time": "coralite-author__time-0" }, "values": { "datetime": "2025-01-08T20:23:07.645Z" }, "document": {} };
70
- const helpers = getHelpers(context);
71
- await coraliteTemplateFunctions["coralite-author"](context, helpers);
72
- })();
73
- })();
74
- </script></body>
75
- </html>
@@ -1,75 +0,0 @@
1
- <!DOCTYPE html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="UTF-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>Blog posts</title>
7
- <meta name="name" content="coralite">
8
- <meta name="description" content="look mum, no database!">
9
- </head>
10
- <body>
11
- <h1>Build database free websites</h1>
12
- <hr>
13
-
14
- <section id="pagination">
15
- <h2>Paginated blog posts</h2>
16
-
17
-
18
-
19
- <a href="/blog/post-1.html">
20
- <h3>Great Barrier Reef</h3>
21
- </a>
22
-
23
-
24
- <span>Nemo</span>
25
- <time datetime="2025-01-08T20:23:07.645Z" data-coralite-ref="coralite-author__time-0">
26
- Wed, 8 Jan 25
27
- </time>
28
-
29
-
30
-
31
- <ul class="pagination"><li class="page-item disabled"><span class="page-link">Previous</span></li><li class="page-item active"><a class="page-link" aria-current="page" href="/blog/all/index.html">1</a></li><li class="page-item"><a class="page-link" href="/blog/all/page/2.html">2</a></li><li class="page-item"><a class="page-link" href="/blog/all/page/3.html">3</a></li><li class="page-item disabled"><span class="page-link">...</span></li><li class="page-item"><a class="page-link" href="/blog/all/page/5.html">5</a></li><li class="page-item"><a class="page-link" href="/blog/all/page/2.html">Next</a></li></ul>
32
-
33
-
34
- </section>
35
- <script type="module">(async () => {
36
- const coraliteTemplateScriptHelpers = { "refs": function refs({ refs }) {
37
- const elements = {};
38
- return function(id) {
39
- if (elements[id]) {
40
- return elements[id];
41
- }
42
- const refId = refs[id];
43
- if (!refId) {
44
- return null;
45
- }
46
- const element = document.querySelector('[data-coralite-ref="' + refId + '"]');
47
- if (element) {
48
- elements[id] = element;
49
- }
50
- return element;
51
- };
52
- } };
53
- const getHelpers = (context) => {
54
- const helpers = {};
55
- for (const key in coraliteTemplateScriptHelpers) {
56
- if (!Object.hasOwn(coraliteTemplateScriptHelpers, key)) continue;
57
- helpers[key] = coraliteTemplateScriptHelpers[key](context);
58
- }
59
- return helpers;
60
- };
61
- const coraliteTemplateFunctions = {
62
- "coralite-author": function script({ values }, { refs }) {
63
- const timeElement = refs("time");
64
- timeElement.setAttribute("data-was-here", values.datetime);
65
- }
66
- };
67
- ;
68
- (async () => {
69
- const context = { "instanceId": "tests/fixtures/pages/blog/all/page/3.html0coralite-posts0coralite-post0coralite-author", "templateId": "coralite-author", "refs": { "time": "coralite-author__time-0" }, "values": { "datetime": "2025-01-08T20:23:07.645Z" }, "document": {} };
70
- const helpers = getHelpers(context);
71
- await coraliteTemplateFunctions["coralite-author"](context, helpers);
72
- })();
73
- })();
74
- </script></body>
75
- </html>
@@ -1,75 +0,0 @@
1
- <!DOCTYPE html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="UTF-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>Blog posts</title>
7
- <meta name="name" content="coralite">
8
- <meta name="description" content="look mum, no database!">
9
- </head>
10
- <body>
11
- <h1>Build database free websites</h1>
12
- <hr>
13
-
14
- <section id="pagination">
15
- <h2>Paginated blog posts</h2>
16
-
17
-
18
-
19
- <a href="/blog/post-1.html">
20
- <h3>Great Barrier Reef</h3>
21
- </a>
22
-
23
-
24
- <span>Nemo</span>
25
- <time datetime="2025-01-08T20:23:07.645Z" data-coralite-ref="coralite-author__time-0">
26
- Wed, 8 Jan 25
27
- </time>
28
-
29
-
30
-
31
- <ul class="pagination"><li class="page-item disabled"><span class="page-link">Previous</span></li><li class="page-item active"><a class="page-link" aria-current="page" href="/blog/all/index.html">1</a></li><li class="page-item"><a class="page-link" href="/blog/all/page/2.html">2</a></li><li class="page-item"><a class="page-link" href="/blog/all/page/3.html">3</a></li><li class="page-item disabled"><span class="page-link">...</span></li><li class="page-item"><a class="page-link" href="/blog/all/page/5.html">5</a></li><li class="page-item"><a class="page-link" href="/blog/all/page/2.html">Next</a></li></ul>
32
-
33
-
34
- </section>
35
- <script type="module">(async () => {
36
- const coraliteTemplateScriptHelpers = { "refs": function refs({ refs }) {
37
- const elements = {};
38
- return function(id) {
39
- if (elements[id]) {
40
- return elements[id];
41
- }
42
- const refId = refs[id];
43
- if (!refId) {
44
- return null;
45
- }
46
- const element = document.querySelector('[data-coralite-ref="' + refId + '"]');
47
- if (element) {
48
- elements[id] = element;
49
- }
50
- return element;
51
- };
52
- } };
53
- const getHelpers = (context) => {
54
- const helpers = {};
55
- for (const key in coraliteTemplateScriptHelpers) {
56
- if (!Object.hasOwn(coraliteTemplateScriptHelpers, key)) continue;
57
- helpers[key] = coraliteTemplateScriptHelpers[key](context);
58
- }
59
- return helpers;
60
- };
61
- const coraliteTemplateFunctions = {
62
- "coralite-author": function script({ values }, { refs }) {
63
- const timeElement = refs("time");
64
- timeElement.setAttribute("data-was-here", values.datetime);
65
- }
66
- };
67
- ;
68
- (async () => {
69
- const context = { "instanceId": "tests/fixtures/pages/blog/all/page/4.html0coralite-posts0coralite-post0coralite-author", "templateId": "coralite-author", "refs": { "time": "coralite-author__time-0" }, "values": { "datetime": "2025-01-08T20:23:07.645Z" }, "document": {} };
70
- const helpers = getHelpers(context);
71
- await coraliteTemplateFunctions["coralite-author"](context, helpers);
72
- })();
73
- })();
74
- </script></body>
75
- </html>