edgexpress 3.0.1 → 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 +3 -3
  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
@@ -0,0 +1,6 @@
1
+ // eslint.config.cjs
2
+ const { configPkg } = require('@adonisjs/eslint-config');
3
+
4
+ module.exports = configPkg({
5
+ ignores: ['coverage'],
6
+ });
@@ -0,0 +1,41 @@
1
+ const express = require('express');
2
+ const { Edge } = require('edgexpress');
3
+
4
+
5
+ // Initialize Express
6
+ const app = express();
7
+ const edge = Edge.create()
8
+
9
+
10
+ edge.mount(path.join(__dirname, 'views'))
11
+
12
+ // Determine environment
13
+ const isProduction = process.env.NODE_ENV === 'production';
14
+
15
+ // Enable/disable cache depending on environment
16
+ edge.configure({
17
+ cache: isProduction
18
+ })
19
+
20
+ // Tell Express where templates are
21
+ app.set('views', path.join(__dirname, 'views'))
22
+
23
+ // 3️⃣ Create a global asset() helper
24
+ edge.global('asset', (filePath) => `/assets/${filePath}`);
25
+
26
+ // Register Edge as Express view engine
27
+ app.engine('edge', async (filePath, options, callback) => {
28
+ try {
29
+ // Derive template name (relative to views dir, no extension)
30
+ const templateName = path
31
+ .relative(app.get('views'), filePath)
32
+ .replace(/\\/g, '/') // handle Windows paths
33
+ .replace('.edge', '') // remove extension
34
+
35
+ const html = await edge.render(templateName, options)
36
+ return callback(null, html)
37
+ } catch (err) {
38
+ return callback(err)
39
+ }
40
+ })
41
+ app.set('view engine', 'edge')
@@ -0,0 +1,26 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <title>{{ title || "Your default title" }}</title>
6
+
7
+ <link rel="stylesheet" href="{{ asset('assets/css/custom.css') }}">
8
+ <link rel="stylesheet" href="{{ asset('assets/css/app.css') }}">
9
+
10
+ @if ($slots.meta)
11
+ {{{ await $slots.meta() }}}
12
+ @endif
13
+ </head>
14
+ <body>
15
+
16
+ @include('partials/header')
17
+
18
+ {{{ await $slots.main() }}}
19
+
20
+ @include('partials/footer')
21
+
22
+
23
+ <script src="{{ asset('assets/js/main.js') }}"></script>
24
+ <script src="{{ asset('assets/js/app.js') }}"></script>
25
+ </body>
26
+ </html>
@@ -0,0 +1,27 @@
1
+ {{ inspect(state) }}
2
+
3
+ <div {{
4
+ ({
5
+ class: 'modal',
6
+ x: {
7
+ data: `{
8
+ title: '${title}',
9
+ trigger: {
10
+ ['@click']() {
11
+ alert(this.title)
12
+ }
13
+ }
14
+ }`
15
+ }
16
+ })
17
+ }}
18
+ >
19
+ <h1 class="title">{{ title }}</h1>
20
+ <div>
21
+ {{{ await $slots.body() }}}
22
+ </div>
23
+
24
+ <div>
25
+ {{{ await $slots.actions() }}}
26
+ </div>
27
+ </div>
@@ -0,0 +1,84 @@
1
+ @layout.main({ title: site?.name || "Home Page" })
2
+
3
+ @slot('main')
4
+ <!-- Testimonials Section -->
5
+ <section class="testimonials">
6
+ <div class="container">
7
+ <div class="section-title">
8
+ <h2>What Our Clients Say</h2>
9
+ <p>Don't just take our word for it - hear from our satisfied clients</p>
10
+ </div>
11
+
12
+ <div class="testimonial-slider">
13
+ <div class="slider-container">
14
+ @each(testimonial in testimonials)
15
+ <div class="testimonial" data-rating="{{ testimonial.rating }}">
16
+ <div class="testimonial-text">
17
+ <p>{{ testimonial.text }}</p>
18
+ </div>
19
+ <div class="testimonial-author">
20
+ <div class="author-img">
21
+ <img src="{{ testimonial.author_image }}" alt="{{ testimonial.author_name }}">
22
+ </div>
23
+ <div class="author-info">
24
+ <div class="author-name">{{ testimonial.author_name }}</div>
25
+ <div class="author-title">{{ testimonial.author_title }}</div>
26
+ <div class="rating"></div>
27
+ </div>
28
+ </div>
29
+ </div>
30
+ @endeach
31
+ </div>
32
+
33
+ <!-- Slider Controls -->
34
+ <div class="slider-controls">
35
+ <button class="slider-btn prev-btn">
36
+ <i class="fas fa-chevron-left"></i>
37
+ </button>
38
+ <button class="slider-btn next-btn">
39
+ <i class="fas fa-chevron-right"></i>
40
+ </button>
41
+ </div>
42
+
43
+ <div class="slider-dots">
44
+ <div class="dot active"></div>
45
+ <div class="dot"></div>
46
+ <div class="dot"></div>
47
+ <div class="dot"></div>
48
+ </div>
49
+ </div>
50
+ </div>
51
+ </section>
52
+
53
+ <!-- Clients Section -->
54
+ <section class="clients">
55
+ <div class="container">
56
+ <div class="section-title">
57
+ <h2>Our Trusted Partners</h2>
58
+ <p>We're proud to work with industry leaders and innovative startups</p>
59
+ </div>
60
+
61
+ <!-- Swiper Wrapper -->
62
+ <div class="swiper client-slider">
63
+ <div class="swiper-wrapper">
64
+ @if(clients && clients.length > 0)
65
+ @each(client in clients)
66
+ <div class="swiper-slide">
67
+ <a href="{{ client.url }}" target="_blank" rel="noopener">
68
+ <img src="{{ client.logo_url }}" alt="{{ client.name }}" class="client-logo">
69
+ </a>
70
+ </div>
71
+ @endeach
72
+ @else
73
+ <div class="swiper-slide">
74
+ <span class="client-logo">No Data at the moment!</span>
75
+ </div>
76
+
77
+ @endif
78
+ </div>
79
+ </div>
80
+ </div>
81
+ </section>
82
+
83
+ @endslot
84
+ @end
@@ -0,0 +1 @@
1
+ <button x-bind="trigger">delete</button>
@@ -0,0 +1,49 @@
1
+
2
+ <!-- Footer -->
3
+ <footer>
4
+ <div class="container">
5
+ <div class="footer-content">
6
+
7
+
8
+ <div class="footer-column">
9
+ @if(footerLinks && footerLinks.length)
10
+ <h3>Quick Links</h3>
11
+ <ul class="footer-links services-dropdown">
12
+ @each(link in footerLinks)
13
+ <li><a href="{{ link.url }}">{{ link.label || 'Untitled' }}</a></li>
14
+ @endeach
15
+ </ul>
16
+ @endif
17
+ </div>
18
+
19
+ <div class="footer-column">
20
+ <h3>Services</h3>
21
+ <ul class="footer-links services-dropdown">
22
+ @if(services)
23
+ @each(card in services)
24
+ <li><a href="/services/{{ card.slug }}">{{ card.title ?? 'Untitled Service' }}</a></li>
25
+ @endeach
26
+ @endif
27
+ </ul>
28
+ </div>
29
+
30
+ </div>
31
+
32
+ <div class="footer-bottom">
33
+ <p>&copy; 2023
34
+ @if(location)
35
+ {{ location.name }}
36
+ @endif
37
+ Inc. All Rights Reserved. |
38
+ @if(term)
39
+ <a href="{{ term.url }}">{{ term.label }}</a>
40
+ @endif
41
+ |
42
+ @if(policy)
43
+ <a href="{{ policy.url }}">{{ policy.label }}</a>
44
+ @endif
45
+ </p>
46
+ </div>
47
+ </div>
48
+ </footer>
49
+
@@ -0,0 +1,61 @@
1
+
2
+ <!-- Main Navigation -->
3
+ <header>
4
+ <div class="container">
5
+ <nav>
6
+ <a href="/" class="logo">
7
+ @if(location)
8
+ <img src="{{ asset(`uploads/settings/${location.image}`) }}" alt="logo">
9
+ <div class="d-flex flex-column">
10
+ <span class="fw-bolder h5 mb-0 extra-bold">{{ location.name }}</span>
11
+ <small class="text-primary text-center fst-italic fw-light border-top pt-1 px-1" style="font-size: 0.75rem; letter-spacing: 0.5px;" title="Company slogan" aria-label="Company slogan">
12
+ {{ location.slogan }}
13
+ </small>
14
+ </div>
15
+ @endif
16
+ </a>
17
+
18
+ <button class="mobile-menu-btn" id="mobileMenuBtn">
19
+ <i class="fas fa-bars"></i>
20
+ </button>
21
+ <ul class="nav-links" id="navLinks">
22
+ {{-- 1) Home --}}
23
+ @if(homeLink)
24
+ <li>
25
+ <a href="{{ homeLink?.url }}"
26
+ class="{{ currentUrl === homeLink.url ? 'active' : '' }}">
27
+ {{ homeLink?.label || 'Home' }}
28
+ </a>
29
+ </li>
30
+ @endif
31
+
32
+ {{-- 2. Services dropdown --}}
33
+ <li class="nav-item dropdown">
34
+ <button class="nav-link dropdown-toggle {{ currentUrl == '/services/' ? 'active' : '' }}" href="#" id="servicesDropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false">
35
+ SERVICES
36
+ </button>
37
+ <ul class="dropdown-menu services-dropdown" aria-labelledby="servicesDropdown">
38
+ @each(card in serviceCards)
39
+ <li>
40
+ <a href="/services/{{ card?.slug }}" class="dropdown-item {{ currentUrl == '/services/' + card.slug ? 'active' : '' }}">
41
+ {{ card?.title || 'Untitled Service' }}
42
+ </a>
43
+ </li>
44
+ @endeach
45
+ </ul>
46
+ </li>
47
+
48
+ {{-- 3) Other header links --}}
49
+ @if(otherLinks && otherLinks.length)
50
+ @each(link in otherLinks)
51
+ <li>
52
+ <a href="{{ link?.url }}" class="{{ currentUrl == link.url ? 'active' : '' }}">
53
+ {{ link?.label || 'Untitled' }}
54
+ </a>
55
+ </li>
56
+ @endeach
57
+ @endif
58
+ </ul>
59
+ </nav>
60
+ </div>
61
+ </header>
@@ -0,0 +1,22 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <title></title>
6
+ <script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script>
7
+ </head>
8
+ <body>
9
+ {{ inspect(state.user) }}
10
+ @set('time', 'afternoon')
11
+
12
+ @component('components/modal', title = 'foo', title = 'bar')
13
+ @slot('body')
14
+ <p>hello</p>
15
+ @endslot
16
+
17
+ @slot('actions')
18
+ @include('partials/button')
19
+ @endslot
20
+ @endcomponent
21
+ </body>
22
+ </html>
package/index.d.ts ADDED
@@ -0,0 +1,7 @@
1
+ import { Edge } from './src/edge/main.js';
2
+ export { EdgeError } from 'edge-error';
3
+ export { Template } from './src/template.js';
4
+ export { edgeGlobals } from './src/edge/globals.js';
5
+ export { Edge };
6
+ declare const edge: Edge;
7
+ export default edge;
package/package.json CHANGED
@@ -1,14 +1,14 @@
1
1
  {
2
2
  "name": "edgexpress",
3
3
  "description": "Template engine",
4
- "version": "3.0.1",
4
+ "version": "3.0.2",
5
5
  "engines": {
6
6
  "node": ">=18.16.0"
7
7
  },
8
8
  "main": "index.js",
9
9
  "types": "index.d.ts",
10
10
  "files": [
11
- "!examples"
11
+ "**/*"
12
12
  ],
13
13
  "exports": {
14
14
  ".": "./index.js",
@@ -87,7 +87,7 @@
87
87
  "format": "cjs",
88
88
  "minify": "dce-only",
89
89
  "fixedExtension": false,
90
- "dts": false,
90
+ "dts": true,
91
91
  "treeshake": false,
92
92
  "sourcemaps": false,
93
93
  "target": "esnext"
@@ -0,0 +1,28 @@
1
+ import type { CacheManagerContract, CompiledTemplate } from './types.js'
2
+ /**
3
+ * In memory cache manager to cache pre-compiled templates.
4
+ */
5
+ export declare class CacheManager implements CacheManagerContract {
6
+ #private
7
+ enabled: boolean
8
+ constructor(enabled: boolean)
9
+ /**
10
+ * Returns a boolean to tell if a template has already been cached
11
+ * or not.
12
+ */
13
+ has(absPath: string): boolean
14
+ /**
15
+ * Returns the template from the cache. If caching is disabled,
16
+ * then it will return undefined.
17
+ */
18
+ get(absPath: string): undefined | CompiledTemplate
19
+ /**
20
+ * Set's the template path and the payload to the cache. If
21
+ * cache is disabled, then this function results in a noop.
22
+ */
23
+ set(absPath: string, payload: CompiledTemplate): void
24
+ /**
25
+ * Delete template from the compiled cache
26
+ */
27
+ delete(absPath: string): void
28
+ }
@@ -0,0 +1,58 @@
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
+ exports.CacheManager = void 0;
12
+ /**
13
+ * In memory cache manager to cache pre-compiled templates.
14
+ */
15
+ class CacheManager {
16
+ enabled;
17
+ #cacheStore = new Map();
18
+ constructor(enabled) {
19
+ this.enabled = enabled;
20
+ }
21
+ /**
22
+ * Returns a boolean to tell if a template has already been cached
23
+ * or not.
24
+ */
25
+ has(absPath) {
26
+ return this.#cacheStore.has(absPath);
27
+ }
28
+ /**
29
+ * Returns the template from the cache. If caching is disabled,
30
+ * then it will return undefined.
31
+ */
32
+ get(absPath) {
33
+ if (!this.enabled) {
34
+ return;
35
+ }
36
+ return this.#cacheStore.get(absPath);
37
+ }
38
+ /**
39
+ * Set's the template path and the payload to the cache. If
40
+ * cache is disabled, then this function results in a noop.
41
+ */
42
+ set(absPath, payload) {
43
+ if (!this.enabled) {
44
+ return;
45
+ }
46
+ this.#cacheStore.set(absPath, payload);
47
+ }
48
+ /**
49
+ * Delete template from the compiled cache
50
+ */
51
+ delete(absPath) {
52
+ if (!this.enabled) {
53
+ return;
54
+ }
55
+ this.#cacheStore.delete(absPath);
56
+ }
57
+ }
58
+ exports.CacheManager = CacheManager;
@@ -0,0 +1,73 @@
1
+ import { type Parser } from 'edge-parser'
2
+ import type { Token } from 'edge-lexer/types'
3
+ import { type Processor } from './processor.js'
4
+ import { type CacheManager } from './cache_manager.js'
5
+ import type {
6
+ ClaimTagFn,
7
+ TagsContract,
8
+ LoaderContract,
9
+ CompilerOptions,
10
+ CompiledTemplate,
11
+ } from './types.js'
12
+ /**
13
+ * Compiler is to used to compile templates using the `edge-parser`. Along with that
14
+ * it natively merges the contents of a layout with a parent template.
15
+ */
16
+ export declare class Compiler {
17
+ #private
18
+ /**
19
+ * Caches compiled templates
20
+ */
21
+ cacheManager: CacheManager
22
+ /**
23
+ * A boolean to know if compat mode is enabled
24
+ */
25
+ compat: boolean
26
+ /**
27
+ * Know if compiler is compiling in the async mode or not
28
+ */
29
+ async: boolean
30
+ constructor(
31
+ loader: LoaderContract,
32
+ tags: TagsContract,
33
+ processor: Processor,
34
+ options?: CompilerOptions
35
+ )
36
+ /**
37
+ * Define a function to claim tags
38
+ */
39
+ claimTag(fn: ClaimTagFn): this
40
+ /**
41
+ * Converts the template content to an array of lexer tokens. The method is
42
+ * same as the `parser.tokenize`, but it also handles layouts natively.
43
+ *
44
+ * ```
45
+ * compiler.tokenize('<template-path>')
46
+ * ```
47
+ */
48
+ tokenize(templatePath: string, parser?: Parser): Token[]
49
+ /**
50
+ * Tokenize a raw template
51
+ */
52
+ tokenizeRaw(contents: string, templatePath?: string, parser?: Parser): Token[]
53
+ /**
54
+ * Compiles the template contents to string. The output is same as the `edge-parser`,
55
+ * it's just that the compiler uses the loader to load the templates and also
56
+ * handles layouts.
57
+ *
58
+ * ```js
59
+ * compiler.compile('welcome')
60
+ * ```
61
+ */
62
+ compile(templatePath: string, localVariables?: string[]): CompiledTemplate
63
+ /**
64
+ * Compiles the template contents to string. The output is same as the `edge-parser`,
65
+ * it's just that the compiler uses the loader to load the templates and also
66
+ * handles layouts.
67
+ *
68
+ * ```js
69
+ * compiler.compileRaw('welcome')
70
+ * ```
71
+ */
72
+ compileRaw(contents: string, templatePath?: string): CompiledTemplate
73
+ }