vite-file-include 1.0.3 → 1.1.0

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 (3) hide show
  1. package/README.md +134 -117
  2. package/package.json +29 -30
  3. package/src/index.js +185 -74
package/README.md CHANGED
@@ -1,211 +1,228 @@
1
- # vite-file-include
1
+ # vite-file-include 🔗
2
2
 
3
- `vite-file-include` is an advanced Vite plugin designed to facilitate the inclusion of external HTML files, looping through data, and conditional rendering within your HTML files. It is particularly useful for managing repetitive HTML structures in static sites or templating environments.
3
+ `vite-file-include` is a modern **Vite plugin** for HTML templating that supports **file inclusion**, **looping**, **conditional rendering**, and **live hot-reload** without reloading the full page.
4
+ It’s ideal for managing repetitive HTML structures in static sites or prototyping environments.
4
5
 
5
- ## Features
6
+ ---
6
7
 
7
- - File inclusion with support for nested includes
8
- - Looping through data arrays or JSON files
9
- - Conditional rendering
10
- - Custom function support for advanced templating
11
- - Evaluate JavaScript expressions directly in your templates.
12
- - Asynchronous file processing
13
- - Enhanced error handling and debugging
8
+ ## 🚀 Features
14
9
 
10
+ - 🧩 **Nested file includes** with variable support
11
+ - 🔁 **Loop rendering** for data arrays and JSON files
12
+ - ⚙️ **Conditional blocks** using inline JavaScript
13
+ - 🧠 **Custom helper functions** for advanced templating
14
+ - ⚡ **JavaScript expression evaluation** inside templates
15
+ - 🔄 **Hot reload support** — live updates without full page refresh
16
+ - 🧵 **Async file processing** and better performance
17
+ - 🪶 **Enhanced error reporting** with context hints
15
18
 
16
- ## Installation
19
+ ---
17
20
 
18
- Install the plugin via npm:
21
+ ## 📦 Installation
19
22
 
20
23
  ```bash
21
- npm install vite-file-include
24
+ npm install vite-file-include --save-dev
22
25
  ```
23
26
 
24
- ## Configuration
27
+ ---
25
28
 
26
- To use the plugin, import and configure it in your `vite.config.js`:
29
+ ## ⚙️ Configuration
27
30
 
28
- ```javascript
29
- import fileIncludePlugin from 'vite-file-include';
31
+ Add the plugin to your `vite.config.js`:
30
32
 
31
- export default {
33
+ ```js
34
+ import { defineConfig } from 'vite'
35
+ import fileIncludePlugin from 'vite-file-include'
36
+
37
+ export default defineConfig({
32
38
  plugins: [
33
39
  fileIncludePlugin({
34
40
  includePattern: "@@include",
35
41
  loopPattern: "@@loop",
36
42
  ifPattern: "@@if",
37
43
  baseDir: process.cwd(),
38
- context: {},
39
- customFunctions: {},
40
- }),
41
- ],
42
- };
44
+ context: {
45
+ siteName: 'My Static Site'
46
+ },
47
+ customFunctions: {
48
+ uppercase: (str) => str.toUpperCase(),
49
+ currentYear: () => new Date().getFullYear()
50
+ }
51
+ })
52
+ ]
53
+ })
43
54
  ```
44
55
 
45
- ### Plugin Options
56
+ ---
46
57
 
47
- - `includePattern` (default: `@@include`): The pattern used to include external HTML files.
48
- - `loopPattern` (default: `@@loop`): The pattern used to loop through data arrays.
49
- - `ifPattern` (default: `@@if`): The pattern used to conditionally render content.
50
- - `baseDir` (default: `process.cwd()`): The base directory for resolving paths.
51
- - `context` (default: `{}`): An object containing global variables that can be used in includes, loops, and conditionals.
52
- - `customFunctions` (default: {}): An object containing custom functions that can be used in your templates.
58
+ ## 🧩 Plugin Options
53
59
 
54
- ## Directives
60
+ | Option | Type | Default | Description |
61
+ |--------|------|----------|-------------|
62
+ | **`includePattern`** | `string` | `@@include` | Directive for including files |
63
+ | **`loopPattern`** | `string` | `@@loop` | Directive for looping over arrays/JSON |
64
+ | **`ifPattern`** | `string` | `@@if` | Directive for conditional rendering |
65
+ | **`baseDir`** | `string` | `process.cwd()` | Base directory for resolving paths |
66
+ | **`context`** | `object` | `{}` | Global variables accessible in templates |
67
+ | **`customFunctions`** | `object` | `{}` | Custom functions available in templates |
55
68
 
56
- ### `@@include`
69
+ ---
57
70
 
58
- The `@@include` directive allows you to include the content of another HTML file within your main file.
71
+ ## 🧱 Directives
59
72
 
60
- **Syntax:**
73
+ ### 🔹 `@@include`
74
+
75
+ Include another HTML file into your main file.
61
76
 
62
77
  ```html
