2
0

eleventy.config.mjs 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282
  1. import { readFileSync } from 'node:fs';
  2. import { EleventyRenderPlugin } from "@11ty/eleventy";
  3. import { join } from 'node:path';
  4. import { sync } from 'glob';
  5. import { appFilters } from "../shared/e11ty/filters.mjs";
  6. import { appData, getCopyList } from "../shared/e11ty/data.mjs"
  7. /** @type {import('@11ty/eleventy').LocalConfig} */
  8. export default function (eleventyConfig) {
  9. const environment = process.env.NODE_ENV || "production";
  10. appFilters(eleventyConfig);
  11. appData(eleventyConfig);
  12. eleventyConfig.setInputDirectory("pages");
  13. eleventyConfig.setOutputDirectory("dist");
  14. eleventyConfig.setLayoutsDirectory("../../shared/layouts");
  15. eleventyConfig.setIncludesDirectory("../../shared/includes");
  16. eleventyConfig.setDataDirectory("../../shared/data");
  17. eleventyConfig.addPassthroughCopy({
  18. ...getCopyList(),
  19. "pages/favicon.ico": "favicon.ico",
  20. "static": "static",
  21. });
  22. eleventyConfig.addPlugin(EleventyRenderPlugin, {
  23. accessGlobalData: true,
  24. });
  25. /**
  26. * Data
  27. */
  28. eleventyConfig.addGlobalData("environment", environment);
  29. eleventyConfig.addGlobalData("package", JSON.parse(readFileSync(join("..", "core", "package.json"), "utf-8")));
  30. eleventyConfig.addGlobalData("readme", readFileSync(join("..", "README.md"), "utf-8"));
  31. eleventyConfig.addGlobalData("license", readFileSync(join("..", "LICENSE"), "utf-8"));
  32. eleventyConfig.addGlobalData("changelog", readFileSync(join("..", "core", "CHANGELOG.md"), "utf-8"));
  33. eleventyConfig.addGlobalData("pages", () => {
  34. return sync('pages/**/*.html').filter((file) => {
  35. return !file.includes('pages/_') && !file.includes('pages/docs/index.html');
  36. }).map((file) => {
  37. return {
  38. url: file.replace(/^pages\//, '/')
  39. }
  40. });
  41. });
  42. /**
  43. * Filters
  44. */
  45. eleventyConfig.addFilter("miliseconds_to_minutes", function (value) {
  46. // Raturn 3:45 time format
  47. const minutes = Math.floor(value / 60000);
  48. const seconds = ((value % 60000) / 1000).toFixed(0);
  49. return `${minutes}:${seconds < 10 ? '0' : ''}${seconds}`;
  50. });
  51. eleventyConfig.addFilter("relative", (page) => {
  52. const segments = (page.url || '').replace(/^\//).split('/');
  53. if (segments.length === 1) {
  54. return '.';
  55. } else {
  56. return '../'.repeat(segments.length - 1).slice(0, -1);
  57. }
  58. });
  59. eleventyConfig.addFilter("contains", (items, item) => {
  60. return items && Array.isArray(items) && items.includes(item);
  61. });
  62. eleventyConfig.addFilter("concat_objects", function (object, object2) {
  63. if (
  64. object &&
  65. object2 &&
  66. typeof object === 'object' &&
  67. typeof object2 === 'object' &&
  68. !Array.isArray(object) &&
  69. !Array.isArray(object2)
  70. ) {
  71. return { ...object, ...object2 };
  72. }
  73. return object;
  74. });
  75. eleventyConfig.addFilter("replace_regex", function (input, regStr, replStr) {
  76. const regex = new RegExp(regStr, 'gm');
  77. return input.replace(regex, replStr);
  78. });
  79. eleventyConfig.addFilter("timestamp_to_date", function (timestamp) {
  80. const date = new Date(timestamp * 1000); // Convert timestamp to milliseconds
  81. return date.toISOString().split('T')[0]; // Extract the date in 'YYYY-MM-DD' format
  82. });
  83. eleventyConfig.addFilter("split_to_n", function (arr, n) {
  84. const chunkSize = Math.round(arr.length / n);
  85. const result = [];
  86. for (let i = 0; i < arr.length; i += chunkSize) {
  87. result.push(arr.slice(i, i + chunkSize));
  88. }
  89. return result;
  90. })
  91. eleventyConfig.addFilter("format_number", function (value) {
  92. return value.toString()
  93. .split('')
  94. .reverse()
  95. .reduce((acc, char, index) => {
  96. if (index > 0 && index % 3 === 0) {
  97. acc.push(',');
  98. }
  99. acc.push(char);
  100. return acc;
  101. }, [])
  102. .reverse()
  103. .join('');
  104. });
  105. function randomNumber(x, min = 0, max = 100, round = 0) {
  106. let value = ((x * x * Math.PI * Math.E * (max + 1) * (Math.sin(x) / Math.cos(x * x))) % (max + 1 - min)) + min;
  107. value = value > max ? max : value;
  108. value = value < min ? min : value;
  109. if (round !== 0) {
  110. value = parseFloat(value.toFixed(round));
  111. } else {
  112. value = Math.floor(value);
  113. }
  114. return value;
  115. }
  116. eleventyConfig.addFilter("random_date_ago", function (x, daysAgo = 100) {
  117. const today = new Date();
  118. const randomDaysAgo = randomNumber(x, 0, daysAgo);
  119. today.setDate(today.getDate() - randomDaysAgo);
  120. return today;
  121. });
  122. eleventyConfig.addFilter("random_date", function (x, startDate = null, endDate = null) {
  123. const start = new Date(startDate ? startDate : '2024-01-01').getTime() / 1000;
  124. const end = new Date(endDate ? endDate : '2024-12-30').getTime() / 1000;
  125. const randomTimestamp = randomNumber(x, start, end);
  126. return new Date(randomTimestamp * 1000);
  127. });
  128. eleventyConfig.addFilter("random_item", function (x, items) {
  129. const index = randomNumber(x, 0, items.length - 1);
  130. return items[index];
  131. });
  132. eleventyConfig.addFilter("random_number", randomNumber);
  133. eleventyConfig.addFilter("first_letters", function capitalizeFirstLetter(string) {
  134. return string.split(' ').map(word => word.charAt(0)).join('');
  135. })
  136. eleventyConfig.addFilter("uc_first", function capitalizeFirstLetter(string) {
  137. return string.charAt(0).toUpperCase() + string.slice(1);
  138. })
  139. eleventyConfig.addFilter("size", function (elem) {
  140. if (elem instanceof Object) {
  141. return Object.keys(elem).length;
  142. }
  143. return elem.length;
  144. })
  145. eleventyConfig.addFilter("first", function (elem) {
  146. if (elem instanceof Object) {
  147. return elem[Object.keys(elem)[0]];
  148. }
  149. return elem[0];
  150. })
  151. // time ago from today
  152. eleventyConfig.addFilter("timeago", function (date) {
  153. const seconds = Math.floor((new Date() - date) / 1000);
  154. let interval = Math.floor(seconds / 31536000);
  155. if (interval > 1) {
  156. return interval + " years ago";
  157. }
  158. interval = Math.floor(seconds / 2592000);
  159. if (interval > 1) {
  160. return interval + " months ago";
  161. }
  162. interval = Math.floor(seconds / 86400);
  163. if (interval > 1) {
  164. return interval + " days ago";
  165. }
  166. interval = Math.floor(seconds / 3600);
  167. if (interval > 1) {
  168. return interval + " hours ago";
  169. }
  170. interval = Math.floor(seconds / 60);
  171. if (interval > 1) {
  172. return interval + " minutes ago";
  173. }
  174. if (seconds > 0) {
  175. return Math.floor(seconds) + " seconds ago";
  176. }
  177. return "now";
  178. })
  179. /**
  180. * Shortcodes
  181. */
  182. const tags = ["highlight", "endhighlight"];
  183. tags.forEach(tag => {
  184. eleventyConfig.addLiquidTag(tag, function (liquidEngine) {
  185. return {
  186. parse: function (tagToken, remainingTokens) {
  187. this.str = tagToken.args;
  188. },
  189. render: function (scope, hash) {
  190. return "";
  191. },
  192. };
  193. });
  194. });
  195. let _CAPTURES = {};
  196. eleventyConfig.on('beforeBuild', () => {
  197. _CAPTURES = {};
  198. });
  199. ['script', 'modal'].forEach((tag) => {
  200. eleventyConfig.addPairedShortcode(`capture_${tag}`, function (content, inline) {
  201. if (inline) {
  202. return content;
  203. }
  204. if (!_CAPTURES[tag]) {
  205. _CAPTURES[tag] = []
  206. }
  207. if (!_CAPTURES[tag][this.page.inputPath]) {
  208. _CAPTURES[tag][this.page.inputPath] = [];
  209. }
  210. _CAPTURES[tag][this.page.inputPath].push(content);
  211. return ''
  212. })
  213. eleventyConfig.addShortcode(`${tag}s`, function () {
  214. if (_CAPTURES[tag] && _CAPTURES[tag][this.page.inputPath]) {
  215. return _CAPTURES[tag][this.page.inputPath] ? `<!-- BEGIN PAGE ${tag.toUpperCase()}S -->\n${_CAPTURES[tag][this.page.inputPath].join('\n').trim()}\n<!-- END PAGE ${tag.toUpperCase()}S -->` : '';
  216. }
  217. return ''
  218. });
  219. });
  220. /**
  221. * Transforms
  222. */
  223. if (environment !== "development") {
  224. function prettifyHTML(content, outputPath) {
  225. return outputPath.endsWith('.html')
  226. ? content
  227. .replace(/\/\/ @formatter:(on|off)\n+/gm, '')
  228. // remove empty lines
  229. .replace(/^\s*[\r\n]/gm, '')
  230. : content
  231. }
  232. eleventyConfig.addTransform('htmlformat', prettifyHTML)
  233. }
  234. };