proteum 1.0.0-1

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.
Files changed (156) hide show
  1. package/.dockerignore +10 -0
  2. package/Rte.zip +0 -0
  3. package/cli/app/config.ts +54 -0
  4. package/cli/app/index.ts +195 -0
  5. package/cli/bin.js +11 -0
  6. package/cli/commands/build.ts +34 -0
  7. package/cli/commands/deploy/app.ts +29 -0
  8. package/cli/commands/deploy/web.ts +60 -0
  9. package/cli/commands/dev.ts +109 -0
  10. package/cli/commands/init.ts +85 -0
  11. package/cli/compiler/client/identite.ts +72 -0
  12. package/cli/compiler/client/index.ts +334 -0
  13. package/cli/compiler/common/babel/index.ts +170 -0
  14. package/cli/compiler/common/babel/plugins/index.ts +0 -0
  15. package/cli/compiler/common/babel/plugins/services.ts +579 -0
  16. package/cli/compiler/common/babel/routes/imports.ts +127 -0
  17. package/cli/compiler/common/babel/routes/routes.ts +1130 -0
  18. package/cli/compiler/common/files/autres.ts +39 -0
  19. package/cli/compiler/common/files/images.ts +35 -0
  20. package/cli/compiler/common/files/style.ts +78 -0
  21. package/cli/compiler/common/index.ts +154 -0
  22. package/cli/compiler/index.ts +532 -0
  23. package/cli/compiler/server/index.ts +211 -0
  24. package/cli/index.ts +189 -0
  25. package/cli/paths.ts +165 -0
  26. package/cli/print.ts +12 -0
  27. package/cli/tsconfig.json +38 -0
  28. package/cli/utils/index.ts +22 -0
  29. package/cli/utils/keyboard.ts +78 -0
  30. package/client/app/component.tsx +54 -0
  31. package/client/app/index.ts +142 -0
  32. package/client/app/service.ts +34 -0
  33. package/client/app.tsconfig.json +28 -0
  34. package/client/components/Button.tsx +298 -0
  35. package/client/components/Dialog/Manager.tsx +309 -0
  36. package/client/components/Dialog/card.tsx +208 -0
  37. package/client/components/Dialog/index.less +151 -0
  38. package/client/components/Dialog/status.less +176 -0
  39. package/client/components/Dialog/status.tsx +48 -0
  40. package/client/components/index.ts +2 -0
  41. package/client/components/types.d.ts +3 -0
  42. package/client/data/input.ts +32 -0
  43. package/client/global.d.ts +5 -0
  44. package/client/hooks.ts +22 -0
  45. package/client/index.ts +6 -0
  46. package/client/pages/_layout/index.less +6 -0
  47. package/client/pages/_layout/index.tsx +43 -0
  48. package/client/pages/bug.tsx.old +60 -0
  49. package/client/pages/useHeader.tsx +50 -0
  50. package/client/services/captcha/index.ts +67 -0
  51. package/client/services/router/components/Link.tsx +46 -0
  52. package/client/services/router/components/Page.tsx +55 -0
  53. package/client/services/router/components/router.tsx +218 -0
  54. package/client/services/router/index.tsx +521 -0
  55. package/client/services/router/request/api.ts +267 -0
  56. package/client/services/router/request/history.ts +5 -0
  57. package/client/services/router/request/index.ts +53 -0
  58. package/client/services/router/request/multipart.ts +147 -0
  59. package/client/services/router/response/index.tsx +128 -0
  60. package/client/services/router/response/page.ts +86 -0
  61. package/client/services/socket/index.ts +147 -0
  62. package/client/utils/dom.ts +77 -0
  63. package/common/app/index.ts +9 -0
  64. package/common/data/chaines/index.ts +54 -0
  65. package/common/data/dates.ts +179 -0
  66. package/common/data/markdown.ts +73 -0
  67. package/common/data/rte/nodes.ts +83 -0
  68. package/common/data/stats.ts +90 -0
  69. package/common/errors/index.tsx +326 -0
  70. package/common/router/index.ts +213 -0
  71. package/common/router/layouts.ts +93 -0
  72. package/common/router/register.ts +55 -0
  73. package/common/router/request/api.ts +77 -0
  74. package/common/router/request/index.ts +35 -0
  75. package/common/router/response/index.ts +45 -0
  76. package/common/router/response/page.ts +128 -0
  77. package/common/utils/rte.ts +183 -0
  78. package/common/utils.ts +7 -0
  79. package/doc/TODO.md +71 -0
  80. package/doc/front/router.md +27 -0
  81. package/doc/workspace/workspace.png +0 -0
  82. package/doc/workspace/workspace2.png +0 -0
  83. package/doc/workspace/workspace_26.01.22.png +0 -0
  84. package/package.json +171 -0
  85. package/server/app/commands.ts +141 -0
  86. package/server/app/container/config.ts +203 -0
  87. package/server/app/container/console/index.ts +550 -0
  88. package/server/app/container/index.ts +137 -0
  89. package/server/app/index.ts +273 -0
  90. package/server/app/service/container.ts +88 -0
  91. package/server/app/service/index.ts +235 -0
  92. package/server/app.tsconfig.json +28 -0
  93. package/server/context.ts +4 -0
  94. package/server/index.ts +4 -0
  95. package/server/services/auth/index.ts +250 -0
  96. package/server/services/auth/old.ts +277 -0
  97. package/server/services/auth/router/index.ts +95 -0
  98. package/server/services/auth/router/request.ts +54 -0
  99. package/server/services/auth/router/service.json +6 -0
  100. package/server/services/auth/service.json +6 -0
  101. package/server/services/cache/commands.ts +41 -0
  102. package/server/services/cache/index.ts +297 -0
  103. package/server/services/cache/service.json +6 -0
  104. package/server/services/cron/CronTask.ts +86 -0
  105. package/server/services/cron/index.ts +112 -0
  106. package/server/services/cron/service.json +6 -0
  107. package/server/services/disks/driver.ts +103 -0
  108. package/server/services/disks/drivers/local/index.ts +188 -0
  109. package/server/services/disks/drivers/local/service.json +6 -0
  110. package/server/services/disks/drivers/s3/index.ts +301 -0
  111. package/server/services/disks/drivers/s3/service.json +6 -0
  112. package/server/services/disks/index.ts +90 -0
  113. package/server/services/disks/service.json +6 -0
  114. package/server/services/email/index.ts +188 -0
  115. package/server/services/email/utils.ts +53 -0
  116. package/server/services/fetch/index.ts +201 -0
  117. package/server/services/fetch/service.json +7 -0
  118. package/server/services/models.7z +0 -0
  119. package/server/services/prisma/Facet.ts +142 -0
  120. package/server/services/prisma/index.ts +201 -0
  121. package/server/services/prisma/service.json +6 -0
  122. package/server/services/router/http/index.ts +217 -0
  123. package/server/services/router/http/multipart.ts +102 -0
  124. package/server/services/router/http/session.ts.old +40 -0
  125. package/server/services/router/index.ts +801 -0
  126. package/server/services/router/request/api.ts +87 -0
  127. package/server/services/router/request/index.ts +184 -0
  128. package/server/services/router/request/service.ts +21 -0
  129. package/server/services/router/request/validation/zod.ts +180 -0
  130. package/server/services/router/response/index.ts +338 -0
  131. package/server/services/router/response/mask/Filter.ts +323 -0
  132. package/server/services/router/response/mask/index.ts +60 -0
  133. package/server/services/router/response/mask/selecteurs.ts +92 -0
  134. package/server/services/router/response/page/document.tsx +160 -0
  135. package/server/services/router/response/page/index.tsx +196 -0
  136. package/server/services/router/service.json +6 -0
  137. package/server/services/router/service.ts +36 -0
  138. package/server/services/schema/index.ts +44 -0
  139. package/server/services/schema/request.ts +49 -0
  140. package/server/services/schema/router/index.ts +28 -0
  141. package/server/services/schema/router/service.json +6 -0
  142. package/server/services/schema/service.json +6 -0
  143. package/server/services/security/encrypt/aes/index.ts +85 -0
  144. package/server/services/security/encrypt/aes/service.json +6 -0
  145. package/server/services/socket/index.ts +162 -0
  146. package/server/services/socket/scope.ts +226 -0
  147. package/server/services/socket/service.json +6 -0
  148. package/server/services_old/SocketClient.ts +92 -0
  149. package/server/services_old/Token.old.ts +97 -0
  150. package/server/utils/slug.ts +79 -0
  151. package/tsconfig.common.json +45 -0
  152. package/tsconfig.json +3 -0
  153. package/types/aliases.d.ts +54 -0
  154. package/types/global/modules.d.ts +49 -0
  155. package/types/global/utils.d.ts +103 -0
  156. package/types/icons.d.ts +1 -0