63
- @@include('path/to/file.html');
78
+ @@include('partials/header.html')
64
79
  ```
65
80
 
66
- **With Data:**
81
+ With data:
67
82
 
68
83
  ```html
69
- @@include('path/to/file.html', { "key": "value" });
84
+ @@include('partials/header.html', { "title": "Home Page" })
70
85
  ```
71
86
 
72
- **Example** (`file.html`):
87
+ **Example** (`partials/header.html`):
73
88
 
74
89
  ```html
75
- <div>{{ key }}</div>
90
+ <header>
91
+ <h1>{{ title }}</h1>
92
+ </header>
76
93
  ```
77
94
 
78
- ### `@@loop`
95
+ ---
79
96
 
80
- The `@@loop` directive enables you to repeat a block of HTML for each item in a data array or JSON file.
97
+ ### 🔹 `@@loop`
81
98
 
82
- **Syntax:**
99
+ Repeat an HTML block for each item in a data array or JSON file.
83
100
 
84
101
  ```html
85
- @@loop('path/to/template.html', 'data.json');
102
+ @@loop('partials/article.html', 'data/articles.json')
86
103
  ```
87
104
 
88
- **With Inline Data:**
105
+ Or inline data:
89
106
 
90
107
  ```html
91
- @@loop('path/to/template.html', [{ "key": "value" }, { "key": "another value" }]);
108
+ @@loop('partials/article.html', [
109
+ { "title": "Article 1" },
110
+ { "title": "Article 2" }
111
+ ])
92
112
  ```
93
113
 
94
- **Example Template** (`template.html`):
114
+ **Example** (`partials/article.html`):
95
115
 
96
116
  ```html
97
117
  <article>
98
- <h2>{{ key }}</h2>
118
+ <h2>{{ title }}</h2>
99
119
  </article>
100
120
  ```
101
121
 
102
- ### `@@if`
122
+ ---
103
123
 
104
- The `@@if` directive allows conditional rendering based on an expression.
124
+ ### 🔹 `@@if`
105
125
 
106
- **Syntax:**
126
+ Conditionally render content based on an expression.
107
127
 
108
128
  ```html
109
- @@if(condition) {
110
- <!-- HTML content -->
111
- }
129
+ @@if(showFooter) {
130
+ @@include('partials/footer.html')
131
+ };
112
132
  ```
113
133
 
114
134
  **Example:**
115
135
 
116
136
  ```html
117
- @@if(name === 'John') {
118
- <p>Welcome, John!</p>
119
- }
137
+ @@if(user.isLoggedIn) {
138
+ <p>Welcome, {{ user.name }}</p>
139
+ };
120
140
  ```
121
141
 
122
- ## Custom Functions
123
-
124
- You can define custom functions to use in your templates. These functions are passed to the plugin through the `customFunctions` option:
142
+ ---
125
143
 
126
- ```javascript
127
- fileIncludePlugin({
128
- customFunctions: {
129
- uppercase: (str) => str.toUpperCase(),
130
- currentYear: () => new Date().getFullYear()
131
- }
132
- })
133
- ```
144
+ ## 🧮 JavaScript Expressions
134
145
 
135
- You can then use these functions in your templates:
146
+ Use JS directly inside templates:
136
147
 
137
148
  ```html
