eleventy.config.mjs 7.3 KB

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