5htp 0.0.2

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 (35) hide show
  1. package/package.json +94 -0
  2. package/src/commands/build.ts +32 -0
  3. package/src/commands/deploy/app.ts +29 -0
  4. package/src/commands/deploy/web.ts +62 -0
  5. package/src/commands/dev.ts +100 -0
  6. package/src/compiler/client/identite.ts +70 -0
  7. package/src/compiler/client/index.ts +335 -0
  8. package/src/compiler/common/babel/index.ts +261 -0
  9. package/src/compiler/common/babel/plugins/form.ts +191 -0
  10. package/src/compiler/common/babel/plugins/icones-svg.ts +350 -0
  11. package/src/compiler/common/babel/plugins/importations.ts +337 -0
  12. package/src/compiler/common/babel/plugins/injection-dependances/index.ts +223 -0
  13. package/src/compiler/common/babel/plugins/injection-dependances/remplacerFonction.ts +226 -0
  14. package/src/compiler/common/babel/plugins/models.ts +241 -0
  15. package/src/compiler/common/babel/plugins/pages.ts +185 -0
  16. package/src/compiler/common/babel/plugins/queries/index.ts +166 -0
  17. package/src/compiler/common/files/autres.ts +37 -0
  18. package/src/compiler/common/files/images.ts +19 -0
  19. package/src/compiler/common/files/style.ts +64 -0
  20. package/src/compiler/common/index.ts +148 -0
  21. package/src/compiler/common/plugins/indexage/_utils/Stringify.ts +72 -0
  22. package/src/compiler/common/plugins/indexage/_utils/annotations.ts +88 -0
  23. package/src/compiler/common/plugins/indexage/_utils/iterateur.ts +52 -0
  24. package/src/compiler/common/plugins/indexage/icones-svg/index.ts +198 -0
  25. package/src/compiler/common/plugins/indexage/index.ts +132 -0
  26. package/src/compiler/common/plugins/indexage/indexeur.ts +13 -0
  27. package/src/compiler/common/plugins/indexage/injection-dependances/index.ts +68 -0
  28. package/src/compiler/index.ts +86 -0
  29. package/src/compiler/server/index.ts +177 -0
  30. package/src/index.ts +192 -0
  31. package/src/paths.ts +158 -0
  32. package/src/print.ts +12 -0
  33. package/src/utils/index.ts +22 -0
  34. package/src/utils/keyboard.ts +78 -0
  35. package/tsconfig.json +38 -0