138
- <p>{{ uppercase(name) }}</p>
139
- <footer>&copy; {{ currentYear() }}</footer>
149
+ <p>Year: {{ new Date().getFullYear() }}</p>
150
+ <p>Uppercase: {{ 'vite'.toUpperCase() }}</p>
140
151
  ```
141
152
 
153
+ ---
142
154
 
143
- ## JavaScript Expressions
155
+ ## 🧰 Custom Functions
144
156
 
145
- You can use JavaScript expressions directly in your templates. For example:
157
+ Define reusable helpers in your config:
146
158
 
147
- ```html
148
- <p>Current Year: {{ new Date().getFullYear() }}</p>
149
- <p>Uppercase Text: {{ 'John'.toUpperCase() }}</p>
159
+ ```js
160
+ customFunctions: {
161
+ uppercase: (str) => str.toUpperCase(),
162
+ currentYear: () => new Date().getFullYear(),
163
+ }
150
164
  ```
151
165
 
152
- ## Example Usage
153
-
154
- Below is an example of how you might structure your HTML files using the plugin's directives:
166
+ Usage:
155
167
 
156
168
  ```html
157
- <!-- main.html -->
158
- <html>
159
- <body>
160
- @@include('header.html', { "title": "My Website" });
169
+ <h1>{{ uppercase(title) }}</h1>
170
+ <footer>&copy; {{ currentYear() }}</footer>
171
+ ```
161
172
 
162
- @@loop('partials/article.html', 'data/articles.json');
173
+ ---
163
174
 
164
- @@if(showFooter) {
165
- @@include('footer.html');
166
- }
167
- </body>
168
- </html>
169
- ```
175
+ ## 🔄 Hot Reload
170
176
 
171
- ### Example Files
177
+ Unlike static include tools, `vite-file-include` supports **Vite’s HMR (Hot Module Replacement)**.
172
178
 
173
- - `header.html`:
179
+ - Changes to included files update **instantly** in the browser
180
+ - No full page reload
181
+ - Works seamlessly with Vite’s dev server
174
182
 
175
- ```html
176
- <header>
177
- <h1>{{ uppercase(title) }}</h1>
178
- </header>
183
+ 💡 Tip: Useful for quickly editing partials like headers, footers, and repeating components.
184
+
185
+ ---
186
+
187
+ ## 🧰 Example Project Structure
188
+
189
+ ```
190
+ project/
191
+ ├─ index.html
192
+ ├─ partials/
193
+ │ ├─ header.html
194
+ │ ├─ footer.html
195
+ │ └─ article.html
196
+ ├─ data/
197
+ │ └─ articles.json
198
+ └─ vite.config.js
179
199
  ```
180
200
 
181
- - `partials/article.html`:
201
+ **index.html**
182
202
 
183
203
  ```html
184
- <article>
185
- <h2>{{ title }}</h2>
186
- <p>{{ content }}</p>
187
- </article>
204
+ <html>
205
+ <body>
206
+ @@include('partials/header.html', { "title": "My Site" })
207
+ @@loop('partials/article.html', 'data/articles.json')
208
+ @@if(showFooter) { @@include('partials/footer.html') };
209
+ </body>
210
+ </html>
188
211
  ```
189
212
 
190
- - `data/articles.json`:
213
+ ---
191
214
 
192
- ```json
193
- [
194
- {
195
- "title": "Article 1",
196
- "content": "Content of the first article."
197
- },
198
- {
199
- "title": "Article 2",
200
- "content": "Content of the second article."
201
- }
202
- ]
203
- ```
215
+ ## ⚠️ Error Handling
216
+
217
+ The plugin provides detailed error messages for:
218
+ - Missing include files
219
+ - Invalid JSON syntax
220
+ - Undefined variables
204
221
 
