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.
- package/eslint.config.cjs +6 -0
- package/examples/index.js +41 -0
- package/examples/views/components/layout/main.edge +26 -0
- package/examples/views/components/modal.edge +27 -0
- package/examples/views/home.edge +84 -0
- package/examples/views/partials/button.edge +1 -0
- package/examples/views/partials/home-footer.edge +49 -0
- package/examples/views/partials/home-header.edge +61 -0
- package/examples/views/welcome.edge +22 -0
- package/index.d.ts +7 -0
- package/package.json +12 -4
- package/src/cache_manager.d.ts +28 -0
- package/src/cache_manager.js +58 -0
- package/src/compiler.d.ts +73 -0
- package/src/compiler.js +319 -0
- package/src/component/props.d.ts +53 -0
- package/src/component/props.js +110 -0
- package/src/edge/globals.d.ts +5 -0
- package/src/edge/globals.js +95 -0
- package/src/edge/main.d.ts +192 -0
- package/src/edge/main.js +334 -0
- package/src/edge/renderer.d.ts +44 -0
- package/src/edge/renderer.js +85 -0
- package/src/edge/stacks.d.ts +22 -0
- package/src/edge/stacks.js +98 -0
- package/src/loader.d.ts +138 -0
- package/src/loader.js +347 -0
- package/src/migrate/globals.d.ts +1 -0
- package/src/migrate/globals.js +100 -0
- package/src/migrate/plugin.d.ts +2 -0
- package/src/migrate/plugin.js +58 -0
- package/src/migrate/props.d.ts +66 -0
- package/src/migrate/props.js +129 -0
- package/src/migrate/tags/layout.d.ts +6 -0
- package/src/migrate/tags/layout.js +25 -0
- package/src/migrate/tags/main.d.ts +4 -0
- package/src/migrate/tags/main.js +19 -0
- package/src/migrate/tags/section.d.ts +6 -0
- package/src/migrate/tags/section.js +23 -0
- package/src/migrate/tags/set.d.ts +26 -0
- package/src/migrate/tags/set.js +104 -0
- package/src/migrate/tags/super.d.ts +9 -0
- package/src/migrate/tags/super.js +31 -0
- package/src/plugins/supercharged.d.ts +4 -0
- package/src/plugins/supercharged.js +88 -0
- package/src/processor.d.ts +42 -0
- package/src/processor.js +86 -0
- package/src/tags/assign.d.ts +5 -0
- package/src/tags/assign.js +42 -0
- package/src/tags/component.d.ts +6 -0
- package/src/tags/component.js +299 -0
- package/src/tags/debugger.d.ts +5 -0
- package/src/tags/debugger.js +26 -0
- package/src/tags/each.d.ts +20 -0
- package/src/tags/each.js +185 -0
- package/src/tags/else.d.ts +2 -0
- package/src/tags/else.js +22 -0
- package/src/tags/else_if.d.ts +7 -0
- package/src/tags/else_if.js +39 -0
- package/src/tags/eval.d.ts +7 -0
- package/src/tags/eval.js +30 -0
- package/src/tags/if.d.ts +5 -0
- package/src/tags/if.js +45 -0
- package/src/tags/include.d.ts +27 -0
- package/src/tags/include.js +78 -0
- package/src/tags/include_if.d.ts +10 -0
- package/src/tags/include_if.js +61 -0
- package/src/tags/inject.d.ts +6 -0
- package/src/tags/inject.js +40 -0
- package/src/tags/let.d.ts +6 -0
- package/src/tags/let.js +69 -0
- package/src/tags/main.d.ts +18 -0
- package/src/tags/main.js +47 -0
- package/src/tags/new_error.d.ts +6 -0
- package/src/tags/new_error.js +47 -0
- package/src/tags/push_once_to.d.ts +13 -0
- package/src/tags/push_once_to.js +65 -0
- package/src/tags/push_to.d.ts +7 -0
- package/src/tags/push_to.js +62 -0
- package/src/tags/slot.d.ts +6 -0
- package/src/tags/slot.js +29 -0
- package/src/tags/stack.d.ts +5 -0
- package/src/tags/stack.js +38 -0
- package/src/tags/unless.d.ts +12 -0
- package/src/tags/unless.js +52 -0
- package/src/template.d.ts +127 -0
- package/src/template.js +203 -0
- package/src/types.d.ts +144 -0
- package/src/types.js +10 -0
- package/src/utils.d.ts +96 -0
- package/src/utils.js +297 -0
- package/tsconfig.json +16 -0
|
@@ -0,0 +1,98 @@
|
|
|
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
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
const node_os_1 = require("node:os");
|
|
12
|
+
class Stacks {
|
|
13
|
+
#contentSources = new Map();
|
|
14
|
+
/**
|
|
15
|
+
* Pre-seeded content before the placeholder has been
|
|
16
|
+
* defined.
|
|
17
|
+
*/
|
|
18
|
+
#seededPlaceholders = new Map();
|
|
19
|
+
/**
|
|
20
|
+
* Placeholders to be flushed
|
|
21
|
+
*/
|
|
22
|
+
#placeholders = new Map();
|
|
23
|
+
/**
|
|
24
|
+
* Returns the placeholder name for a given stack
|
|
25
|
+
*/
|
|
26
|
+
#createPlaceholder(name) {
|
|
27
|
+
return `<!-- @edge.stacks.${name} -->`;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Create a new stack placeholder. Multiple calls to this method
|
|
31
|
+
* with the same name results in an exception.
|
|
32
|
+
*/
|
|
33
|
+
create(name) {
|
|
34
|
+
if (this.#placeholders.has(name)) {
|
|
35
|
+
throw new Error(`Cannot declare stack "${name}" for multiple times`);
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Copy content from the seeded placeholders and delete it
|
|
39
|
+
*/
|
|
40
|
+
const seededPlaceholder = this.#seededPlaceholders.get(name) || [];
|
|
41
|
+
this.#seededPlaceholders.delete(name);
|
|
42
|
+
this.#placeholders.set(name, [...seededPlaceholder]);
|
|
43
|
+
return this.#createPlaceholder(name);
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Push content inside a given stack. Content can be pre-seeded
|
|
47
|
+
* without creating a stack
|
|
48
|
+
*/
|
|
49
|
+
pushTo(name, contents) {
|
|
50
|
+
let placeholder = this.#placeholders.get(name);
|
|
51
|
+
if (!placeholder) {
|
|
52
|
+
if (!this.#seededPlaceholders.has(name)) {
|
|
53
|
+
this.#seededPlaceholders.set(name, []);
|
|
54
|
+
}
|
|
55
|
+
const seededPlaceholder = this.#seededPlaceholders.get(name);
|
|
56
|
+
seededPlaceholder.push(contents);
|
|
57
|
+
return this;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Defined content for the unique key inside a given
|
|
61
|
+
* stack
|
|
62
|
+
*/
|
|
63
|
+
placeholder.push(contents);
|
|
64
|
+
return this;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Push contents to a stack with a unique source id. A
|
|
68
|
+
* source can only push once to a given stack.
|
|
69
|
+
*/
|
|
70
|
+
pushOnceTo(name, sourceId, contents) {
|
|
71
|
+
const contentSources = this.#contentSources.get(name);
|
|
72
|
+
if (contentSources && contentSources.has(sourceId)) {
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
this.pushTo(name, contents);
|
|
76
|
+
/**
|
|
77
|
+
* Track source
|
|
78
|
+
*/
|
|
79
|
+
if (contentSources) {
|
|
80
|
+
contentSources.add(sourceId);
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
this.#contentSources.set(name, new Set([sourceId]));
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Fill placeholders with their actual content
|
|
88
|
+
*/
|
|
89
|
+
fillPlaceholders(contents) {
|
|
90
|
+
for (let [name, sources] of this.#placeholders) {
|
|
91
|
+
contents = contents.replace(this.#createPlaceholder(name), sources.join(node_os_1.EOL));
|
|
92
|
+
}
|
|
93
|
+
this.#placeholders.clear();
|
|
94
|
+
this.#seededPlaceholders.clear();
|
|
95
|
+
return contents;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
exports.default = Stacks;
|
package/src/loader.d.ts
ADDED
|
@@ -0,0 +1,138 @@
|
|
|
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 { ComponentsTree, LoaderContract, LoaderTemplate } from './types.js'
|
|
10
|
+
/**
|
|
11
|
+
* The job of a loader is to load the template from a given path.
|
|
12
|
+
* The base loader (shipped with edge) looks for files on the
|
|
13
|
+
* file-system and reads them synchronously.
|
|
14
|
+
*
|
|
15
|
+
* You are free to define your own loaders that implements the [[LoaderContract]] interface.
|
|
16
|
+
*/
|
|
17
|
+
export declare class Loader implements LoaderContract {
|
|
18
|
+
#private
|
|
19
|
+
/**
|
|
20
|
+
* Returns an object of mounted directories with their public
|
|
21
|
+
* names.
|
|
22
|
+
*
|
|
23
|
+
* ```js
|
|
24
|
+
* loader.mounted
|
|
25
|
+
* // output
|
|
26
|
+
*
|
|
27
|
+
* {
|
|
28
|
+
* default: '/users/virk/code/app/views',
|
|
29
|
+
* foo: '/users/virk/code/app/foo',
|
|
30
|
+
* }
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
get mounted(): {
|
|
34
|
+
[key: string]: string
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Returns an object of templates registered as a raw string
|
|
38
|
+
*
|
|
39
|
+
* ```js
|
|
40
|
+
* loader.templates
|
|
41
|
+
* // output
|
|
42
|
+
*
|
|
43
|
+
* {
|
|
44
|
+
* 'form.label': { template: 'Template contents' }
|
|
45
|
+
* }
|
|
46
|
+
* ```
|
|
47
|
+
*/
|
|
48
|
+
get templates(): {
|
|
49
|
+
[templatePath: string]: LoaderTemplate
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Mount a directory with a name for resolving views. If name is set
|
|
53
|
+
* to `default`, then you can resolve views without prefixing the
|
|
54
|
+
* disk name.
|
|
55
|
+
*
|
|
56
|
+
* ```js
|
|
57
|
+
* loader.mount('default', join(__dirname, 'views'))
|
|
58
|
+
*
|
|
59
|
+
* // mount a named disk
|
|
60
|
+
* loader.mount('admin', join(__dirname, 'admin/views'))
|
|
61
|
+
* ```
|
|
62
|
+
*/
|
|
63
|
+
mount(diskName: string, dirPath: string | URL): void
|
|
64
|
+
/**
|
|
65
|
+
* Remove the previously mounted dir.
|
|
66
|
+
*
|
|
67
|
+
* ```js
|
|
68
|
+
* loader.unmount('default')
|
|
69
|
+
* ```
|
|
70
|
+
*/
|
|
71
|
+
unmount(diskName: string): void
|
|
72
|
+
/**
|
|
73
|
+
* Make path to a given template. The paths are resolved from the root
|
|
74
|
+
* of the mounted directory.
|
|
75
|
+
*
|
|
76
|
+
* ```js
|
|
77
|
+
* loader.makePath('welcome') // returns {diskRootPath}/welcome.edge
|
|
78
|
+
* loader.makePath('admin::welcome') // returns {adminRootPath}/welcome.edge
|
|
79
|
+
* loader.makePath('users.list') // returns {diskRootPath}/users/list.edge
|
|
80
|
+
* ```
|
|
81
|
+
*
|
|
82
|
+
* @throws Error if disk is not mounted and attempting to make path for it.
|
|
83
|
+
*/
|
|
84
|
+
makePath(templatePath: string): string
|
|
85
|
+
/**
|
|
86
|
+
* Resolves the template by reading its contents from the disk
|
|
87
|
+
*
|
|
88
|
+
* ```js
|
|
89
|
+
* loader.resolve('welcome', true)
|
|
90
|
+
*
|
|
91
|
+
* // output
|
|
92
|
+
* {
|
|
93
|
+
* template: `<h1> Template content </h1>`,
|
|
94
|
+
* }
|
|
95
|
+
* ```
|
|
96
|
+
*/
|
|
97
|
+
resolve(templatePath: string): LoaderTemplate
|
|
98
|
+
/**
|
|
99
|
+
* Register in memory template for a given path. This is super helpful
|
|
100
|
+
* when distributing components.
|
|
101
|
+
*
|
|
102
|
+
* ```js
|
|
103
|
+
* loader.register('welcome', {
|
|
104
|
+
* template: '<h1> Template content </h1>',
|
|
105
|
+
* Presenter: class Presenter {
|
|
106
|
+
* constructor (state) {
|
|
107
|
+
* this.state = state
|
|
108
|
+
* }
|
|
109
|
+
* }
|
|
110
|
+
* })
|
|
111
|
+
* ```
|
|
112
|
+
*
|
|
113
|
+
* @throws Error if template content is empty.
|
|
114
|
+
*/
|
|
115
|
+
register(templatePath: string, contents: LoaderTemplate): void
|
|
116
|
+
/**
|
|
117
|
+
* Remove registered template
|
|
118
|
+
*/
|
|
119
|
+
remove(templatePath: string): void
|
|
120
|
+
/**
|
|
121
|
+
* Returns a list of components from all the disks. We assume
|
|
122
|
+
* the components are stored within the components directory.
|
|
123
|
+
*
|
|
124
|
+
* Also, we treat all in-memory templates as components.
|
|
125
|
+
*
|
|
126
|
+
* The return path is same the path you will pass to the `@component`
|
|
127
|
+
* tag.
|
|
128
|
+
*/
|
|
129
|
+
listComponents(): ComponentsTree
|
|
130
|
+
/**
|
|
131
|
+
* Returns a list of templates from all the disks and in-memory
|
|
132
|
+
* templates as well
|
|
133
|
+
*/
|
|
134
|
+
listTemplates(): {
|
|
135
|
+
diskName: string
|
|
136
|
+
templates: string[]
|
|
137
|
+
}[]
|
|
138
|
+
}
|
package/src/loader.js
ADDED
|
@@ -0,0 +1,347 @@
|
|
|
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
|
+
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.Loader = void 0;
|
|
15
|
+
const node_url_1 = require("node:url");
|
|
16
|
+
const string_1 = __importDefault(require("@poppinss/utils/string"));
|
|
17
|
+
const node_path_1 = require("node:path");
|
|
18
|
+
const node_fs_1 = require("node:fs");
|
|
19
|
+
/**
|
|
20
|
+
* The job of a loader is to load the template from a given path.
|
|
21
|
+
* The base loader (shipped with edge) looks for files on the
|
|
22
|
+
* file-system and reads them synchronously.
|
|
23
|
+
*
|
|
24
|
+
* You are free to define your own loaders that implements the [[LoaderContract]] interface.
|
|
25
|
+
*/
|
|
26
|
+
class Loader {
|
|
27
|
+
/**
|
|
28
|
+
* List of mounted directories
|
|
29
|
+
*/
|
|
30
|
+
#mountedDirs = new Map();
|
|
31
|
+
/**
|
|
32
|
+
* List of pre-registered (in-memory) templates
|
|
33
|
+
*/
|
|
34
|
+
#preRegistered = new Map();
|
|
35
|
+
/**
|
|
36
|
+
* Reads the content of a template from the disk. An exception is raised
|
|
37
|
+
* when file is missing or if `readFileSync` returns an error.
|
|
38
|
+
*/
|
|
39
|
+
#readTemplateContents(absPath) {
|
|
40
|
+
try {
|
|
41
|
+
return (0, node_fs_1.readFileSync)(absPath, 'utf-8');
|
|
42
|
+
}
|
|
43
|
+
catch (error) {
|
|
44
|
+
if (error.code === 'ENOENT') {
|
|
45
|
+
throw new Error(`Cannot resolve "${absPath}". Make sure the file exists`);
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
throw error;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Returns a list of components for a given disk
|
|
54
|
+
*/
|
|
55
|
+
#getDiskComponents(diskName) {
|
|
56
|
+
const componentsDirName = 'components';
|
|
57
|
+
const diskBasePath = this.#mountedDirs.get(diskName);
|
|
58
|
+
let files = diskName === 'default'
|
|
59
|
+
? Array.from(this.#preRegistered.keys()).map((template) => {
|
|
60
|
+
return {
|
|
61
|
+
fileName: template,
|
|
62
|
+
componentPath: template,
|
|
63
|
+
};
|
|
64
|
+
})
|
|
65
|
+
: [];
|
|
66
|
+
/**
|
|
67
|
+
* Read disk files
|
|
68
|
+
*/
|
|
69
|
+
const componentsPath = (0, node_path_1.join)(diskBasePath, componentsDirName);
|
|
70
|
+
if ((0, node_fs_1.existsSync)(componentsPath)) {
|
|
71
|
+
files = files.concat((0, node_fs_1.readdirSync)((0, node_path_1.join)(componentsPath), {
|
|
72
|
+
recursive: true,
|
|
73
|
+
withFileTypes: true,
|
|
74
|
+
})
|
|
75
|
+
.filter((file) => {
|
|
76
|
+
return file.isFile() && file.name.endsWith('.edge');
|
|
77
|
+
})
|
|
78
|
+
.map((file) => {
|
|
79
|
+
const fileName = string_1.default
|
|
80
|
+
.toUnixSlash((0, node_path_1.relative)(componentsPath, (0, node_path_1.join)(file.parentPath, file.name)))
|
|
81
|
+
.replace(/\.edge$/, '');
|
|
82
|
+
return {
|
|
83
|
+
fileName,
|
|
84
|
+
componentPath: `${componentsDirName}/${fileName}`,
|
|
85
|
+
};
|
|
86
|
+
}));
|
|
87
|
+
}
|
|
88
|
+
return files.map(({ fileName, componentPath }) => {
|
|
89
|
+
const tagName = fileName
|
|
90
|
+
.split('/')
|
|
91
|
+
.filter((segment, index) => {
|
|
92
|
+
return index === 0 || segment !== 'index';
|
|
93
|
+
})
|
|
94
|
+
.map((segment) => string_1.default.camelCase(segment))
|
|
95
|
+
.join('.');
|
|
96
|
+
return {
|
|
97
|
+
componentName: diskName !== 'default' ? `${diskName}::${componentPath}` : componentPath,
|
|
98
|
+
tagName: diskName !== 'default' ? `${diskName}.${tagName}` : tagName,
|
|
99
|
+
};
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Returns a list of templates for a given disk
|
|
104
|
+
*/
|
|
105
|
+
#getDiskTemplates(diskName) {
|
|
106
|
+
const diskBasePath = this.#mountedDirs.get(diskName);
|
|
107
|
+
let files = diskName === 'default' ? Array.from(this.#preRegistered.keys()) : [];
|
|
108
|
+
if ((0, node_fs_1.existsSync)(diskBasePath)) {
|
|
109
|
+
files = files.concat((0, node_fs_1.readdirSync)(diskBasePath, {
|
|
110
|
+
recursive: true,
|
|
111
|
+
withFileTypes: true,
|
|
112
|
+
})
|
|
113
|
+
.filter((file) => {
|
|
114
|
+
return file.isFile() && file.name.endsWith('.edge');
|
|
115
|
+
})
|
|
116
|
+
.map((file) => {
|
|
117
|
+
return (0, node_path_1.relative)(diskBasePath, (0, node_path_1.join)(file.parentPath, file.name)).replace(/\.edge$/, '');
|
|
118
|
+
}));
|
|
119
|
+
}
|
|
120
|
+
return files.map((file) => {
|
|
121
|
+
const fileName = string_1.default.toUnixSlash(file).replace(/\.edge$/, '');
|
|
122
|
+
return diskName !== 'default' ? `${diskName}::${fileName}` : fileName;
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Extracts the disk name and the template name from the template
|
|
127
|
+
* path expression.
|
|
128
|
+
*
|
|
129
|
+
* If `diskName` is missing, it will be set to `default`.
|
|
130
|
+
*
|
|
131
|
+
* ```
|
|
132
|
+
* extractDiskAndTemplateName('users::list')
|
|
133
|
+
* // returns ['users', 'list.edge']
|
|
134
|
+
*
|
|
135
|
+
* extractDiskAndTemplateName('list')
|
|
136
|
+
* // returns ['default', 'list.edge']
|
|
137
|
+
* ```
|
|
138
|
+
*/
|
|
139
|
+
#extractDiskAndTemplateName(templatePath) {
|
|
140
|
+
let [disk, ...rest] = templatePath.split('::');
|
|
141
|
+
if (!rest.length) {
|
|
142
|
+
rest = [disk];
|
|
143
|
+
disk = 'default';
|
|
144
|
+
}
|
|
145
|
+
let [template, ext] = rest.join('::').split('.edge');
|
|
146
|
+
return [disk, `${template}.${ext || 'edge'}`];
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Returns an object of mounted directories with their public
|
|
150
|
+
* names.
|
|
151
|
+
*
|
|
152
|
+
* ```js
|
|
153
|
+
* loader.mounted
|
|
154
|
+
* // output
|
|
155
|
+
*
|
|
156
|
+
* {
|
|
157
|
+
* default: '/users/virk/code/app/views',
|
|
158
|
+
* foo: '/users/virk/code/app/foo',
|
|
159
|
+
* }
|
|
160
|
+
* ```
|
|
161
|
+
*/
|
|
162
|
+
get mounted() {
|
|
163
|
+
return Array.from(this.#mountedDirs).reduce((obj, [key, value]) => {
|
|
164
|
+
obj[key] = value;
|
|
165
|
+
return obj;
|
|
166
|
+
}, {});
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Returns an object of templates registered as a raw string
|
|
170
|
+
*
|
|
171
|
+
* ```js
|
|
172
|
+
* loader.templates
|
|
173
|
+
* // output
|
|
174
|
+
*
|
|
175
|
+
* {
|
|
176
|
+
* 'form.label': { template: 'Template contents' }
|
|
177
|
+
* }
|
|
178
|
+
* ```
|
|
179
|
+
*/
|
|
180
|
+
get templates() {
|
|
181
|
+
return Array.from(this.#preRegistered).reduce((obj, [key, value]) => {
|
|
182
|
+
obj[key] = value;
|
|
183
|
+
return obj;
|
|
184
|
+
}, {});
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Mount a directory with a name for resolving views. If name is set
|
|
188
|
+
* to `default`, then you can resolve views without prefixing the
|
|
189
|
+
* disk name.
|
|
190
|
+
*
|
|
191
|
+
* ```js
|
|
192
|
+
* loader.mount('default', join(__dirname, 'views'))
|
|
193
|
+
*
|
|
194
|
+
* // mount a named disk
|
|
195
|
+
* loader.mount('admin', join(__dirname, 'admin/views'))
|
|
196
|
+
* ```
|
|
197
|
+
*/
|
|
198
|
+
mount(diskName, dirPath) {
|
|
199
|
+
this.#mountedDirs.set(diskName, typeof dirPath === 'string' ? dirPath : (0, node_url_1.fileURLToPath)(dirPath));
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Remove the previously mounted dir.
|
|
203
|
+
*
|
|
204
|
+
* ```js
|
|
205
|
+
* loader.unmount('default')
|
|
206
|
+
* ```
|
|
207
|
+
*/
|
|
208
|
+
unmount(diskName) {
|
|
209
|
+
this.#mountedDirs.delete(diskName);
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Make path to a given template. The paths are resolved from the root
|
|
213
|
+
* of the mounted directory.
|
|
214
|
+
*
|
|
215
|
+
* ```js
|
|
216
|
+
* loader.makePath('welcome') // returns {diskRootPath}/welcome.edge
|
|
217
|
+
* loader.makePath('admin::welcome') // returns {adminRootPath}/welcome.edge
|
|
218
|
+
* loader.makePath('users.list') // returns {diskRootPath}/users/list.edge
|
|
219
|
+
* ```
|
|
220
|
+
*
|
|
221
|
+
* @throws Error if disk is not mounted and attempting to make path for it.
|
|
222
|
+
*/
|
|
223
|
+
makePath(templatePath) {
|
|
224
|
+
/**
|
|
225
|
+
* Return the template path as it is, when it is registered
|
|
226
|
+
* dynamically
|
|
227
|
+
*/
|
|
228
|
+
if (this.#preRegistered.has(templatePath)) {
|
|
229
|
+
return templatePath;
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Return absolute path as it is
|
|
233
|
+
*/
|
|
234
|
+
if ((0, node_path_1.isAbsolute)(templatePath)) {
|
|
235
|
+
return templatePath;
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Extract disk name and template path from the expression
|
|
239
|
+
*/
|
|
240
|
+
const [diskName, template] = this.#extractDiskAndTemplateName(templatePath);
|
|
241
|
+
/**
|
|
242
|
+
* Raise exception when disk name is not registered
|
|
243
|
+
*/
|
|
244
|
+
const mountedDir = this.#mountedDirs.get(diskName);
|
|
245
|
+
if (!mountedDir) {
|
|
246
|
+
throw new Error(`"${diskName}" namespace is not mounted`);
|
|
247
|
+
}
|
|
248
|
+
return (0, node_path_1.join)(mountedDir, template);
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* Resolves the template by reading its contents from the disk
|
|
252
|
+
*
|
|
253
|
+
* ```js
|
|
254
|
+
* loader.resolve('welcome', true)
|
|
255
|
+
*
|
|
256
|
+
* // output
|
|
257
|
+
* {
|
|
258
|
+
* template: `<h1> Template content </h1>`,
|
|
259
|
+
* }
|
|
260
|
+
* ```
|
|
261
|
+
*/
|
|
262
|
+
resolve(templatePath) {
|
|
263
|
+
/**
|
|
264
|
+
* Return from pre-registered one's if exists
|
|
265
|
+
*/
|
|
266
|
+
if (this.#preRegistered.has(templatePath)) {
|
|
267
|
+
return this.#preRegistered.get(templatePath);
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* Make absolute to the file on the disk
|
|
271
|
+
*/
|
|
272
|
+
templatePath = (0, node_path_1.isAbsolute)(templatePath) ? templatePath : this.makePath(templatePath);
|
|
273
|
+
return {
|
|
274
|
+
template: this.#readTemplateContents(templatePath),
|
|
275
|
+
};
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
* Register in memory template for a given path. This is super helpful
|
|
279
|
+
* when distributing components.
|
|
280
|
+
*
|
|
281
|
+
* ```js
|
|
282
|
+
* loader.register('welcome', {
|
|
283
|
+
* template: '<h1> Template content </h1>',
|
|
284
|
+
* Presenter: class Presenter {
|
|
285
|
+
* constructor (state) {
|
|
286
|
+
* this.state = state
|
|
287
|
+
* }
|
|
288
|
+
* }
|
|
289
|
+
* })
|
|
290
|
+
* ```
|
|
291
|
+
*
|
|
292
|
+
* @throws Error if template content is empty.
|
|
293
|
+
*/
|
|
294
|
+
register(templatePath, contents) {
|
|
295
|
+
/**
|
|
296
|
+
* Ensure template content is defined as a string
|
|
297
|
+
*/
|
|
298
|
+
if (typeof contents.template !== 'string') {
|
|
299
|
+
throw new Error('Make sure to define the template content as a string');
|
|
300
|
+
}
|
|
301
|
+
/**
|
|
302
|
+
* Do not overwrite existing template with same template path
|
|
303
|
+
*/
|
|
304
|
+
if (this.#preRegistered.has(templatePath)) {
|
|
305
|
+
throw new Error(`Cannot override previously registered "${templatePath}" template`);
|
|
306
|
+
}
|
|
307
|
+
this.#preRegistered.set(templatePath, contents);
|
|
308
|
+
}
|
|
309
|
+
/**
|
|
310
|
+
* Remove registered template
|
|
311
|
+
*/
|
|
312
|
+
remove(templatePath) {
|
|
313
|
+
this.#preRegistered.delete(templatePath);
|
|
314
|
+
}
|
|
315
|
+
/**
|
|
316
|
+
* Returns a list of components from all the disks. We assume
|
|
317
|
+
* the components are stored within the components directory.
|
|
318
|
+
*
|
|
319
|
+
* Also, we treat all in-memory templates as components.
|
|
320
|
+
*
|
|
321
|
+
* The return path is same the path you will pass to the `@component`
|
|
322
|
+
* tag.
|
|
323
|
+
*/
|
|
324
|
+
listComponents() {
|
|
325
|
+
const diskNames = [...this.#mountedDirs.keys()];
|
|
326
|
+
return diskNames.map((diskName) => {
|
|
327
|
+
return {
|
|
328
|
+
diskName,
|
|
329
|
+
components: this.#getDiskComponents(diskName),
|
|
330
|
+
};
|
|
331
|
+
});
|
|
332
|
+
}
|
|
333
|
+
/**
|
|
334
|
+
* Returns a list of templates from all the disks and in-memory
|
|
335
|
+
* templates as well
|
|
336
|
+
*/
|
|
337
|
+
listTemplates() {
|
|
338
|
+
const diskNames = [...this.#mountedDirs.keys()];
|
|
339
|
+
return diskNames.map((diskName) => {
|
|
340
|
+
return {
|
|
341
|
+
diskName,
|
|
342
|
+
templates: this.#getDiskTemplates(diskName),
|
|
343
|
+
};
|
|
344
|
+
});
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
exports.Loader = Loader;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const GLOBALS: Record<string, Function>
|
|
@@ -0,0 +1,100 @@
|
|
|
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.GLOBALS = void 0;
|
|
15
|
+
const edge_error_1 = require("edge-error");
|
|
16
|
+
// @ts-ignore untyped module
|
|
17
|
+
const js_stringify_1 = __importDefault(require("js-stringify"));
|
|
18
|
+
// @ts-ignore untyped module
|
|
19
|
+
const inspect_1 = __importDefault(require("@poppinss/inspect"));
|
|
20
|
+
const { string: prettyPrintHtml } = inspect_1.default;
|
|
21
|
+
const string_1 = __importDefault(require("@poppinss/utils/string"));
|
|
22
|
+
const template_js_1 = require("../template.js");
|
|
23
|
+
exports.GLOBALS = {
|
|
24
|
+
/**
|
|
25
|
+
* Converts new lines to break
|
|
26
|
+
*/
|
|
27
|
+
nl2br: (value) => {
|
|
28
|
+
if (!value) {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
return String(value).replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g, '$1<br>');
|
|
32
|
+
},
|
|
33
|
+
/**
|
|
34
|
+
* Inspect state
|
|
35
|
+
*/
|
|
36
|
+
inspect: (value) => {
|
|
37
|
+
return (0, template_js_1.htmlSafe)(prettyPrintHtml.html(value));
|
|
38
|
+
},
|
|
39
|
+
/**
|
|
40
|
+
* Truncate a sentence
|
|
41
|
+
*/
|
|
42
|
+
truncate: (value, length = 20, options) => {
|
|
43
|
+
options = options || {};
|
|
44
|
+
return string_1.default.truncate(value, length, {
|
|
45
|
+
completeWords: options.completeWords !== undefined ? options.completeWords : !options.strict,
|
|
46
|
+
suffix: options.suffix,
|
|
47
|
+
});
|
|
48
|
+
},
|
|
49
|
+
/**
|
|
50
|
+
* Raise an exception
|
|
51
|
+
*/
|
|
52
|
+
raise: (message, options) => {
|
|
53
|
+
if (!options) {
|
|
54
|
+
throw new Error(message);
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
throw new edge_error_1.EdgeError(message, 'E_RUNTIME_EXCEPTION', options);
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
/**
|
|
61
|
+
* Generate an excerpt
|
|
62
|
+
*/
|
|
63
|
+
excerpt: (value, length = 20, options) => {
|
|
64
|
+
options = options || {};
|
|
65
|
+
return string_1.default.excerpt(value, length, {
|
|
66
|
+
completeWords: options.completeWords !== undefined ? options.completeWords : !options.strict,
|
|
67
|
+
suffix: options.suffix,
|
|
68
|
+
});
|
|
69
|
+
},
|
|
70
|
+
/**
|
|
71
|
+
* Using `"e"` because, `escape` is a global function in the
|
|
72
|
+
* Node.js global namespace and edge parser gives priority
|
|
73
|
+
* to it
|
|
74
|
+
*/
|
|
75
|
+
e: template_js_1.escape,
|
|
76
|
+
/**
|
|
77
|
+
* Convert javascript data structures to a string. The method is a little
|
|
78
|
+
* better over JSON.stringify in handling certain data structures. For
|
|
79
|
+
* example: In JSON.stringify, the date is converted to an ISO string
|
|
80
|
+
* whereas this method converts it to an actual instance of date
|
|
81
|
+
*/
|
|
82
|
+
stringify: js_stringify_1.default,
|
|
83
|
+
safe: template_js_1.htmlSafe,
|
|
84
|
+
camelCase: string_1.default.camelCase,
|
|
85
|
+
snakeCase: string_1.default.snakeCase,
|
|
86
|
+
dashCase: string_1.default.dashCase,
|
|
87
|
+
pascalCase: string_1.default.pascalCase,
|
|
88
|
+
capitalCase: string_1.default.capitalCase,
|
|
89
|
+
sentenceCase: string_1.default.sentenceCase,
|
|
90
|
+
dotCase: string_1.default.dotCase,
|
|
91
|
+
noCase: string_1.default.noCase,
|
|
92
|
+
titleCase: string_1.default.titleCase,
|
|
93
|
+
pluralize: string_1.default.pluralize,
|
|
94
|
+
sentence: string_1.default.sentence,
|
|
95
|
+
prettyMs: string_1.default.milliseconds.format,
|
|
96
|
+
toMs: string_1.default.milliseconds.parse,
|
|
97
|
+
prettyBytes: string_1.default.bytes.format,
|
|
98
|
+
toBytes: string_1.default.bytes.parse,
|
|
99
|
+
ordinal: string_1.default.ordinal,
|
|
100
|
+
};
|