@@ -0,0 +1,191 @@
1
+ /*----------------------------------
2
+ - DEPENDANCES
3
+ ----------------------------------*/
4
+
5
+ import { PluginObj } from '@babel/core';
6
+
7
+ import * as types from '@babel/types'
8
+ import generate from '@babel/generator';
9
+
10
+ /*----------------------------------
11
+ - WEBPACK RULE
12
+ ----------------------------------*/
13
+ module.exports = {
14
+ test: "**/client/**/*.tsx",
15
+ plugins: [
16
+ [Plugin]
17
+ ]
18
+ }
19
+
20
+ const debug = false
21
+
22
+ /*----------------------------------
23
+ - PLUGIN
24
+ ----------------------------------*/
25
+ function Plugin (babel) {
26
+
27
+ const t = babel.types as typeof types;
28
+
29
+ const plugin: PluginObj<{
30
+ fichier: string,
31
+ cancel: boolean
32
+ }> = {
33
+ pre(state) {
34
+
35
+ this.fichier = state.opts.filename as string;
36
+
37
+ if (!('useForm' in state.scope.bindings))
38
+ this.cancel = true;
39
+
40
+ },
41
+ visitor: {
42
+ JSXElement(instruction) {
43
+
44
+ if (this.cancel === true)
45
+ return;
46
+
47
+ const balise = instruction.node.openingElement;
48
+
49
+ /*
50
+ <Champs.metas.titre className="full" attrsChamp={{ className: "h1" }} />
51
+ */
52
+
53
+ if (!(
54
+ balise.selfClosing === true
55
+ &&
56
+ balise.name.type === 'JSXMemberExpression'
57
+ &&
58
+ balise.name.property.type === 'JSXIdentifier'
59
+ ))
60
+ return;
61
+
62
+ debug && console.log(`[compilation][babel][form] Original: `, generate(instruction.node).code);
63
+
64
+ // Si le premier element du memberexpression est Champ
65
+ let nomA: types.JSXMemberExpression | types.JSXIdentifier = balise.name;
66
+ while (nomA.type === 'JSXMemberExpression')
67
+ nomA = nomA.object;
68
+ if (!nomA.name.startsWith('Champs'))
69
+ return;
70
+
71
+ // Ne pas parcourir les élements enfant
72
+ // Avec .stop, babel arrête d'itérer les élements voisins à partir du 6ème - 7ème
73
+ //instruction.stop();
74
+ instruction.skip();
75
+
76
+ // Transformation de la lste des attributs en un objet
77
+ /*
78
+ className="full" attrsChamp={{ className: "h1" }}
79
+
80
+ =>
81
+
82
+ { className: "full", attrsChamp: { className: "h1" } }
83
+ */
84
+ let objAttributs: types.ObjectProperty[] = [];
85
+ for (const attribut of balise.attributes)
86
+ if (
87
+ attribut.type === 'JSXAttribute' &&
88
+ attribut.value !== undefined &&
89
+ typeof attribut.name.name === "string"
90
+ ) {
91
+
92
+ let propValue: types.ObjectProperty["value"];
93
+ if (attribut.value === null) // <Champ.titre autoFocus />
94
+ propValue = t.booleanLiteral(true);
95
+ else if (attribut.value.type !== 'JSXExpressionContainer')
96
+ propValue = attribut.value;
97
+ else if (attribut.value.expression.type !== 'JSXEmptyExpression')
98
+ propValue = attribut.value.expression;
99
+ else
100
+ propValue = t.nullLiteral();
101
+
102
+ objAttributs.push(
103
+ t.objectProperty(
104
+ t.identifier( attribut.name.name ),
105
+ propValue
106
+ )
107
+ )
108
+ }
109
+
110
+ // Traverse chaque branche du chemin du champ, dans l'ordre inverse
111
+ // NOTE: on aurai pu reconstituer le chemin et créer les memberexpressions en une seule itération
112
+ // Mais le fait d ele faire en deux itérations rend le code plus claire et maintenable
113
+ let cheminComposant: string[] = []
114
+ let brancheA: types.JSXMemberExpression | types.JSXIdentifier = balise.name;
115
+ while (brancheA.type === 'JSXMemberExpression') {
116
+
117
+ const { property } = brancheA;
118
+
119
+ cheminComposant.unshift(property.name)
120
+ brancheA = brancheA.object;
121
+ }
122
+
123
+ let cheminSchema: types.MemberExpression | types.OptionalMemberExpression = t.memberExpression(
124
+ t.identifier('Champs'),
125
+ t.identifier('schema')
126
+ );
127
+ let cheminDonnees: types.MemberExpression | types.OptionalMemberExpression = t.memberExpression(
128
+ t.identifier('Champs'),
129
+ t.identifier('data')
130
+ );
131
+ const iDerniereBranche = cheminComposant.length - 1
132
+ for (let iBranche = iDerniereBranche; iBranche >= 0; iBranche--) {
133
+
134
+ const branche = cheminComposant[ iBranche ];
135
+
136
+ cheminSchema = t.optionalMemberExpression(
137
+ cheminSchema,
138
+ t.identifier( branche ),
139
+ undefined,
140
+ true
141
+ )
142
+
143
+ if (iBranche !== iDerniereBranche)
144
+ cheminDonnees = t.optionalMemberExpression(
145
+ cheminDonnees,
146
+ t.identifier(branche),
147
+ undefined,
148
+ true
149
+ )
150
+
151
+ }
152
+
153
+ // Remplacement
154
+ /*
155
+ {Champs._render( Champs.metas?.titre, Champs._data.metas?.titre, 'metas.titre', {
156
+ className: "full",
157
+ attrsChamp: { className: "h1" }
158
+ })}
159
+ */
160
+ const remplacement = t.callExpression(
161
+
162
+ // Champs.render
163
+ t.memberExpression(
164
+ t.identifier('Champs'),
165
+ t.identifier('render')
166
+ ),
167
+ [
168
+ // Champs.<chemin>
169
+ cheminSchema,
170
+
171
+ // Champs._data.<chemin>
172
+ cheminDonnees,
173
+
174
+ // Chemin
175
+ t.stringLiteral( cheminComposant.join('.') ),
176
+
177
+ // { <attrs> }
178
+ t.objectExpression(objAttributs)
179
+ ]
180
+ )
181
+
182
+ debug && console.log(`[compilation][babel][form] Remplacement: `, generate(remplacement).code );
183
+
184
+ instruction.replaceWith(remplacement);
185
+
186
+ }
187
+ },
188
+ };
189
+
190
+ return plugin;
191
+ }
@@ -0,0 +1,350 @@
1
+ /*----------------------------------
2
+ - DEPENDANCES
3
+ ----------------------------------*/
4
+
5
+ // Npm
6
+ import * as types from '@babel/types'
7
+
8
+ import { PluginObj } from '@babel/core';
9
+
10
+ export type TIndexIcones = { [chemin: string]: { id: string, nom: string, fichier: string } };
11
+
12
+ /*----------------------------------
13
+ - WEBPACK RULE
14
+ ----------------------------------*/
15
+ module.exports = {
16
+ test: /\.(tsx|jsx|ts)$/, // <i src="icon" /> et /* @icon */"icon"
17
+ plugins: [
18
+ [Plugin]
19
+ ]
20
+ }
21
+
22
+ const debug = false;
23
+
24
+ const defaultIconsPack = 'regular';
25
+
26
+ /*----------------------------------
27
+ - PLUGIN
28
+ ----------------------------------*/
29
+ const ids: string[] = []
30
+ function Plugin (babel) {
31
+
32
+ const t = babel.types as typeof types;
33
+
34
+ const plugin: PluginObj<{
35
+ referencerIcone: (nomBrut: string) => string | null,
36
+ fichier: string,
37
+ traiter: boolean,
38
+ iconeTrouvee: boolean,
39
+ icones: TIndexIcones
40
+ }> = {
41
+ pre(state) {
42
+
43
+ this.fichier = state.opts.filename as string;
44
+
45
+ //console.log('SVG', fichier);
46
+
47
+ this.traiter = true;
48
+ this.iconeTrouvee = false;
49
+
50
+ this.icones = {}; // chemin => { id, nom }
51
+
52
+ this.referencerIcone = (nomBrut: string) => {
53
+
54
+ // Décomposition & dossier par défaut
55
+ let [dossierIcone, nomIcone] = nomBrut.split('/');
56
+ if (nomIcone === undefined) {
57
+ nomIcone = dossierIcone;
58
+ dossierIcone = defaultIconsPack;
59
+ }
60
+
61
+ // Extraction des infos
62
+ const cheminIconeBrut = dossierIcone + '/' + nomIcone;
63
+ const cheminIcone = cheminIconeBrut + '.svg';
64
+
65
+ // Référencement si pas déjà fait
66
+ if (this.icones[ cheminIconeBrut ] === undefined) {
67
+
68
+ const id = nomBrut.replace(/\//g, '-');
69
+
70
+ this.icones[ cheminIconeBrut ] = {
71
+ //id: dossierIcone.substring(0, 1) + '-' + nomIcone,
72
+ id: id,
73
+ nom: nomBrut,
74
+ fichier: cheminIcone
75
+ };
76
+
77
+ }
78
+
79
+ this.iconeTrouvee = true;
80
+
81
+ debug && console.log(`[icons]`, nomBrut, '=>', this.icones[cheminIconeBrut].id);
82
+
83
+ ids.push(this.icones[cheminIconeBrut].id);
84
+
85
+ return this.icones[ cheminIconeBrut ].id;
86
+ }
87
+
88
+ },
89
+ visitor: {
90
+ Program: {
91
+
92
+ enter(path) {
93
+
94
+ if (!this.traiter)
95
+ return;
96
+
97
+ },
98
+ },
99
+
100
+ StringLiteral(path) {
101
+
102
+ // Marquage d'une référence à une icon via un /* @icon */"<nom>"
103
+ if (
104
+ path.node.leadingComments
105
+ &&
106
+ path.node.leadingComments.length !== 0
107
+ &&
108
+ path.node.leadingComments[0].value === ' @icon '
109
+ ) {
110
+
111
+ // Remplacement par id
112
+ const idIcone = this.referencerIcone(path.node.value);
113
+ if (idIcone === null)
114
+ return;
115
+
116
+ path.replaceWith(
117
+ t.stringLiteral(idIcone)
118
+ );
119
+
120
+ path.skip();
121
+
122
+ }
123
+ },
124
+
125
+ // { icon: "solid/<nom>" }
126
+ Property(path) {
127
+ if (
128
+ path.node.key.type === 'Identifier'
129
+ &&
130
+ path.node.key.name === 'icon'
131
+ &&
132
+ path.node.value?.type === 'StringLiteral'
133
+ ) {
134
+
135
+ // Remplacement par id
136
+ const idIcone = this.referencerIcone(path.node.value.value);
137
+ if (idIcone === null)
138
+ return;
139
+
140
+ path.replaceWith(
141
+ t.objectProperty(
142
+ t.identifier('icon'),
143
+ t.stringLiteral( idIcone )
144
+ )
145
+ );
146
+
147
+ path.skip();
148
+
149
+ }
150
+ },
151
+
152
+ JSXAttribute(path) {
153
+
154
+ // icon="solid/<nom>"
155
+ if (
156
+ path.node.name.type === 'JSXIdentifier'
157
+ &&
158
+ path.node.name.name.startsWith("icon")
159
+ &&
160
+ path.node.value
161
+ ) {
162
+
163
+ const nomAttr = path.node.name.name;
164
+ const valAttr = path.node.value;
165
+ let remplacement;
166
+
167
+ // icon="solid/<nom>"
168
+ if (valAttr.type === 'StringLiteral') {
169
+
170
+ const idIcone = this.referencerIcone(valAttr.value);
171
+ if (idIcone === null)
172
+ return;
173
+
174
+ remplacement = t.stringLiteral(idIcone)
175
+
176
+ // icon={condition ? "solid/<nom>" : "solid/<nom>"}
177
+ } else if (
178
+ valAttr.type === 'JSXExpressionContainer'
179
+ &&
180
+ valAttr.expression.type === 'ConditionalExpression'
181
+ &&
182
+ valAttr.expression.consequent.type === 'StringLiteral'
183
+ &&
184
+ valAttr.expression.alternate.type === 'StringLiteral'
185
+ ) {
186
+
187
+ const idIcone1 = this.referencerIcone(valAttr.expression.consequent.value);
188
+ const idIcone2 = this.referencerIcone(valAttr.expression.alternate.value);
189
+
190
+ remplacement = t.jsxExpressionContainer(
191
+ t.conditionalExpression(
192
+ valAttr.expression.test,
193
+ idIcone1 ? t.stringLiteral(idIcone1) : valAttr.expression.consequent,
194
+ idIcone2 ? t.stringLiteral(idIcone2) : valAttr.expression.alternate,
195
+
196
+ )
197
+ )
198
+
199
+ } else
200
+ return;
201
+
202
+ path.replaceWith(
203
+ t.jsxAttribute(
204
+ t.jsxIdentifier( nomAttr ),
205
+ remplacement
206
+ )
207
+ );
208
+
209
+ path.skip();
210
+
211
+ }
212
+ },
213
+
214
+ JSXElement(path) {
215
+
216
+ // <i />
217
+ if (
218
+ this.traiter
219
+ &&
220
+ path.node
221
+ &&
222
+ path.node.openingElement
223
+ &&
224
+ path.node.openingElement.name.type === 'JSXIdentifier'
225
+ &&
226
+ path.node.openingElement.name.name === 'i'
227
+ ) {
228
+
229
+ // Extraction des attributs src et class
230
+ const attrs: {[prop: string]: types.JSXAttribute["value"]} = {}
231
+ let nouveauxAttributs = path.node.openingElement.attributes.filter((attribut) => {
232
+
233
+ if (attribut.type === 'JSXAttribute' && attribut.name) {
234
+
235
+ if (attribut.name.name === 'src') {
236
+ attrs.src = attribut.value
237
+ return false;
238
+ } else if (attribut.name.name === 'class') {
239
+ attrs.class = attribut.value
240
+ return false;
241
+ }
242
+ }
243
+ return true;
244
+ });
245
+
246
+ if (!attrs.src)
247
+ return;
248
+
249
+ // <i src="..." />
250
+ let classeIcone: types.StringLiteral | types.BinaryExpression | undefined = undefined;
251
+
252
+ // Chaine: On référence le nom de l'icon
253
+ if (attrs.src.type === 'StringLiteral') {
254
+
255
+ // <i src="spin" /> => <i class="svg-xxxxx spin" />
256
+ let valSrc = attrs.src.value
257
+ if (valSrc === 'spin') {
258
+
259
+ const idIcone = this.referencerIcone('solid/spinner-third');
260
+ if (idIcone === null)
261
+ return;
262
+
263
+ classeIcone = t.stringLiteral('svg-' + idIcone + ' spin');
264
+
265
+ // <i src="regular/user" /> => <i class="svg-xxxxxx" />
266
+ } else {
267
+
268
+ const idIcone = this.referencerIcone(valSrc);
269
+ if (idIcone === null)
270
+ return;
271
+
272
+ classeIcone = t.stringLiteral('svg-' + idIcone);
273
+ }
274
+
275
+ // Autre: on renomme src en class et contatène le préfixe "svg-"
276
+ // <i src={icon} /> => <i class={"svg-" + icon} />
277
+ } else if (attrs.src.type === 'JSXExpressionContainer' && attrs.src.expression.type !== 'JSXEmptyExpression') {
278
+
279
+ classeIcone = t.binaryExpression(
280
+ '+',
281
+ t.stringLiteral('svg-'),
282
+ attrs.src.expression
283
+ );
284
+
285
+ } else
286
+ throw new Error(`Type de valeur non-géré pour l'attribut src: ${attrs.src.type}`);
287
+
288
+ const origClass = attrs.class?.type !== 'JSXExpressionContainer'
289
+ ? attrs.class
290
+ : attrs.class.expression.type !== 'JSXEmptyExpression'
291
+ ? attrs.class.expression
292
+ : null
293
+
294
+ path.replaceWith(
295
+
296
+ // Balise <i>
297
+ t.jsxElement(
298
+ t.jsxOpeningElement(
299
+ t.jsxIdentifier('i'),
300
+
301
+ // Attributs
302
+ [
303
+ ...nouveauxAttributs,
304
+ t.jsxAttribute(
305
+ t.jsxIdentifier("class"),
306
+
307
+ // Attribut class
308
+ // concatSrc doit toujours être en premier dans les binary expressions
309
+ // afin que le sélecteur CSS i[class^="svg-"] soit toujours valable
310
+ t.jsxExpressionContainer(
311
+ origClass // Concaténation si attribut déjà défini
312
+ ? t.binaryExpression(
313
+ '+',
314
+ classeIcone,
315
+
316
+ t.binaryExpression(
317
+ '+',
318
+ t.stringLiteral(' '),
319
+ origClass
320
+ )
321
+ )
322
+ : classeIcone
323
+ )
324
+ )
325
+ ]
326
+ ),
327
+ t.jsxClosingElement(
328
+ t.jsxIdentifier('i')
329
+ ),
330
+ path.node.children,
331
+ path.node.selfClosing
332
+ )
333
+ );
334
+ }
335
+ }
336
+ },
337
+ post(state) {
338
+
339
+ if (!this.traiter || !this.iconeTrouvee)
340
+ return;
341
+
342
+ //console.log('@@@@@@ TEST ICONE', this.icones['/home/gaetan/www/Professionnel/Node/framework/kernel/client/assets/img/icones/fa/free/brands/youtube.svg']);
343
+
344
+ state.metadata['icones-svg'] = this.icones;
345
+
346
+ }
347
+ };
348
+
349
+ return plugin;
350
+ }