205
- ## Error Handling
222
+ Each error logs file path and directive line for easier debugging.
206
223
 
207
- If there is an error parsing JSON data or including a file, the plugin will log a detailed error message to the console. This helps in debugging while ensuring that your build process continues without interruption.
224
+ ---
208
225
 
209
- ## License
226
+ ## 📄 License
210
227
 
211
- This project is licensed under the MIT License. See the LICENSE file for more details.
228
+ MIT © 2025
package/package.json CHANGED
@@ -1,30 +1,29 @@
1
- {
2
- "name": "vite-file-include",
3
- "version": "1.0.3",
4
- "description": "A Vite plugin for file inclusion, loops, and conditionals in HTML files",
5
- "main": "src/index.js",
6
- "type": "module",
7
- "scripts": {
8
- "test": "echo \"Error: no test specified\" && exit 1"
9
- },
10
- "keywords": [
11
- "vite",
12
- "plugin",
13
- "file-include",
14
- "html"
15
- ],
16
- "author": "Ahmed Abdulgid",
17
- "license": "MIT",
18
- "repository": {
19
- "type": "git",
20
- "url": "https://github.com/abdulgidcoder/vite-file-includ.git"
21
- },
22
- "peerDependencies": {
23
- "vite": "^4.0.0"
24
- },
25
- "dependencies": {
26
- "fs": "0.0.1-security",
27
- "path": "^0.12.7",
28
- "vite-file-include": "^1.0.2"
29
- }
30
- }
1
+ {
2
+ "name": "vite-file-include",
3
+ "version": "1.1.0",
4
+ "description": "A Vite plugin for file inclusion, loops, and conditionals in HTML files",
5
+ "main": "src/index.js",
6
+ "type": "module",
7
+ "scripts": {
8
+ "test": "echo \"Error: no test specified\" && exit 1"
9
+ },
10
+ "keywords": [
11
+ "vite",
12
+ "plugin",
13
+ "file-include",
14
+ "html"
15
+ ],
16
+ "author": "Ahmed Abdulgid",
17
+ "license": "MIT",
18
+ "repository": {
19
+ "type": "git",
20
+ "url": "https://github.com/abdulgidcoder/vite-file-include.git"
21
+ },
22
+ "peerDependencies": {
23
+ "vite": "^4.0.0"
24
+ },
25
+ "dependencies": {
26
+ "fs": "0.0.1-security",
27
+ "path": "^0.12.7"
28
+ }
29
+ }
package/src/index.js CHANGED
@@ -11,6 +11,16 @@ function fileIncludePlugin(options = {}) {
11
11
  customFunctions = {},
12
12
  } = options;
13
13
 
14
+ // Cache for file reads
15
+ const fileCache = new Map();
16
+
17
+ const readFileCached = (filePath) => {
18
+ if (!fileCache.has(filePath)) {
19
+ fileCache.set(filePath, fs.readFileSync(filePath, "utf-8"));
20
+ }
21
+ return fileCache.get(filePath);
22
+ };
23
+
14
24
  return {
15
25
  name: "vite-plugin-file-include",
16
26
 
@@ -22,35 +32,64 @@ function fileIncludePlugin(options = {}) {
22
32
  loopPattern,
23
33
  ifPattern,
24
34
  context,
25
- customFunctions
35
+ customFunctions,
36
+ new Set(),
37
+ readFileCached
26
38
  );
27
39
  },
28
40
 
