edgexpress 3.0.0 → 3.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 (92) hide show
  1. package/eslint.config.cjs +6 -0
  2. package/examples/index.js +41 -0
  3. package/examples/views/components/layout/main.edge +26 -0
  4. package/examples/views/components/modal.edge +27 -0
  5. package/examples/views/home.edge +84 -0
  6. package/examples/views/partials/button.edge +1 -0
  7. package/examples/views/partials/home-footer.edge +49 -0
  8. package/examples/views/partials/home-header.edge +61 -0
  9. package/examples/views/welcome.edge +22 -0
  10. package/index.d.ts +7 -0
  11. package/package.json +12 -4
  12. package/src/cache_manager.d.ts +28 -0
  13. package/src/cache_manager.js +58 -0
  14. package/src/compiler.d.ts +73 -0
  15. package/src/compiler.js +319 -0
  16. package/src/component/props.d.ts +53 -0
  17. package/src/component/props.js +110 -0
  18. package/src/edge/globals.d.ts +5 -0
  19. package/src/edge/globals.js +95 -0
  20. package/src/edge/main.d.ts +192 -0
  21. package/src/edge/main.js +334 -0
  22. package/src/edge/renderer.d.ts +44 -0
  23. package/src/edge/renderer.js +85 -0
  24. package/src/edge/stacks.d.ts +22 -0
  25. package/src/edge/stacks.js +98 -0
  26. package/src/loader.d.ts +138 -0
  27. package/src/loader.js +347 -0
  28. package/src/migrate/globals.d.ts +1 -0
  29. package/src/migrate/globals.js +100 -0
  30. package/src/migrate/plugin.d.ts +2 -0
  31. package/src/migrate/plugin.js +58 -0
  32. package/src/migrate/props.d.ts +66 -0
  33. package/src/migrate/props.js +129 -0
  34. package/src/migrate/tags/layout.d.ts +6 -0
  35. package/src/migrate/tags/layout.js +25 -0
  36. package/src/migrate/tags/main.d.ts +4 -0
  37. package/src/migrate/tags/main.js +19 -0
  38. package/src/migrate/tags/section.d.ts +6 -0
  39. package/src/migrate/tags/section.js +23 -0
  40. package/src/migrate/tags/set.d.ts +26 -0
  41. package/src/migrate/tags/set.js +104 -0
  42. package/src/migrate/tags/super.d.ts +9 -0
  43. package/src/migrate/tags/super.js +31 -0
  44. package/src/plugins/supercharged.d.ts +4 -0
  45. package/src/plugins/supercharged.js +88 -0
  46. package/src/processor.d.ts +42 -0
  47. package/src/processor.js +86 -0
  48. package/src/tags/assign.d.ts +5 -0
  49. package/src/tags/assign.js +42 -0
  50. package/src/tags/component.d.ts +6 -0
  51. package/src/tags/component.js +299 -0
  52. package/src/tags/debugger.d.ts +5 -0
  53. package/src/tags/debugger.js +26 -0
  54. package/src/tags/each.d.ts +20 -0
  55. package/src/tags/each.js +185 -0
  56. package/src/tags/else.d.ts +2 -0
  57. package/src/tags/else.js +22 -0
  58. package/src/tags/else_if.d.ts +7 -0
  59. package/src/tags/else_if.js +39 -0
  60. package/src/tags/eval.d.ts +7 -0
  61. package/src/tags/eval.js +30 -0
  62. package/src/tags/if.d.ts +5 -0
  63. package/src/tags/if.js +45 -0
  64. package/src/tags/include.d.ts +27 -0
  65. package/src/tags/include.js +78 -0
  66. package/src/tags/include_if.d.ts +10 -0
  67. package/src/tags/include_if.js +61 -0
  68. package/src/tags/inject.d.ts +6 -0
  69. package/src/tags/inject.js +40 -0
  70. package/src/tags/let.d.ts +6 -0
  71. package/src/tags/let.js +69 -0
  72. package/src/tags/main.d.ts +18 -0
  73. package/src/tags/main.js +47 -0
  74. package/src/tags/new_error.d.ts +6 -0
  75. package/src/tags/new_error.js +47 -0
  76. package/src/tags/push_once_to.d.ts +13 -0
  77. package/src/tags/push_once_to.js +65 -0
  78. package/src/tags/push_to.d.ts +7 -0
  79. package/src/tags/push_to.js +62 -0
  80. package/src/tags/slot.d.ts +6 -0
  81. package/src/tags/slot.js +29 -0
  82. package/src/tags/stack.d.ts +5 -0
  83. package/src/tags/stack.js +38 -0
  84. package/src/tags/unless.d.ts +12 -0
  85. package/src/tags/unless.js +52 -0
  86. package/src/template.d.ts +127 -0
  87. package/src/template.js +203 -0
  88. package/src/types.d.ts +144 -0
  89. package/src/types.js +10 -0
  90. package/src/utils.d.ts +96 -0
  91. package/src/utils.js +297 -0
  92. package/tsconfig.json +16 -0
