@rettangoli/sites 1.0.0-rc2 → 1.0.0-rc4

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
@@ -115,10 +115,14 @@ Available in YAML templates/pages without extra setup:
115
115
  - `jsonStringify(value, space = 0)`
116
116
  - `formatDate(value, format = "YYYYMMDDHHmmss", useUtc = true)`
117
117
  - `now(format = "YYYYMMDDHHmmss", useUtc = true)`
118
+ - `sort(list, key, order = "asc")`
119
+ - `md(content)`
118
120
  - `toQueryString(object)`
119
121
 
120
122
  `formatDate` tokens: `YYYY`, `MM`, `DD`, `HH`, `mm`, `ss`.
121
123
  `decodeURI`/`decodeURIComponent` return the original input when decoding fails.
124
+ `sort` supports `order` as `asc` or `desc` (default: `asc`), accepts dot-path keys (for example `data.date`), and returns a new array.
125
+ `md` returns raw rendered HTML from Markdown for template insertion.
122
126
 
123
127
  ## Screenshots
124
128
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rettangoli/sites",
3
- "version": "1.0.0-rc2",
3
+ "version": "1.0.0-rc4",
4
4
  "description": "Generate static sites using Markdown and YAML for docs, blogs, and marketing sites.",
5
5
  "author": {
6
6
  "name": "Luciano Hanyon Wu",
@@ -1,3 +1,7 @@
1
+ import MarkdownIt from 'markdown-it';
2
+
3
+ const markdownRenderer = new MarkdownIt();
4
+
1
5
  function toDate(value) {
2
6
  if (value instanceof Date) {
3
7
  return value;
@@ -71,6 +75,78 @@ function safeDecode(value, decoder) {
71
75
  }
72
76
  }
73
77
 
78
+ function readSortValue(item, key, keyParts) {
79
+ if (key == null) {
80
+ return item;
81
+ }
82
+
83
+ if (item == null) {
84
+ return undefined;
85
+ }
86
+
87
+ if (!keyParts) {
88
+ return item?.[key];
89
+ }
90
+
91
+ if (Object.prototype.hasOwnProperty.call(item, key)) {
92
+ return item[key];
93
+ }
94
+
95
+ let current = item;
96
+ for (const part of keyParts) {
97
+ if (!part) {
98
+ return undefined;
99
+ }
100
+ current = current?.[part];
101
+ }
102
+ return current;
103
+ }
104
+
105
+ function sortImpl(value, key, order = 'asc') {
106
+ if (!Array.isArray(value)) {
107
+ return [];
108
+ }
109
+
110
+ const normalizedOrder = String(order ?? 'asc').toLowerCase() === 'desc' ? 'desc' : 'asc';
111
+ const factor = normalizedOrder === 'asc' ? 1 : -1;
112
+ const keyParts = typeof key === 'string' && key.includes('.') ? key.split('.') : null;
113
+
114
+ return [...value].sort((left, right) => {
115
+ const leftRaw = readSortValue(left, key, keyParts);
116
+ const rightRaw = readSortValue(right, key, keyParts);
117
+
118
+ if (leftRaw == null && rightRaw == null) return 0;
119
+ if (leftRaw == null) return 1;
120
+ if (rightRaw == null) return -1;
121
+
122
+ const leftDate = Date.parse(String(leftRaw));
123
+ const rightDate = Date.parse(String(rightRaw));
124
+ const canCompareAsDate = !Number.isNaN(leftDate) && !Number.isNaN(rightDate);
125
+
126
+ if (canCompareAsDate) {
127
+ if (leftDate === rightDate) return 0;
128
+ return leftDate > rightDate ? factor : -factor;
129
+ }
130
+
131
+ if (typeof leftRaw === 'number' && typeof rightRaw === 'number') {
132
+ if (leftRaw === rightRaw) return 0;
133
+ return leftRaw > rightRaw ? factor : -factor;
134
+ }
135
+
136
+ const leftText = String(leftRaw);
137
+ const rightText = String(rightRaw);
138
+ const result = leftText.localeCompare(rightText);
139
+ if (result === 0) return 0;
140
+ return result > 0 ? factor : -factor;
141
+ });
142
+ }
143
+
144
+ function mdImpl(content) {
145
+ return {
146
+ __html: markdownRenderer.render(String(content ?? '')),
147
+ };
148
+ }
149
+
74
150
  export const builtinTemplateFunctions = {
75
151
  encodeURI: (value) => encodeURI(String(value ?? '')),
76
152
  encodeURIComponent: (value) => encodeURIComponent(String(value ?? '')),
@@ -79,6 +155,8 @@ export const builtinTemplateFunctions = {
79
155
  jsonStringify,
80
156
  formatDate: formatDateImpl,
81
157
  now: (format = 'YYYYMMDDHHmmss', useUtc = true) => formatDateImpl(new Date(), format, useUtc),
158
+ sort: sortImpl,
159
+ md: mdImpl,
82
160
  toQueryString,
83
161
  };
84
162
 
@@ -227,10 +227,14 @@ Use these directly in `${...}` expressions:
227
227
  - `jsonStringify(value, space = 0)`
228
228
  - `formatDate(value, format = "YYYYMMDDHHmmss", useUtc = true)`
229
229
  - `now(format = "YYYYMMDDHHmmss", useUtc = true)`
230
+ - `sort(list, key, order = "asc")`
231
+ - `md(content)`
230
232
  - `toQueryString(object)`
231
233
 
232
234
  Date format tokens: `YYYY`, `MM`, `DD`, `HH`, `mm`, `ss`.
233
235
  `decodeURI`/`decodeURIComponent` return the original input when decoding fails.
236
+ `sort` supports `order` as `asc` or `desc` (default: `asc`), accepts dot-path keys (for example `data.date`), and returns a new array.
237
+ `md` returns raw rendered HTML from Markdown for template insertion.
234
238
 
235
239
  ## Static Files
236
240