eleventy.config.mjs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580
  1. import { readFileSync } from 'node:fs';
  2. import { EleventyRenderPlugin } from "@11ty/eleventy";
  3. import { join, dirname } from 'node:path';
  4. /*
  5. * Copy list
  6. */
  7. const getCopyList = () => {
  8. let copy = {
  9. "node_modules/@tabler/core/dist": "core",
  10. "pages/favicon.ico": "favicon.ico",
  11. "static": "static",
  12. }
  13. const libs = JSON.parse(readFileSync('./pages/_data/libs.json'));
  14. let files = []
  15. Object.keys(libs.js).forEach((lib) => {
  16. files.push(Array.isArray(libs.js[lib]) ? libs.js[lib] : [libs.js[lib]])
  17. })
  18. Object.keys(libs.css).forEach((lib) => {
  19. files.push(Array.isArray(libs.css[lib]) ? libs.css[lib] : [libs.css[lib]])
  20. })
  21. Object.keys(libs['js-copy']).forEach((lib) => {
  22. files.push(libs['js-copy'][lib])
  23. })
  24. files = files.flat()
  25. files.forEach((file) => {
  26. if (!file.match(/^https?/)) {
  27. copy[`node_modules/${dirname(file)}`] = `libs/${dirname(file) }`;
  28. }
  29. })
  30. return copy;
  31. }
  32. /** @type {import('@11ty/eleventy').LocalConfig} */
  33. export default function (eleventyConfig) {
  34. const env = process.env.NODE_ENV || "development";
  35. eleventyConfig.setInputDirectory("pages");
  36. eleventyConfig.setOutputDirectory("dist");
  37. eleventyConfig.setLayoutsDirectory("_layouts");
  38. eleventyConfig.setIncludesDirectory("_includes");
  39. eleventyConfig.addWatchTarget("../core/dist/**");
  40. eleventyConfig.setWatchThrottleWaitTime(100);
  41. eleventyConfig.addPassthroughCopy(getCopyList());
  42. eleventyConfig.addPlugin(EleventyRenderPlugin, {
  43. accessGlobalData: true,
  44. });
  45. eleventyConfig.setLiquidOptions({
  46. timezoneOffset: 0,
  47. jekyllInclude: true,
  48. dynamicPartials: true,
  49. jekyllWhere: true,
  50. });
  51. /**
  52. * Data
  53. */
  54. eleventyConfig.addGlobalData("environment", env);
  55. eleventyConfig.addGlobalData("package", JSON.parse(readFileSync(join("..", "core", "package.json"), "utf-8")));
  56. eleventyConfig.addGlobalData("readme", readFileSync(join("..", "README.md"), "utf-8"));
  57. eleventyConfig.addGlobalData("license", readFileSync(join("..", "LICENSE"), "utf-8"));
  58. eleventyConfig.addGlobalData("changelog", readFileSync(join("..", "CHANGELOG.md"), "utf-8"));
  59. eleventyConfig.addGlobalData("site", {
  60. title: "Tabler",
  61. description: "Premium and Open Source dashboard template with responsive and high quality UI.",
  62. themeColor: "#066fd1",
  63. email: "support@tabler.io",
  64. homepage: "https://tabler.io",
  65. githubUrl: "https://github.com/tabler/tabler",
  66. githubSponsorsUrl: "https://github.com/sponsors/codecalm",
  67. changelogUrl: "https://github.com/tabler/tabler/releases",
  68. sponsorUrl: "https://github.com/sponsors/codecalm",
  69. previewUrl: "https://tabler.io/demo",
  70. docsUrl: "https://tabler.io/docs",
  71. mapboxKey: "pk.eyJ1IjoidGFibGVyIiwiYSI6ImNscHh3dnhndjB2M3QycW85bGd0NXRmZ3YifQ.9LfHPsNoEXQH-xzz-81Ffw",
  72. googleMapsKey: "AIzaSyAr5mRB4U1KRkVznIrDWEvZjroYcD202DI",
  73. googleMapsDevKey: "AIzaSyCL-BY8-sq12m0S9H-S_yMqDmcun3A9znw",
  74. npmPackage: "@tabler/core",
  75. tablerCssPlugins: [
  76. "tabler-flags",
  77. "tabler-socials",
  78. "tabler-payments",
  79. "tabler-vendors",
  80. "tabler-marketing"
  81. ],
  82. icons: {
  83. link: "https://tabler.io/icons"
  84. },
  85. emails: {
  86. price: "$29",
  87. buy_link: "https://r.tabler.io/buy-emails"
  88. },
  89. illustrations: {
  90. price: "$59",
  91. count: 50,
  92. buy_link: "https://r.tabler.io/buy-illustrations"
  93. },
  94. colors: {
  95. "blue": {
  96. "class": "blue",
  97. "hex": "#066fd1",
  98. "title": "Blue"
  99. },
  100. "azure": {
  101. "class": "azure",
  102. "hex": "#45aaf2",
  103. "title": "Azure"
  104. },
  105. "indigo": {
  106. "class": "indigo",
  107. "hex": "#6574cd",
  108. "title": "Indigo"
  109. },
  110. "purple": {
  111. "class": "purple",
  112. "hex": "#a55eea",
  113. "title": "Purple"
  114. },
  115. "pink": {
  116. "class": "pink",
  117. "hex": "#f66d9b",
  118. "title": "Pink"
  119. },
  120. "red": {
  121. "class": "red",
  122. "hex": "#fa4654",
  123. "title": "Red"
  124. },
  125. "orange": {
  126. "class": "orange",
  127. "hex": "#fd9644",
  128. "title": "Orange"
  129. },
  130. "yellow": {
  131. "class": "yellow",
  132. "hex": "#f1c40f",
  133. "title": "Yellow"
  134. },
  135. "lime": {
  136. "class": "lime",
  137. "hex": "#7bd235",
  138. "title": "Lime"
  139. },
  140. "green": {
  141. "class": "green",
  142. "hex": "#5eba00",
  143. "title": "Green"
  144. },
  145. "teal": {
  146. "class": "teal",
  147. "hex": "#2bcbba",
  148. "title": "Teal"
  149. },
  150. "cyan": {
  151. "class": "cyan",
  152. "hex": "#17a2b8",
  153. "title": "Cyan"
  154. }
  155. },
  156. skinColors: {
  157. "rose": {
  158. "hex": "#FFCB9D",
  159. "title": "Rose",
  160. "class": "rose"
  161. },
  162. "yellow": {
  163. "hex": "#F0BA60",
  164. "title": "Yellow",
  165. "class": "yellow"
  166. },
  167. "skin-1": {
  168. "hex": "#e2c6a7",
  169. "title": "Skin 1",
  170. "class": "skin-1"
  171. },
  172. "skin-2": {
  173. "hex": "#c7a786",
  174. "title": "Skin 2",
  175. "class": "skin-2"
  176. },
  177. "skin-3": {
  178. "hex": "#a68063",
  179. "title": "Skin 3",
  180. "class": "skin-3"
  181. },
  182. "skin-4": {
  183. "hex": "#926241",
  184. "title": "Skin 4",
  185. "class": "skin-4"
  186. },
  187. "skin-5": {
  188. "hex": "#654c45",
  189. "title": "Skin 5",
  190. "class": "skin-5"
  191. },
  192. "gray": {
  193. "hex": "#d5d7dd",
  194. "title": "Gray",
  195. "class": "gray"
  196. }
  197. },
  198. colorsExtra: {
  199. "white": {
  200. "hex": "#ffffff",
  201. "title": "White"
  202. },
  203. "dark": {
  204. "hex": "#303645",
  205. "title": "Dark"
  206. },
  207. "gray": {
  208. "hex": "#868e96",
  209. "title": "Gray"
  210. }
  211. },
  212. variants: [
  213. {
  214. "name": "success",
  215. "icon": "check"
  216. },
  217. {
  218. "name": "info",
  219. "icon": "info-circle"
  220. },
  221. {
  222. "name": "warning",
  223. "icon": "alert-triangle"
  224. },
  225. {
  226. "name": "danger",
  227. "icon": "alert-circle"
  228. }
  229. ],
  230. "themeColors": {
  231. "primary": {
  232. "class": "primary",
  233. "title": "Primary"
  234. },
  235. "secondary": {
  236. "class": "secondary",
  237. "title": "Secondary"
  238. },
  239. "success": {
  240. "class": "success",
  241. "title": "Success"
  242. },
  243. "warning": {
  244. "class": "warning",
  245. "title": "Warning"
  246. },
  247. "danger": {
  248. "class": "danger",
  249. "title": "Danger"
  250. },
  251. "info": {
  252. "class": "info",
  253. "title": "Info"
  254. },
  255. "dark": {
  256. "class": "dark",
  257. "title": "Dark"
  258. },
  259. "light": {
  260. "class": "light",
  261. "title": "Light"
  262. }
  263. },
  264. "buttonStates": [
  265. {
  266. "class": null,
  267. "title": "Normal"
  268. },
  269. {
  270. "class": "active",
  271. "title": "Active state"
  272. },
  273. {
  274. "class": "disabled",
  275. "title": "Disabled"
  276. }
  277. ],
  278. "socials": {
  279. "x": {
  280. "icon": "brand-x",
  281. "title": "X"
  282. },
  283. "facebook": {
  284. "icon": "brand-facebook",
  285. "title": "Facebook"
  286. },
  287. "twitter": {
  288. "icon": "brand-twitter",
  289. "title": "Twitter"
  290. },
  291. "google": {
  292. "icon": "brand-google",
  293. "title": "Google"
  294. },
  295. "youtube": {
  296. "icon": "brand-youtube",
  297. "title": "Youtube"
  298. },
  299. "vimeo": {
  300. "icon": "brand-vimeo",
  301. "title": "Vimeo"
  302. },
  303. "dribbble": {
  304. "icon": "brand-dribbble",
  305. "title": "Dribbble"
  306. },
  307. "github": {
  308. "icon": "brand-github",
  309. "title": "Github"
  310. },
  311. "instagram": {
  312. "icon": "brand-instagram",
  313. "title": "Instagram"
  314. },
  315. "pinterest": {
  316. "icon": "brand-pinterest",
  317. "title": "Pinterest"
  318. },
  319. "vk": {
  320. "icon": "brand-vk",
  321. "title": "VK"
  322. },
  323. "rss": {
  324. "icon": "rss",
  325. "title": "RSS"
  326. },
  327. "flickr": {
  328. "icon": "brand-flickr",
  329. "title": "Flickr"
  330. },
  331. "bitbucket": {
  332. "icon": "brand-bitbucket",
  333. "title": "Bitbucket"
  334. },
  335. "tabler": {
  336. "icon": "brand-tabler",
  337. "title": "Tabler"
  338. }
  339. },
  340. "months-short": [
  341. "Jan",
  342. "Feb",
  343. "Mar",
  344. "Apr",
  345. "May",
  346. "Jun",
  347. "Jul",
  348. "Aug",
  349. "Sep",
  350. "Oct",
  351. "Nov",
  352. "Dec"
  353. ],
  354. "months-long": [
  355. "January",
  356. "February",
  357. "March",
  358. "April",
  359. "May",
  360. "June",
  361. "July",
  362. "August",
  363. "September",
  364. "October",
  365. "November",
  366. "December"
  367. ]
  368. });
  369. /**
  370. * Filters
  371. */
  372. eleventyConfig.addFilter("miliseconds_to_minutes", function (value) {
  373. // Raturn 3:45 time format
  374. const minutes = Math.floor(value / 60000);
  375. const seconds = ((value % 60000) / 1000).toFixed(0);
  376. return `${minutes}:${seconds < 10 ? '0' : ''}${seconds}`;
  377. });
  378. eleventyConfig.addFilter("relative", (page) => {
  379. const segments = (page.url || '').replace(/^\//).split('/');
  380. if (segments.length === 1) {
  381. return '.';
  382. } else {
  383. return '../'.repeat(segments.length - 1).slice(0, -1);
  384. }
  385. });
  386. eleventyConfig.addFilter("concat_objects", function (object, object2) {
  387. if (
  388. object &&
  389. object2 &&
  390. typeof object === 'object' &&
  391. typeof object2 === 'object' &&
  392. !Array.isArray(object) &&
  393. !Array.isArray(object2)
  394. ) {
  395. return { ...object, ...object2 };
  396. }
  397. return object;
  398. });
  399. eleventyConfig.addFilter("replace_regex", function (input, regStr, replStr) {
  400. const regex = new RegExp(regStr, 'gm');
  401. return input.replace(regex, replStr);
  402. });
  403. eleventyConfig.addFilter("timestamp_to_date", function (timestamp) {
  404. const date = new Date(timestamp * 1000); // Convert timestamp to milliseconds
  405. return date.toISOString().split('T')[0]; // Extract the date in 'YYYY-MM-DD' format
  406. });
  407. eleventyConfig.addFilter("split_to_n", function (arr, n) {
  408. const chunkSize = Math.round(arr.length / n);
  409. const result = [];
  410. for (let i = 0; i < arr.length; i += chunkSize) {
  411. result.push(arr.slice(i, i + chunkSize));
  412. }
  413. return result;
  414. })
  415. eleventyConfig.addFilter("format_number", function (value) {
  416. return value.toString()
  417. .split('')
  418. .reverse()
  419. .reduce((acc, char, index) => {
  420. if (index > 0 && index % 3 === 0) {
  421. acc.push(',');
  422. }
  423. acc.push(char);
  424. return acc;
  425. }, [])
  426. .reverse()
  427. .join('');
  428. });
  429. function randomNumber(x, min = 0, max = 100, round = 0) {
  430. let value = ((x * x * Math.PI * Math.E * (max + 1) * (Math.sin(x) / Math.cos(x * x))) % (max + 1 - min)) + min;
  431. value = value > max ? max : value;
  432. value = value < min ? min : value;
  433. if (round !== 0) {
  434. value = parseFloat(value.toFixed(round));
  435. } else {
  436. value = Math.floor(value);
  437. }
  438. return value;
  439. }
  440. eleventyConfig.addFilter("random_date_ago", function (x, daysAgo = 100) {
  441. const today = new Date();
  442. const randomDaysAgo = randomNumber(x, 0, daysAgo);
  443. today.setDate(today.getDate() - randomDaysAgo);
  444. return today;
  445. });
  446. eleventyConfig.addFilter("random_date", function (x, startDate = null, endDate = null) {
  447. const start = startDate ? new Date(startDate).getTime() : Date.now() - 100 * 24 * 60 * 60 * 1000;
  448. const end = endDate ? new Date(endDate).getTime() : Date.now();
  449. const randomTimestamp = randomNumber(x, start, end);
  450. return new Date(randomTimestamp);
  451. });
  452. eleventyConfig.addFilter("random_item", function (x, items) {
  453. const index = randomNumber(x, 0, items.length - 1);
  454. return items[index];
  455. });
  456. eleventyConfig.addFilter("random_number", randomNumber);
  457. eleventyConfig.addFilter("first_letters", function capitalizeFirstLetter(string) {
  458. return string.split(' ').map(word => word.charAt(0)).join('');
  459. })
  460. eleventyConfig.addFilter("size", function (elem) {
  461. if (elem instanceof Object) {
  462. return Object.keys(elem).length;
  463. }
  464. return elem.length;
  465. })
  466. eleventyConfig.addFilter("first", function (elem) {
  467. if (elem instanceof Object) {
  468. return elem[Object.keys(elem)[0]];
  469. }
  470. return elem[0];
  471. })
  472. // time ago from today
  473. eleventyConfig.addFilter("timeago", function (date) {
  474. const seconds = Math.floor((new Date() - date) / 1000);
  475. let interval = Math.floor(seconds / 31536000);
  476. if (interval > 1) {
  477. return interval + " years ago";
  478. }
  479. interval = Math.floor(seconds / 2592000);
  480. if (interval > 1) {
  481. return interval + " months ago";
  482. }
  483. interval = Math.floor(seconds / 86400);
  484. if (interval > 1) {
  485. return interval + " days ago";
  486. }
  487. interval = Math.floor(seconds / 3600);
  488. if (interval > 1) {
  489. return interval + " hours ago";
  490. }
  491. interval = Math.floor(seconds / 60);
  492. if (interval > 1) {
  493. return interval + " minutes ago";
  494. }
  495. if (seconds > 0) {
  496. return Math.floor(seconds) + " seconds ago";
  497. }
  498. return "now";
  499. })
  500. /**
  501. * Shortcodes
  502. */
  503. const tags = ["capture_global", "endcapture_global", "highlight", "endhighlight"];
  504. tags.forEach(tag => {
  505. eleventyConfig.addLiquidTag(tag, function (liquidEngine) {
  506. return {
  507. parse: function (tagToken, remainingTokens) {
  508. this.str = tagToken.args;
  509. },
  510. render: function (scope, hash) {
  511. return "";
  512. },
  513. };
  514. });
  515. });
  516. /**
  517. * Transforms
  518. */
  519. function prettifyHTML(content, outputPath) {
  520. return outputPath.endsWith('.html')
  521. ? content
  522. .replace(/\/\/ @formatter:(on|off)\n+/gm, '')
  523. // remove empty lines
  524. .replace(/^\s*[\r\n]/gm, '')
  525. : content
  526. }
  527. eleventyConfig.addTransform('htmlformat', prettifyHTML)
  528. };