package/src/types.d.ts ADDED
@@ -0,0 +1,144 @@
1
+ /**
2
+ * edge
3
+ *
4
+ * (c) EdgeJS
5
+ *
6
+ * For the full copyright and license information, please view the LICENSE
7
+ * file that was distributed with this source code.
8
+ */
9
+ import type { TagToken } from 'edge-lexer/types'
10
+ import type { Parser, EdgeBuffer } from 'edge-parser'
11
+ import type { ParserTagDefinitionContract } from 'edge-parser/types'
12
+ import type { Edge } from './edge/main.js'
13
+ import type { Template } from './template.js'
14
+ /**
15
+ * The shape in which the loader must resolve the template
16
+ */
17
+ export type LoaderTemplate = {
18
+ template: string
19
+ }
20
+ export type ComponentsTree = {
21
+ diskName: string
22
+ components: {
23
+ componentName: string
24
+ tagName: string
25
+ }[]
26
+ }[]
27
+ /**
28
+ * Loader contract that every loader must adheres to.
29
+ */
30
+ export interface LoaderContract {
31
+ /**
32
+ * List of mounted disks
33
+ */
34
+ mounted: {
35
+ [diskName: string]: string
36
+ }
37
+ /**
38
+ * List of pre-registered template
39
+ */
40
+ templates: {
41
+ [templatePath: string]: LoaderTemplate
42
+ }
43
+ /**
44
+ * Save disk name and dirPath to resolve views
45
+ */
46
+ mount(diskName: string, dirPath: string | URL): void
47
+ /**
48
+ * Remove disk from the previously saved paths
49
+ */
50
+ unmount(diskName: string): void
51
+ /**
52
+ * Resolve template contents
53
+ */
54
+ resolve(templatePath: string): LoaderTemplate
55
+ /**
56
+ * Make absolute path to a template
57
+ */
58
+ makePath(templatePath: string): string
59
+ /**
60
+ * Register in memory template and presenter
61
+ */
62
+ register(templatePath: string, contents: LoaderTemplate): void
63
+ /**
64
+ * Remove the pre-registered template
65
+ */
66
+ remove(templatePath: string): void
67
+ /**
68
+ * Returns a list of components for all the registered disks
69
+ */
70
+ listComponents(): ComponentsTree
71
+ }
72
+ /**
73
+ * The tag must have a tagName along with other properties
74
+ * required by lexer and parser
75
+ */
76
+ export interface TagContract extends ParserTagDefinitionContract {
77
+ tagName: string
78
+ boot?(template: typeof Template): void
79
+ }
80
+ /**
81
+ * Shape of collection of tags
82
+ */
83
+ export type TagsContract = {
84
+ [tagName: string]: TagContract
85
+ }
86
+ /**
87
+ * Shape of compiled template as a function
88
+ */
89
+ export type CompiledTemplate = (
90
+ template: Template,
91
+ state: Record<string, any>,
92
+ $context: Record<string, any> | undefined,
93
+ ...localVariables: any[]
94
+ ) => any
95
+ /**
96
+ * Shape of the cache manager
97
+ */
98
+ export interface CacheManagerContract {
99
+ enabled: boolean
100
+ get(templatePath: string): undefined | CompiledTemplate
101
+ set(templatePath: string, compiledOutput: CompiledTemplate): void
102
+ has(templatePath: string): boolean
103
+ delete(templatePath: string): void
104
+ }
105
+ /**
106
+ * Compiler constructor options
107
+ */
108
+ export type CompilerOptions = {
109
+ cache?: boolean
110
+ async?: boolean
111
+ compat?: boolean
112
+ }
113
+ /**
114
+ * Shape of options that can be passed to the
115
+ * edge constructor
116
+ */
117
+ export type EdgeOptions = {
118
+ loader?: LoaderContract
119
+ cache?: boolean
120
+ }
121
+ /**
122
+ * Shape of edge plugin
123
+ */
124
+ export type PluginFn<T> = (edge: Edge, firstRun: boolean, options: T) => void
125
+ /**
126
+ * Shape of global helpers
127
+ */
128
+ export type EdgeGlobals = Record<string, any>
129
+ /**
130
+ * Required when creating custom tags
131
+ */
132
+ export type ParserContract = Parser
133
+ export type TagTokenContract = TagToken
134
+ export type EdgeBufferContract = EdgeBuffer
135
+ export type * from 'edge-lexer/types'
136
+ export type {
137
+ AcornLoc,
138
+ ClaimTagFn,
139
+ MustacheTransformer,
140
+ OnLineFn,
141
+ ParserOptions,
142
+ ParserTagDefinitionContract,
143
+ TagTransformer,
144
+ } from 'edge-parser/types'
package/src/types.js ADDED
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ /**
3
+ * edge
4
+ *
5
+ * (c) EdgeJS
6
+ *
7
+ * For the full copyright and license information, please view the LICENSE
8
+ * file that was distributed with this source code.
9
+ */
10
+ Object.defineProperty(exports, "__esModule", { value: true });
package/src/utils.d.ts ADDED
@@ -0,0 +1,96 @@
1
+ import type { TagToken } from 'edge-lexer/types'
2
+ import { type expressions as expressionsList, type Parser } from 'edge-parser'
3
+ type ExpressionList = readonly (keyof typeof expressionsList | 'ObjectPattern' | 'ArrayPattern')[]
4
+ /**
5
+ * Raise an `E_UNALLOWED_EXPRESSION` exception. Filename and expression is
6
+ * required to point the error stack to the correct file
7
+ */
8
+ export declare function unallowedExpression(
9
+ message: string,
10
+ filename: string,
11
+ loc: {
12
+ line: number
13
+ col: number
14
+ }
15
+ ): void
16
+ /**
17
+ * Validates the expression type to be part of the allowed
18
+ * expressions only.
19
+ *
20
+ * The filename is required to report errors.
21
+ *
22
+ * ```js
23
+ * isNotSubsetOf(expression, ['Literal', 'Identifier'], () => {})
24
+ * ```
25
+ */
26
+ export declare function isSubsetOf(
27
+ expression: any,
28
+ expressions: ExpressionList,
29
+ errorCallback: () => void
30
+ ): void
31
+ /**
32
+ * Validates the expression type not to be part of the disallowed
33
+ * expressions.
34
+ *
35
+ * The filename is required to report errors.
36
+ *
37
+ * ```js
38
+ * isNotSubsetOf(expression, 'SequenceExpression', () => {})
39
+ * ```
40
+ */
41
+ export declare function isNotSubsetOf(
42
+ expression: any,
43
+ expressions: ExpressionList,
44
+ errorCallback: () => void
45
+ ): void
46
+ /**
47
+ * Parses the jsArg by generating and transforming its AST
48
+ */
49
+ export declare function parseJsArg(parser: Parser, token: TagToken): any
50
+ /**
51
+ * Each loop. A soft replacement for `lodash.each` that we were using earlier
52
+ */
53
+ export declare function each(collection: any, iteratee: (value: any, key: any) => void): void
54
+ /**
55
+ * Async each loop. A soft replacement for `lodash.each` that we were
56
+ * using earlier with support for async await
57
+ */
58
+ export declare function asyncEach(
59
+ collection: any,
60
+ iteratee: (value: any, key: any) => Promise<void>
61
+ ): Promise<void>
62
+ /**
63
+ * This class generates a valid object as a string, which is written to the template
64
+ * output. The reason we need a string like object, since we don't want it's
65
+ * properties to be evaluated during the object creation, instead it must
66
+ * be evaluated when the compiled output is invoked.
67
+ */
68
+ export declare class StringifiedObject {
69
+ #private
70
+ addSpread(key: string): void
71
+ /**
72
+ * Add key/value pair to the object.
73
+ *
74
+ * ```js
75
+ * stringifiedObject.add('username', `'virk'`)
76
+ * ```
77
+ */
78
+ add(key: any, value: any, isComputed?: boolean): void
79
+ /**
80
+ * Returns the object alike string back.
81
+ *
82
+ * ```js
83
+ * stringifiedObject.flush()
84
+ *
85
+ * // returns
86
+ * `{ username: 'virk' }`
87
+ * ```
88
+ */
89
+ flush(): string
90
+ }
91
+ /**
92
+ * Stringify an object to props to HTML attributes
93
+ */
94
+ export declare function stringifyAttributes(props: any, namespace?: string): string
95
+ export declare let nanoid: (length?: number) => string
96
+ export {}
package/src/utils.js ADDED
@@ -0,0 +1,297 @@
1
+ "use strict";
2
+ /*
3
+ * edge.js
4
+ *
5
+ * (c) EdgeJS
6
+ *
7
+ * For the full copyright and license information, please view the LICENSE
8
+ * file that was distributed with this source code.
9
+ */
10
+ var __importDefault = (this && this.__importDefault) || function (mod) {
11
+ return (mod && mod.__esModule) ? mod : { "default": mod };
12
+ };
13
+ Object.defineProperty(exports, "__esModule", { value: true });
14
+ exports.nanoid = exports.StringifiedObject = void 0;
15
+ exports.unallowedExpression = unallowedExpression;
16
+ exports.isSubsetOf = isSubsetOf;
17
+ exports.isNotSubsetOf = isNotSubsetOf;
18
+ exports.parseJsArg = parseJsArg;
19
+ exports.each = each;
20
+ exports.asyncEach = asyncEach;
21
+ exports.stringifyAttributes = stringifyAttributes;
22
+ const classnames_1 = __importDefault(require("classnames"));
23
+ const edge_error_1 = require("edge-error");
24
+ const property_information_1 = require("property-information");
25
+ /**
26
+ * Function to register custom properties
27
+ * with "property-information" package.
28
+ */
29
+ function definePropertyInformation(property, value) {
30
+ property_information_1.html.normal[property] = property;
31
+ property_information_1.html.property[property] = {
32
+ attribute: property,
33
+ boolean: true,
34
+ property: property,
35
+ space: 'html',
36
+ booleanish: false,
37
+ commaOrSpaceSeparated: false,
38
+ commaSeparated: false,
39
+ spaceSeparated: false,
40
+ number: false,
41
+ overloadedBoolean: false,
42
+ defined: false,
43
+ mustUseProperty: false,
44
+ ...value,
45
+ };
46
+ }
47
+ definePropertyInformation('x-cloak');
48
+ definePropertyInformation('x-ignore');
49
+ definePropertyInformation('x-transition:enterstart', {
50
+ attribute: 'x-transition:enter-start',
51
+ property: 'x-transition:enterStart',
52
+ boolean: false,
53
+ spaceSeparated: true,
54
+ commaOrSpaceSeparated: true,
55
+ });
56
+ definePropertyInformation('x-transition:enterend', {
57
+ attribute: 'x-transition:enter-end',
58
+ property: 'x-transition:enterEnd',
59
+ boolean: false,
60
+ spaceSeparated: true,
61
+ commaOrSpaceSeparated: true,
62
+ });
63
+ definePropertyInformation('x-transition:leavestart', {
64
+ attribute: 'x-transition:leave-start',
65
+ property: 'x-transition:leaveStart',
66
+ boolean: false,
67
+ spaceSeparated: true,
68
+ commaOrSpaceSeparated: true,
69
+ });
70
+ definePropertyInformation('x-transition:leaveend', {
71
+ attribute: 'x-transition:leave-end',
72
+ property: 'x-transition:leaveEnd',
73
+ boolean: false,
74
+ spaceSeparated: true,
75
+ commaOrSpaceSeparated: true,
76
+ });
77
+ /**
78
+ * Alpine namespaces we handle with special
79
+ * rules when stringifying attributes
80
+ */
81
+ const alpineNamespaces = {
82
+ x: 'x-',
83
+ xOn: 'x-on:',
84
+ xBind: 'x-bind:',
85
+ xTransition: 'x-transition:',
86
+ };
87
+ /**
88
+ * Raise an `E_UNALLOWED_EXPRESSION` exception. Filename and expression is
89
+ * required to point the error stack to the correct file
90
+ */
91
+ function unallowedExpression(message, filename, loc) {
92
+ throw new edge_error_1.EdgeError(message, 'E_UNALLOWED_EXPRESSION', {
93
+ line: loc.line,
94
+ col: loc.col,
95
+ filename: filename,
96
+ });
97
+ }
98
+ /**
99
+ * Validates the expression type to be part of the allowed
100
+ * expressions only.
101
+ *
102
+ * The filename is required to report errors.
103
+ *
104
+ * ```js
105
+ * isNotSubsetOf(expression, ['Literal', 'Identifier'], () => {})
106
+ * ```
107
+ */
108
+ function isSubsetOf(expression, expressions, errorCallback) {
109
+ if (!expressions.includes(expression.type)) {
110
+ errorCallback();
111
+ }
112
+ }
113
+ /**
114
+ * Validates the expression type not to be part of the disallowed
115
+ * expressions.
116
+ *
117
+ * The filename is required to report errors.
118
+ *
119
+ * ```js
120
+ * isNotSubsetOf(expression, 'SequenceExpression', () => {})
121
+ * ```
122
+ */
123
+ function isNotSubsetOf(expression, expressions, errorCallback) {
124
+ if (expressions.includes(expression.type)) {
125
+ errorCallback();
126
+ }
127
+ }
128
+ /**
129
+ * Parses the jsArg by generating and transforming its AST
130
+ */
131
+ function parseJsArg(parser, token) {
132
+ return parser.utils.transformAst(parser.utils.generateAST(token.properties.jsArg, token.loc, token.filename), token.filename, parser);
133
+ }
134
+ /**
135
+ * Each loop. A soft replacement for `lodash.each` that we were using earlier
136
+ */
137
+ function each(collection, iteratee) {
138
+ if (Array.isArray(collection)) {
139
+ for (let [key, value] of collection.entries()) {
140
+ iteratee(value, key);
141
+ }
142
+ return;
143
+ }
144
+ if (typeof collection === 'string') {
145
+ let index = 0;
146
+ for (let value of collection) {
147
+ iteratee(value, index++);
148
+ }
149
+ return;
150
+ }
151
+ if (collection && typeof collection === 'object') {
152
+ for (let [key, value] of Object.entries(collection)) {
153
+ iteratee(value, key);
154
+ }
155
+ }
156
+ }
157
+ /**
158
+ * Async each loop. A soft replacement for `lodash.each` that we were
159
+ * using earlier with support for async await
160
+ */
161
+ async function asyncEach(collection, iteratee) {
162
+ if (Array.isArray(collection)) {
163
+ for (let [key, value] of collection.entries()) {
164
+ await iteratee(value, key);
165
+ }
166
+ return;
167
+ }
168
+ if (typeof collection === 'string') {
169
+ let index = 0;
170
+ for (let value of collection) {
171
+ await iteratee(value, index++);
172
+ }
173
+ return;
174
+ }
175
+ if (collection && typeof collection === 'object') {
176
+ for (let [key, value] of Object.entries(collection)) {
177
+ await iteratee(value, key);
178
+ }
179
+ }
180
+ }
181
+ /**
182
+ * This class generates a valid object as a string, which is written to the template
183
+ * output. The reason we need a string like object, since we don't want it's
184
+ * properties to be evaluated during the object creation, instead it must
185
+ * be evaluated when the compiled output is invoked.
186
+ */
187
+ class StringifiedObject {
188
+ #obj = '';
189
+ addSpread(key) {
190
+ this.#obj += this.#obj.length ? `, ${key}` : `${key}`;
191
+ }
192
+ /**
193
+ * Add key/value pair to the object.
194
+ *
195
+ * ```js
196
+ * stringifiedObject.add('username', `'virk'`)
197
+ * ```
198
+ */
199
+ add(key, value, isComputed = false) {
200
+ key = isComputed ? `[${key}]` : key;
201
+ this.#obj += this.#obj.length ? `, ${key}: ${value}` : `${key}: ${value}`;
202
+ }
203
+ /**
204
+ * Returns the object alike string back.
205
+ *
206
+ * ```js
207
+ * stringifiedObject.flush()
208
+ *
209
+ * // returns
210
+ * `{ username: 'virk' }`
211
+ * ```
212
+ */
213
+ flush() {
214
+ const obj = `{ ${this.#obj} }`;
215
+ this.#obj = '';
216
+ return obj;
217
+ }
218
+ }
219
+ exports.StringifiedObject = StringifiedObject;
220
+ /**
221
+ * Stringify an object to props to HTML attributes
222
+ */
223
+ function stringifyAttributes(props, namespace) {
224
+ const attributes = Object.keys(props);
225
+ if (attributes.length === 0) {
226
+ return '';
227
+ }
228
+ return attributes
229
+ .reduce((result, key) => {
230
+ let value = props[key];
231
+ key = namespace ? `${namespace}${key}` : key;
232
+ /**
233
+ * No value defined, remove attribute
234
+ */
235
+ if (!value) {
236
+ return result;
237
+ }
238
+ /**
239
+ * Handle alpine properties separately
240
+ */
241
+ if (alpineNamespaces[key] && typeof value === 'object') {
242
+ result = result.concat(stringifyAttributes(value, alpineNamespaces[key]));
243
+ return result;
244
+ }
245
+ const propInfo = (0, property_information_1.find)(property_information_1.html, key);
246
+ /**
247
+ * Ignore unknown attributes
248
+ */
249
+ if (!propInfo) {
250
+ return result;
251
+ }
252
+ const attribute = propInfo.attribute;
253
+ /**
254
+ * Boolean properties
255
+ */
256
+ if (value === true) {
257
+ result.push(attribute);
258
+ return result;
259
+ }
260
+ /**
261
+ * Encoding rules for certain properties.
262
+ *
263
+ * - Class values can be objects with conditionals
264
+ * - Non-booleanish and numeric properties will be html escaped
265
+ * - Arrays will be concatenated into a string list and html escaped
266
+ */
267
+ if (key === 'class') {
268
+ value = `"${(0, classnames_1.default)(value)}"`;
269
+ }
270
+ else if (Array.isArray(value)) {
271
+ value = `"${value.join(propInfo.commaSeparated ? ',' : ' ')}"`;
272
+ }
273
+ else {
274
+ value = `"${String(value)}"`;
275
+ }
276
+ /**
277
+ * Push attribute value string
278
+ */
279
+ result.push(`${attribute}=${value}`);
280
+ return result;
281
+ }, [])
282
+ .join(' ');
283
+ }
284
+ /**
285
+ * Copy-pasted from
286
+ * https://github.com/ai/nanoid/blob/main/nanoid.js
287
+ */
288
+ const seed = 'useandom26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict';
289
+ let nanoid = (length = 15) => {
290
+ let output = '';
291
+ const random = crypto.getRandomValues(new Uint8Array(length));
292
+ for (let n = 0; n < length; n++) {
293
+ output += seed[63 & random[n]];
294
+ }
295
+ return output;
296
+ };
297
+ exports.nanoid = nanoid;
package/tsconfig.json ADDED
@@ -0,0 +1,16 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2020", // modern JS target
4
+ "module": "CommonJS", // Node.js module system
5
+ "declaration": true, // generate .d.ts files
6
+ "outDir": ".", // compiled JS output
7
+ "rootDir": "./src", // source folder
8
+ "strict": true, // enable strict type checks
9
+ "esModuleInterop": true, // allow default imports from CJS modules
10
+ "forceConsistentCasingInFileNames": true,
11
+ "skipLibCheck": true,
12
+ "sourceMap": false // set true if debugging is needed
13
+ },
14
+ "include": ["src/**/*.ts", "index.ts"],
15
+ "exclude": ["node_modules", "tests"]
16
+ }