29
41
  transform(code, id) {
30
42
  if (id.endsWith(".html")) {
31
- return processIncludes(
32
- code,
33
- path.dirname(id),
34
- includePattern,
35
- loopPattern,
36
- ifPattern,
37
- context,
38
- customFunctions
39
- );
43
+ return {
44
+ code: processIncludes(
45
+ code,
46
+ baseDir,
47
+ includePattern,
48
+ loopPattern,
49
+ ifPattern,
50
+ context,
51
+ customFunctions,
52
+ new Set(),
53
+ readFileCached
54
+ ),
55
+ };
40
56
  }
41
- return code;
57
+ return { code };
42
58
  },
43
59
 
44
- handleHotUpdate({ file, server }) {
60
+ handleHotUpdate({ file, server, modules }) {
45
61
  if (file.endsWith(".html")) {
46
- server.ws.send({
47
- type: "full-reload",
48
- });
62
+ const mod = modules.find((m) => m.file && m.file.endsWith(".html"));
63
+
64
+ if (mod) {
65
+ server.moduleGraph.invalidateModule(mod);
66
+ server.ws.send({
67
+ type: "update",
68
+ updates: [
69
+ {
70
+ type: "js-update",
71
+ path: mod.url,
72
+ acceptedPath: mod.url,
73
+ timestamp: Date.now(),
74
+ },
75
+ ],
76
+ });
77
+ } else {
78
+ server.ws.send({
79
+ type: "custom",
80
+ event: "vite-file-include:update",
81
+ data: { file },
82
+ });
83
+ }
84
+
85
+ return [];
49
86
  }
50
87
  },
51
88
  };
52
89
  }
53
90
 
