eleventy.config.mjs 7.1 KB

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