@@ -0,0 +1,147 @@
1
+ /*----------------------------------
2
+ - DEPENDANCES
3
+ ----------------------------------*/
4
+
5
+ import type { ClientContext } from '../../context';
6
+
7
+ import type { TDialogControls } from '@client/components/Dialog/Manager';
8
+
9
+ /*----------------------------------
10
+ - TYPE
11
+ ----------------------------------*/
12
+
13
+ type TEventsList = {[name: string]: TEventCallback[]};
14
+
15
+ type TEventCallback = (data: any) => void
16
+
17
+ let netwokrStatusToast: TDialogControls;
18
+
19
+ /*----------------------------------
20
+ - SERVICE
21
+ ----------------------------------*/
22
+ class SocketScope {
23
+
24
+ public ws?: WebSocket;
25
+ public events: TEventsList = {}
26
+
27
+ public constructor(
28
+ public path: string,
29
+ public context: ClientContext,
30
+ events: {[name: string]: TEventCallback} = {}
31
+ ) {
32
+ this.connect();
33
+
34
+ for (const event in events)
35
+ this.events[event] = [events[event]];
36
+ }
37
+
38
+ private connect() {
39
+
40
+ const protocol = window.location.protocol === 'http:' ? 'ws:' : 'wss:';
41
+ const url = protocol + '//' + this.context.request.host + this.path;
42
+
43
+ try {
44
+ this.ws = new WebSocket(url);
45
+ } catch (error) {
46
+ console.warn(`[socket] Connection failed for ${url}`, error);
47
+ return;
48
+ }
49
+
50
+ this.ws.onopen = () => {
51
+ console.log(`[socket] Connected to the live data provider:`, url);
52
+
53
+ if (netwokrStatusToast) {
54
+ netwokrStatusToast.close(true);
55
+ this.context.toast.success("Your connection has been restored", null, null, {
56
+ autohide: 3
57
+ });
58
+ }
59
+ }
60
+
61
+ this.ws.onmessage = (event: MessageEvent<any>) => {
62
+
63
+ const [name, rawData] = event.data.split('>');
64
+ if (this.events[name] === undefined) {
65
+ console.warn("Unknown command: " + name + `. Raw command:`, event.data);
66
+ return;
67
+ }
68
+
69
+ let data;
70
+ try {
71
+ data = JSON.parse(rawData);
72
+ } catch (error) {
73
+ console.warn(`[socket] Error decoding data`, rawData, error);
74
+ return;
75
+ }
76
+
77
+ for (const callback of this.events[name])
78
+ callback(data);
79
+
80
+ }
81
+
82
+ this.ws.onerror = (event) => {
83
+ console.log(`[socket] Network error for ${url}`, event);
84
+ this.close();
85
+ }
86
+
87
+ this.ws.onclose = (event) => {
88
+
89
+ // Fermeture volontaire = on ne retente pas de se connecter
90
+ if (event.wasClean) {
91
+ console.log(`[socket] Disconnected from ${url}. Reason: `, event.reason);
92
+ return;
93
+ }
94
+
95
+ if (!netwokrStatusToast)
96
+ netwokrStatusToast = this.context.toast.error("You're offline", "Please check your connection", null, {
97
+ autohide: false,
98
+ prison: true
99
+ });
100
+ console.log(`[socket] Disconnected from ${url}. Retry in 5 seconds ...`, event);
101
+ setTimeout(() => this.connect(), 5000);
102
+ }
103
+
104
+ }
105
+
106
+ public close() {
107
+ if (this.ws)
108
+ this.ws.close();
109
+ }
110
+
111
+ public on(event: string, callback: TEventCallback) {
112
+
113
+ if (this.events[event] === undefined)
114
+ this.events[event] = [callback]
115
+ else
116
+ this.events[event].push(callback)
117
+
118
+ return this;
119
+ }
120
+
121
+ public off(event: string) {
122
+
123
+ delete this.events[event];
124
+
125
+ return this;
126
+ }
127
+
128
+ }
129
+
130
+ export default class SocketClient {
131
+
132
+ public scopes: { [name: string]: SocketScope } = {}
133
+
134
+ public constructor( public context: ClientContext ) {
135
+
136
+
137
+ }
138
+
139
+ public open(path: string, commands: {[name: string]: TEventCallback} = {}) {
140
+
141
+ if (!(path in this.scopes))
142
+ this.scopes[path] = new SocketScope(path, this.context, commands);
143
+
144
+ return this.scopes[path]
145
+ }
146
+
147
+ }
@@ -0,0 +1,77 @@
1
+ import type { RefObject } from 'preact';
2
+ import { history } from '@client/services/router/request/history';
3
+
4
+ type ElementOrSelector = HTMLElement | string;
5
+ export const deepContains = (
6
+ parents: ElementOrSelector | ElementOrSelector[],
7
+ children: HTMLElement
8
+ ): boolean => {
9
+
10
+ if (!Array.isArray(parents))
11
+ parents = [parents];
12
+
13
+ let node: HTMLElement | null = children;
14
+ while (node) {
15
+ for (const parent of parents) {
16
+ //console.log('Checking if', parent, 'matches with', node);
17
+ if (
18
+ // HTML Element
19
+ node === parent
20
+ ||
21
+ // CSS Selector
22
+ (typeof parent === 'string' && node.matches && node.matches(parent))
23
+ )
24
+ return true;
25
+ }
26
+
27
+ node = node.parentNode as HTMLElement | null;
28
+ }
29
+
30
+ return false;
31
+ }
32
+
33
+ // Usage: React.useEffect( blurable([ <element>, <function> ]) );
34
+ export const blurable = (...args: [HTMLElement, Function][]) => {
35
+
36
+ if (!history)
37
+ return;
38
+
39
+ const blur = (e: MouseEvent) => {
40
+
41
+ if (e.target === null)
42
+ return;
43
+
44
+ for (const [refElement, masquer] of args) {
45
+
46
+ //console.log("refElement", refElement, e.target?.matches);
47
+
48
+ if (!deepContains([refElement], e.target))
49
+ masquer();
50
+
51
+ }
52
+ }
53
+
54
+ window.addEventListener('mousedown', blur);
55
+
56
+ const unlisten = history.listen(() => {
57
+ for (const [, masquer] of args) {
58
+
59
+ masquer();
60
+
61
+ }
62
+ })
63
+
64
+ return () => {
65
+ window.removeEventListener('mousedown', blur);
66
+ unlisten();
67
+ }
68
+ }
69
+
70
+ export const focusContent = ( container: HTMLElement ) => {
71
+
72
+ const toFocus = container.querySelector<HTMLInputElement | HTMLTextAreaElement | HTMLButtonElement>(
73
+ 'input, textarea, button.btn.primary, footer > button.btn'
74
+ ) || container; // Is it useful ? Creating unwanted scroll issue on showing popover
75
+
76
+ toFocus?.focus();
77
+ }
@@ -0,0 +1,9 @@
1
+ import type ClientApplication from '@client/app';
2
+ import type ServerApplication from '@server/app';
3
+
4
+ export type ClientOrServerApplication = ClientApplication | ServerApplication;
5
+
6
+ export type TAppArrowFunction<
7
+ TRegisteredData = void,
8
+ TApplication extends ClientOrServerApplication = ClientOrServerApplication
9
+ > = (app: TApplication) => TRegisteredData
@@ -0,0 +1,54 @@
1
+ /*----------------------------------
2
+ - TRANSFORM
3
+ ----------------------------------*/
4
+
5
+ /**
6
+ * Normalize a string into an ID
7
+ * @param name The string to normalize
8
+ * @returns A ID string
9
+ */
10
+ export const nameToID = (name: string) => name.toLowerCase().replace(/[^a-z1-9]/gi, '');
11
+
12
+ export const ucfirst = (chaine: string): string => {
13
+ return chaine.charAt(0).toUpperCase() + chaine.slice(1);
14
+ }
15
+
16
+ export const linkify = (texte: string): string => {
17
+ const regex = /((http|https)\:\/\/([a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,3}(\/\S*)?))/gi;
18
+ return texte.replace(regex, '<a href="$1" target="_blank">$3</a>');
19
+ }
20
+
21
+ export const trim = (s: string, c: string) => {
22
+ if (c === "]") c = "\\]";
23
+ if (c === "\\") c = "\\\\";
24
+ return s.replace(new RegExp(
25
+ "^[" + c + "]+|[" + c + "]+$", "g"
26
+ ), "");
27
+ }
28
+
29
+ export const trimLeft = (chaine: string, toTrim: string) => chaine.startsWith(toTrim)
30
+ ? chaine.substring(toTrim.length) : chaine;
31
+
32
+ export const trimRight = (chaine: string, toTrim: string) => chaine.endsWith(toTrim)
33
+ ? chaine.substring(0, -toTrim.length) : chaine;
34
+
35
+ export const escapeRegExp = (string: string) =>
36
+ string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
37
+
38
+ /*----------------------------------
39
+ - EXTRACT
40
+ ----------------------------------*/
41
+ export const getKeywords = (str: string, delimiter: string = ' ') => str
42
+
43
+ // Minuscule
44
+ .toLowerCase()
45
+
46
+ // condenseWhitespace ( https://github.com/sindresorhus/condense-whitespace/blob/main/index.js )
47
+ .trim().replace(/\s{2,}/gu, ' ')
48
+
49
+ // Ne garde que les caractères alĥanumériques, ainsi que .
50
+ // https://stackoverflow.com/questions/20690499/concrete-javascript-regex-for-accented-characters-diacritics
51
+ .replace(/[^\.0-9A-Za-zÀ-ÖØ-öø-ÿ]/ig, ' ')
52
+
53
+ // TODO: remove stopwords: https://github.com/fergiemcdowall/stopword
54
+ export const getSlug = (str: string) => getKeywords(str, '-')
@@ -0,0 +1,179 @@
1
+ import dayjs from 'dayjs';
2
+ /*
3
+ // Function to calculate the difference in the specified unit
4
+ function dateDiffInUnits(date1, date2) {
5
+ const msPerSecond = 1000;
6
+ const msPerMinute = msPerSecond * 60;
7
+ const msPerHour = msPerMinute * 60;
8
+ const msPerDay = msPerHour * 24;
9
+ const msPerMonth = msPerDay * 30; // Approximation
10
+ const msPerYear = msPerDay * 365; // Approximation
11
+
12
+ const diffInMs = date2 - date1;
13
+
14
+ return {
15
+ years: diffInMs / msPerYear,
16
+ months: diffInMs / msPerMonth,
17
+ days: diffInMs / msPerDay,
18
+ hours: diffInMs / msPerHour,
19
+ minutes: diffInMs / msPerMinute,
20
+ seconds: diffInMs / msPerSecond,
21
+ };
22
+ }
23
+
24
+ // Function to determine the best unit based on the differences
25
+ function chooseBestUnit(diffs) {
26
+ if (Math.abs(diffs.years) >= 1) return 'year';
27
+ if (Math.abs(diffs.months) >= 1) return 'month';
28
+ if (Math.abs(diffs.days) >= 1) return 'day';
29
+ if (Math.abs(diffs.hours) >= 1) return 'hour';
30
+ if (Math.abs(diffs.minutes) >= 1) return 'minute';
31
+ return 'second';
32
+ }
33
+
34
+ // Function to format the relative time between two dates
35
+ function formatRelativeTime(date1, date2, locale = 'en') {
36
+ const diffs = dateDiffInUnits(date1, date2);
37
+ const bestUnit = chooseBestUnit(diffs);
38
+ const diff = diffs[bestUnit];
39
+ const rtf = new Intl.RelativeTimeFormat(locale, { numeric: 'auto' });
40
+ return rtf.format(Math.round(diff), bestUnit);
41
+ }
42
+
43
+ // Example dates
44
+ const date1 = new Date('2023-07-01');
45
+ const date2 = new Date('2024-07-13');
46
+
47
+ // Format the relative time automatically choosing the best unit
48
+ console.log(formatRelativeTime(date1, date2)); // Output: "in 1 year"
49
+
50
+ */
51
+
52
+ export type TDateInfo = {
53
+ isPast: boolean,
54
+ delta: number,
55
+ text: string
56
+ }
57
+
58
+ export const timeSince = (date: Date | number | string): TDateInfo | null => {
59
+
60
+ if (date === undefined)
61
+ return null;
62
+
63
+ // Timeago ne prend que des dates et des timestamp
64
+ if (typeof date === 'string') {
65
+ date = Date.parse(date);
66
+ if (isNaN(date))
67
+ return null;
68
+ }
69
+
70
+ // Get metas
71
+ const now = Date.now()
72
+ const timestamp = date instanceof Date ? date.getTime() : date;
73
+ const deltaSeconds = Math.abs( Math.round( (now - timestamp) / 1000 ));
74
+ const isPast = now > timestamp;
75
+
76
+ return {
77
+ text: date,//timeAgo.format(date),
78
+ isPast,
79
+ delta: deltaSeconds
80
+ };
81
+ }
82
+
83
+ export const tempsRelatif = (time: number, nbChiffresInit?: number) => {
84
+
85
+ const nbChiffres = nbChiffresInit === undefined ? 2 : nbChiffresInit;
86
+
87
+ const jours = Math.floor(time / (60 * 60 * 24));
88
+
89
+ if (jours >= 1) {
90
+
91
+ return jours + (jours === 1 ? ' day' : ' days')
92
+
93
+ } else {
94
+
95
+ const heures = Math.floor((time % (60 * 60 * 24)) / (60 * 60));
96
+ const minutes = Math.floor((time % (60 * 60)) / (60));
97
+ const secondes = Math.floor(time % (60));
98
+
99
+ return [heures, minutes, secondes].filter(
100
+ (nb: number | false, i: number) => nb > 0 || 4 - i <= nbChiffres
101
+ ).map(
102
+ (nb: number) => nb < 10 ? '0' + nb : nb
103
+ ).join(':');
104
+ }
105
+ }
106
+
107
+ export const chaineDate = (chaine: string): boolean => {
108
+ // 2019-09-09T11:28:21.778Z
109
+ const regexDate = /[0-9]{4}\-[0-9]{2}\-[0-9]{2}T[0-9]{2}\:[0-9]{2}\:[0-9]{2}\.[0-9]{3}Z/;
110
+ return regexDate.test( chaine );
111
+ }
112
+
113
+
114
+
115
+
116
+
117
+ // Based on https://github.com/sebastiansandqvist/s-ago/blob/master/index.ts
118
+ type TUnit = {
119
+ max: number,
120
+ divisor?: number,
121
+ past: string,
122
+ future: string
123
+ }
124
+
125
+ const units: {[name: string]: TUnit} = {
126
+ seconds: { max: 60000, past: 'just now', future: 'now' },
127
+ minute: { max: 2760000, divisor: 60000, past: 'a minute ago', future: 'in a minute' }, // max: 46 minutes
128
+ hour: { max: 72000000, divisor: 3600000, past: 'an hour ago', future: 'in an hour' }, // max: 20 hours
129
+ day: { max: 518400000, divisor: 86400000, past: 'yesterday', future: 'tomorrow' }, // max: 6 days
130
+ week: { max: 2419200000, divisor: 604800000, past: 'last week', future: 'in a week' }, // max: 28 days
131
+ month: { max: 28512000000, divisor: 2592000000, past: 'last month', future: 'in a month' }, // max: 11 months
132
+ year: { max: Infinity, divisor: 31536000000, past: 'last year', future: 'in a year' },
133
+ };
134
+
135
+ export function ago(date: Date | string, { min, max }: { min?: string, max?: string } = {}): string {
136
+
137
+ if (!date)
138
+ return '-';
139
+
140
+ if (typeof date === 'string')
141
+ date = new Date(date);
142
+
143
+ const minUnit = min ? units[min].max : 0;
144
+ const diff = Date.now() - date.getTime();
145
+ const delta = Math.abs(diff);
146
+
147
+ let unitName!: string;
148
+ let unit!: TUnit;
149
+ for (unitName in units) {
150
+ unit = units[unitName];
151
+ if (unit.max >= minUnit && (delta < unit.max || unitName === max))
152
+ break;
153
+ }
154
+
155
+ if (unit.divisor === undefined)
156
+ return diff < 0 ? unit.future : unit.past;
157
+
158
+ var val = Math.round(delta / unit.divisor);
159
+ if (diff < 0)
160
+ return val <= 1 ? unit.future : 'in ' + val + ' ' + unitName + 's';
161
+ else
162
+ return val <= 1 ? unit.past : val + ' ' + unitName + 's ago';
163
+
164
+ };
165
+
166
+ export const daysAgo = (date: string) => {
167
+
168
+ const days = dayjs().diff(date, 'days')
169
+
170
+ if (days === 0)
171
+ return 'Today';
172
+ else if (days === 1)
173
+ return 'Yesterday';
174
+ else if (days <= 7)
175
+ return days + ' days ago'
176
+ else
177
+ return dayjs(date).format('DD/MM');
178
+
179
+ }
@@ -0,0 +1,73 @@
1
+ import markdownIt from 'markdown-it';
2
+ const md = markdownIt({
3
+ html: false, // Enable HTML tags in source
4
+ xhtmlOut: false, // Use '/' to close single tags (<br />). This is only for full CommonMark compatibility.
5
+ breaks: true, // Convert '\n' in paragraphs into <br>
6
+ langPrefix: 'language-', // CSS language prefix for fenced blocks. Can be useful for external highlighters.
7
+ linkify: false, // Autoconvert URL-like text to links
8
+ });
9
+
10
+ const rules = md.renderer.rules;
11
+
12
+ // ------------------------
13
+
14
+ var link_open_default = rules.link_open || function (tokens, idx, options, env, self) {
15
+ return self.renderToken(tokens, idx, options);
16
+ };
17
+
18
+ // Target = _blank
19
+ rules.link_open = function (tokens, idx, options, env, self) {
20
+
21
+ const aIndex = tokens[idx].attrIndex('target');
22
+ if (aIndex < 0) {
23
+ tokens[idx].attrPush(['target', '_blank']);
24
+ } else {
25
+ tokens[idx].attrs[ aIndex ][1] = '_blank';
26
+ }
27
+
28
+ return link_open_default(tokens, idx, options, env, self);
29
+ };
30
+
31
+ // ------------------------
32
+
33
+ var image_default = rules.image || function (tokens, idx, options, env, self) {
34
+ return self.renderToken(tokens, idx, options);
35
+ };
36
+
37
+ // img => figure
38
+ rules.image = function (tokens, idx, options, env, self) {
39
+
40
+ const rendu = image_default(tokens, idx, options, env, self);
41
+
42
+ return `<figure>${rendu}</figure>`
43
+ };
44
+
45
+ // ------------------------
46
+
47
+ md.block.ruler.after('list', 'test', (state, startLine, endLine, silent) => {
48
+
49
+ for (const token of state.tokens) {
50
+ if (token.type === 'bullet_list_open') {
51
+
52
+ const aIndex = token.attrIndex('class');
53
+ if (aIndex < 0) {
54
+ token.attrPush(['class', 'liste']); // add new attribute
55
+ } else {
56
+ token.attrs[ aIndex ][1] = 'liste'; // replace value of existing attr
57
+ }
58
+
59
+ } else if (token.type === 'ordered_list_open') {
60
+
61
+ const aIndex = token.attrIndex('class');
62
+ if (aIndex < 0) {
63
+ token.attrPush(['class', 'steps']); // add new attribute
64
+ } else {
65
+ token.attrs[ aIndex ][1] = 'steps'; // replace value of existing attr
66
+ }
67
+
68
+ }
69
+ }
70
+
71
+ }, { alt: ['paragraph', 'reference', 'blockquote'] })
72
+
73
+ export default md;
@@ -0,0 +1,83 @@
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ */
8
+
9
+ import type { Klass, LexicalNode } from 'lexical';
10
+
11
+ import { CodeHighlightNode, CodeNode } from '@lexical/code';
12
+ import { HashtagNode } from '@lexical/hashtag';
13
+ import { AutoLinkNode, LinkNode } from '@lexical/link';
14
+ import { ListItemNode, ListNode } from '@lexical/list';
15
+ import { MarkNode } from '@lexical/mark';
16
+ import { OverflowNode } from '@lexical/overflow';
17
+ import { HorizontalRuleNode } from '@lexical/react/LexicalHorizontalRuleNode';
18
+ import { HeadingNode, QuoteNode } from '@lexical/rich-text';
19
+ import { TableCellNode, TableNode, TableRowNode } from '@lexical/table';
20
+
21
+ import { CollapsibleContainerNode } from '@client/components/Rte/plugins/CollapsiblePlugin/CollapsibleContainerNode';
22
+ import { CollapsibleContentNode } from '@client/components/Rte/plugins/CollapsiblePlugin/CollapsibleContentNode';
23
+ import { CollapsibleTitleNode } from '@client/components/Rte/plugins/CollapsiblePlugin/CollapsibleTitleNode';
24
+ import { AutocompleteNode } from '@client/components/Rte/nodes/AutocompleteNode';
25
+ import { EmojiNode } from '@client/components/Rte/nodes/EmojiNode';
26
+ import { ImageNode } from '@client/components/Rte/nodes/ImageNode';
27
+ import { InlineImageNode } from '@client/components/Rte/nodes/InlineImageNode/InlineImageNode';
28
+ import { KeywordNode } from '@client/components/Rte/nodes/KeywordNode';
29
+ import { LayoutContainerNode } from '@client/components/Rte/nodes/LayoutContainerNode';
30
+ import { LayoutItemNode } from '@client/components/Rte/nodes/LayoutItemNode';
31
+ import { MentionNode } from '@client/components/Rte/nodes/MentionNode';
32
+ import { PageBreakNode } from '@client/components/Rte/nodes/PageBreakNode';
33
+ import { PollNode } from '@client/components/Rte/nodes/PollNode';
34
+ import { StickyNode } from '@client/components/Rte/nodes/StickyNode';
35
+ import { TweetNode } from '@client/components/Rte/nodes/TweetNode';
36
+ import { YouTubeNode } from '@client/components/Rte/nodes/YouTubeNode';
37
+
38
+ import HeadingWithAnchorNode from '@client/components/Rte/nodes/HeadingNode';
39
+ import ReferenceLinkNode from '@client/components/Rte/nodes/ReferenceLinkNode';
40
+
41
+ const PlaygroundNodes: Array<Klass<LexicalNode>> = [
42
+ /*HeadingNode, */HeadingWithAnchorNode,
43
+ {
44
+ replace: HeadingNode,
45
+ with: (node) => {
46
+ return new HeadingWithAnchorNode( node.getTag() );
47
+ }
48
+ },
49
+ ListNode,
50
+ ListItemNode,
51
+ QuoteNode,
52
+ CodeNode,
53
+ TableNode,
54
+ TableCellNode,
55
+ TableRowNode,
56
+ HashtagNode,
57
+ CodeHighlightNode,
58
+ AutoLinkNode,
59
+ LinkNode,
60
+ OverflowNode,
61
+ PollNode,
62
+ StickyNode,
63
+ ImageNode, InlineImageNode,
64
+ MentionNode,
65
+ EmojiNode,
66
+ AutocompleteNode,
67
+ KeywordNode,
68
+ HorizontalRuleNode,
69
+ TweetNode,
70
+ YouTubeNode,
71
+ MarkNode,
72
+ CollapsibleContainerNode,
73
+ CollapsibleContentNode,
74
+ CollapsibleTitleNode,
75
+ PageBreakNode,
76
+ LayoutContainerNode,
77
+ LayoutItemNode,
78
+
79
+ // Custom
80
+ ReferenceLinkNode
81
+ ];
82
+
83
+ export default PlaygroundNodes;