91
+ /* ---------------- Core Processing ---------------- */
92
+
54
93
  function processIncludes(
55
94
  content,
56
95
  dir,
@@ -58,27 +97,47 @@ function processIncludes(
58
97
  loopPattern,
59
98
  ifPattern,
60
99
  context,
61
- customFunctions
100
+ customFunctions,
101
+ visited,
102
+ readFileCached
62
103
  ) {
63
- content = processIncludesWithPattern(
64
- content,
65
- dir,
66
- includePattern,
67
- loopPattern,
68
- ifPattern,
69
- context,
70
- customFunctions
71
- );
72
- content = processLoops(content, dir, loopPattern, context, customFunctions);
73
- content = processConditionals(
74
- content,
75
- dir,
76
- ifPattern,
77
- includePattern,
78
- loopPattern,
79
- context,
80
- customFunctions
81
- );
104
+ let lastContent;
105
+ do {
106
+ lastContent = content;
107
+ content = processIncludesWithPattern(
108
+ content,
109
+ dir,
110
+ includePattern,
111
+ loopPattern,
112
+ ifPattern,
113
+ context,
114
+ customFunctions,
115
+ visited,
116
+ readFileCached
117
+ );
118
+ content = processLoops(
119
+ content,
120
+ dir,
121
+ loopPattern,
122
+ context,
123
+ customFunctions,
124
+ includePattern,
125
+ ifPattern,
126
+ visited,
127
+ readFileCached
128
+ );
129
+ content = processConditionals(
130
+ content,
131
+ dir,
132
+ ifPattern,
133
+ includePattern,
134
+ loopPattern,
135
+ context,
136
+ customFunctions,
137
+ visited,
138
+ readFileCached
139
+ );
140
+ } while (content !== lastContent);
82
141
 
83
142
  return content;
84
143
  }
@@ -90,27 +149,34 @@ function processIncludesWithPattern(
90
149
  loopPattern,
91
150
  ifPattern,
92
151
  context,
93
- customFunctions
152
+ customFunctions,
153
+ visited,
154
+ readFileCached
94
155
  ) {
95
156
  const regex = new RegExp(
96
- `${includePattern}\\(\\s*['"](.+?)['"]\\s*,?\\s*({[\\s\\S]*?})?\\s*\\);`,
157
+ `${includePattern}\\(\\s*['"]([^'"]+)['"]\\s*(?:,\\s*({[\\s\\S]*?}))?\\s*\\)\\s*;?`,
97
158
  "g"
98
159
  );
99
160
 
100
161
  return content.replace(regex, (match, filePath, jsonData) => {
101
162
  const includePath = path.resolve(dir, filePath);
102
- let data = {};
163
+ if (visited.has(includePath)) {
164
+ console.warn(`⚠️ Circular include detected: ${includePath}`);
165
+ return "";
166
+ }
167
+ visited.add(includePath);
103
168
 
169
+ let data = {};
104
170
  if (jsonData) {
105
171
  try {
106
172
  data = JSON.parse(jsonData);
107
- } catch (error) {
173
+ } catch {
108
174
  console.error(`Failed to parse JSON data: ${jsonData}`);
109
175
  }
110
176
  }
111
177
 
112
178
  try {
113
- let includedContent = fs.readFileSync(includePath, "utf-8");
179
+ let includedContent = readFileCached(includePath);
114
180
  includedContent = injectData(
115
181
  includedContent,
116
182
  { ...context, ...data },
@@ -122,19 +188,31 @@ function processIncludesWithPattern(
122
188
  includePattern,
123
189
  loopPattern,
124
190
  ifPattern,
125
- context,
126
- customFunctions
191
+ { ...context, ...data },
192
+ customFunctions,
193
+ visited,
194
+ readFileCached
127
195
  );
128
- } catch (error) {
196
+ } catch (err) {
129
197
  console.error(`Failed to include file: ${includePath}`);
130
198
  return "";
131
199
  }
132
200
  });
133
201
  }
134
202
 
135
- function processLoops(content, dir, loopPattern, context, customFunctions) {
203
+ function processLoops(
204
+ content,
205
+ dir,
206
+ loopPattern,
207
+ context,
208
+ customFunctions,
209
+ includePattern,
210
+ ifPattern,
211
+ visited,
212
+ readFileCached
213
+ ) {
136
214
  const regex = new RegExp(
137
- `${loopPattern}\\(\\s*['"](.+?)['"]\\s*,\\s*(\\[[\\s\\S]*?\\]|['"](.+?)['"])\\s*\\);`,
215
+ `${loopPattern}\\(\\s*['"]([^'"]+)['"]\\s*,\\s*(\\[[\\s\\S]*?\\]|['"][^'"]+['"])\\s*\\)\\s*;?`,
138
216
  "g"
139
217
  );
140
218
 
@@ -143,31 +221,46 @@ function processLoops(content, dir, loopPattern, context, customFunctions) {
143
221
  let dataArray = [];
144
222
 
145
223
  try {
146
- if (
147
- jsonArrayOrFilePath.startsWith("[") ||
148
- jsonArrayOrFilePath.startsWith("{")
149
- ) {
224
+ if (jsonArrayOrFilePath.trim().startsWith("[")) {
150
225
  dataArray = JSON.parse(jsonArrayOrFilePath);
151
226
  } else {
152
227
  const jsonFilePath = path.resolve(
153
228
  dir,
154
229
  jsonArrayOrFilePath.replace(/['"]/g, "")
155
230
  );
156
- const jsonData = fs.readFileSync(jsonFilePath, "utf-8");
231
+ const jsonData = readFileCached(jsonFilePath);
157
232
  dataArray = JSON.parse(jsonData);
158
233
  }
159
234
  } catch (error) {
160
- console.error(`Failed to parse JSON: ${jsonArrayOrFilePath}`);
161
- console.error(error);
235
+ console.error(`Failed to parse loop JSON: ${jsonArrayOrFilePath}`);
236
+ return "";
162
237
  }
163
238
 
164
239
  try {
165
- let loopTemplate = fs.readFileSync(loopPath, "utf-8");
240
+ let loopTemplate = readFileCached(loopPath);
166
241
  return dataArray
167
- .map((data) => injectData(loopTemplate, data, customFunctions))
242
+ .map((data) => {
243
+ const mergedContext = { ...context, ...data };
244
+ const loopContent = injectData(
245
+ loopTemplate,
246
+ mergedContext,
247
+ customFunctions
248
+ );
249
+ return processIncludes(
250
+ loopContent,
251
+ dir,
252
+ includePattern,
253
+ loopPattern,
254
+ ifPattern,
255
+ mergedContext,
256
+ customFunctions,
257
+ visited,
258
+ readFileCached
259
+ );
260
+ })
168
261
  .join("");
169
262
  } catch (error) {
170
- console.error(`Failed to include file: ${loopPath}`);
263
+ console.error(`Failed to include loop file: ${loopPath}`);
171
264
  return "";
172
265
  }
173
266
  });
@@ -180,10 +273,12 @@ function processConditionals(
180
273
  includePattern,
181
274
  loopPattern,
182
275
  context,
183
- customFunctions
276
+ customFunctions,
277
+ visited,
278
+ readFileCached
184
279
  ) {
185
280
  const regex = new RegExp(
186
- `${ifPattern}\\s*\\(([^)]+)\\)\\s*{([\\s\\S]*?)};\\s*`,
281
+ `${ifPattern}\\s*\\(([^)]+)\\)\\s*{([\\s\\S]*?)};?`,
187
282
  "g"
188
283
  );
189
284
 
@@ -192,21 +287,45 @@ function processConditionals(
192
287
  const result = evaluateCondition(condition, context, customFunctions);
193
288
 
194
289
  if (result) {
195
- return processIncludesWithPattern(
290
+ let processed = processIncludesWithPattern(
196
291
  body.trim(),
197
292
  dir,
198
293
  includePattern,
199
294
  loopPattern,
200
295
  ifPattern,
201
296
  context,
202
- customFunctions
297
+ customFunctions,
298
+ visited,
299
+ readFileCached
300
+ );
301
+ processed = processLoops(
302
+ processed,
303
+ dir,
304
+ loopPattern,
305
+ context,
306
+ customFunctions,
307
+ includePattern,
308
+ ifPattern,
309
+ visited,
310
+ readFileCached
311
+ );
312
+ processed = processConditionals(
313
+ processed,
314
+ dir,
315
+ ifPattern,
316
+ includePattern,
317
+ loopPattern,
318
+ context,
319
+ customFunctions,
320
+ visited,
321
+ readFileCached
203
322
  );
323
+ return processed;
204
324
  }
205
325
 
206
326
  return "";
207
327
  } catch (error) {
208
328
  console.error(`Failed to evaluate condition: ${condition}`);
209
- console.error(error);
210
329
  return "";
211
330
  }
212
331
  });
@@ -217,30 +336,22 @@ function injectData(content, data, customFunctions = {}) {
217
336
  try {
218
337
  const result = evaluateExpression(expression, data, customFunctions);
219
338
  return result !== undefined ? result : match;
220
- } catch (error) {
221
- console.error(`Failed to evaluate expression: ${expression}`);
222
- console.error(error);
339
+ } catch {
223
340
  return match;
224
341
  }
225
342
  });
226
343
  }
227
344
 
228
345
  function evaluateExpression(expression, data, customFunctions) {
229
- // Bind custom functions to the evaluation context
230
346
  const context = { ...data, ...customFunctions };
231
- return new Function(
232
- "context",
233
- "with (context) { return " + expression + "; }"
234
- )(context);
347
+ return new Function("context", `with (context) { return ${expression}; }`)(
348
+ context
349
+ );
235
350
  }
236
351
 
237
352
  function evaluateCondition(condition, context, customFunctions) {
238
- // Bind custom functions to the evaluation context
239
- const contextWithFunctions = { ...context, ...customFunctions };
240
- return new Function(
241
- "context",
242
- "with (context) { return " + condition + "; }"
243
- )(contextWithFunctions);
353
+ const ctx = { ...context, ...customFunctions };
354
+ return new Function("context", `with (context) { return ${condition}; }`)(ctx);
244
355
  }
245
356
 
246
357
  export default fileIncludePlugin;