kist 0.1.31 → 0.1.32

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.
@@ -13,11 +13,13 @@ const FileRenameAction_1 = require("../actions/FileRenameAction");
13
13
  const JavaScriptMinifyAction_1 = require("../actions/JavaScriptMinifyAction");
14
14
  const LintAction_1 = require("../actions/LintAction");
15
15
  const PackageManagerAction_1 = require("../actions/PackageManagerAction");
16
+ const RunScriptAction_1 = require("../actions/RunScriptAction");
16
17
  const StyleProcessingAction_1 = require("../actions/StyleProcessingAction");
17
18
  const SvgPackagerAction_1 = require("../actions/SvgPackagerAction");
18
19
  const SvgReaderAction_1 = require("../actions/SvgReaderAction");
19
20
  const SvgSpriteAction_1 = require("../actions/SvgSpriteAction");
20
21
  const SvgToPngAction_1 = require("../actions/SvgToPngAction");
22
+ const TemplateRenderAction_1 = require("../actions/TemplateRenderAction");
21
23
  const TypeScriptCompilerAction_1 = require("../actions/TypeScriptCompilerAction");
22
24
  const VersionWriteAction_1 = require("../actions/VersionWriteAction");
23
25
  // ============================================================================
@@ -37,11 +39,13 @@ exports.coreActions = {
37
39
  [new JavaScriptMinifyAction_1.JavaScriptMinifyAction().name]: JavaScriptMinifyAction_1.JavaScriptMinifyAction,
38
40
  [new LintAction_1.LintAction().name]: LintAction_1.LintAction,
39
41
  [new PackageManagerAction_1.PackageManagerAction().name]: PackageManagerAction_1.PackageManagerAction,
42
+ [new RunScriptAction_1.RunScriptAction().name]: RunScriptAction_1.RunScriptAction,
40
43
  [new StyleProcessingAction_1.StyleProcessingAction().name]: StyleProcessingAction_1.StyleProcessingAction,
41
44
  [new SvgPackagerAction_1.SvgPackagerAction().name]: SvgPackagerAction_1.SvgPackagerAction,
42
45
  [new SvgReaderAction_1.SvgReaderAction().name]: SvgReaderAction_1.SvgReaderAction,
43
46
  [new SvgSpriteAction_1.SvgSpriteAction().name]: SvgSpriteAction_1.SvgSpriteAction,
44
47
  [new SvgToPngAction_1.SvgToPngAction().name]: SvgToPngAction_1.SvgToPngAction,
48
+ [new TemplateRenderAction_1.TemplateRenderAction().name]: TemplateRenderAction_1.TemplateRenderAction,
45
49
  [new TypeScriptCompilerAction_1.TypeScriptCompilerAction().name]: TypeScriptCompilerAction_1.TypeScriptCompilerAction,
46
50
  [new VersionWriteAction_1.VersionWriteAction().name]: VersionWriteAction_1.VersionWriteAction,
47
51
  };
@@ -0,0 +1,22 @@
1
+ import { Action } from "../../core/pipeline/Action";
2
+ import { ActionOptionsType } from "../../types/ActionOptionsType";
3
+ /**
4
+ * RunScriptAction executes an external JavaScript file as part of a KIST pipeline.
5
+ * The script is executed in a separate process to avoid blocking the main application.
6
+ */
7
+ export declare class RunScriptAction extends Action {
8
+ /**
9
+ * Executes the external script file.
10
+ *
11
+ * @param options - The options specifying the script file to execute.
12
+ * @returns A Promise that resolves when the script execution completes.
13
+ * @throws {Error} If the script execution fails.
14
+ */
15
+ execute(options: ActionOptionsType): Promise<void>;
16
+ /**
17
+ * Provides a description of the action.
18
+ *
19
+ * @returns A string description of the action.
20
+ */
21
+ describe(): string;
22
+ }
@@ -0,0 +1,77 @@
1
+ "use strict";
2
+ // ============================================================================
3
+ // Imports
4
+ // ============================================================================
5
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
6
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
7
+ return new (P || (P = Promise))(function (resolve, reject) {
8
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
9
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
10
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
11
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
12
+ });
13
+ };
14
+ var __importDefault = (this && this.__importDefault) || function (mod) {
15
+ return (mod && mod.__esModule) ? mod : { "default": mod };
16
+ };
17
+ Object.defineProperty(exports, "__esModule", { value: true });
18
+ exports.RunScriptAction = void 0;
19
+ const child_process_1 = require("child_process");
20
+ const path_1 = __importDefault(require("path"));
21
+ const util_1 = __importDefault(require("util"));
22
+ const Action_1 = require("../../core/pipeline/Action");
23
+ // ============================================================================
24
+ // Constants
25
+ // ============================================================================
26
+ const execFileAsync = util_1.default.promisify(child_process_1.execFile);
27
+ // ============================================================================
28
+ // Classes
29
+ // ============================================================================
30
+ /**
31
+ * RunScriptAction executes an external JavaScript file as part of a KIST pipeline.
32
+ * The script is executed in a separate process to avoid blocking the main application.
33
+ */
34
+ class RunScriptAction extends Action_1.Action {
35
+ /**
36
+ * Executes the external script file.
37
+ *
38
+ * @param options - The options specifying the script file to execute.
39
+ * @returns A Promise that resolves when the script execution completes.
40
+ * @throws {Error} If the script execution fails.
41
+ */
42
+ execute(options) {
43
+ return __awaiter(this, void 0, void 0, function* () {
44
+ const { scriptPath, args = [] } = options;
45
+ if (!scriptPath) {
46
+ throw new Error("Invalid options: 'scriptPath' is required.");
47
+ }
48
+ const resolvedScriptPath = path_1.default.resolve(scriptPath);
49
+ this.logInfo(`Executing external script: ${resolvedScriptPath}...`);
50
+ try {
51
+ const { stdout, stderr } = yield execFileAsync("node", [
52
+ resolvedScriptPath,
53
+ ...args,
54
+ ]);
55
+ if (stderr) {
56
+ this.logError(`Script execution failed: ${stderr}`);
57
+ throw new Error(stderr);
58
+ }
59
+ this.logInfo(stdout);
60
+ this.logInfo("Script executed successfully.");
61
+ }
62
+ catch (error) {
63
+ this.logError("Error occurred while executing the script.", error);
64
+ throw error;
65
+ }
66
+ });
67
+ }
68
+ /**
69
+ * Provides a description of the action.
70
+ *
71
+ * @returns A string description of the action.
72
+ */
73
+ describe() {
74
+ return "Executes an external JavaScript file as part of the KIST pipeline.";
75
+ }
76
+ }
77
+ exports.RunScriptAction = RunScriptAction;
@@ -0,0 +1,2 @@
1
+ import { RunScriptAction } from "./RunScriptAction";
2
+ export { RunScriptAction };
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ // ============================================================================
3
+ // Import
4
+ // ============================================================================
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.RunScriptAction = void 0;
7
+ const RunScriptAction_1 = require("./RunScriptAction");
8
+ Object.defineProperty(exports, "RunScriptAction", { enumerable: true, get: function () { return RunScriptAction_1.RunScriptAction; } });
@@ -0,0 +1,25 @@
1
+ import { Action } from "../../core/pipeline/Action";
2
+ import { ActionOptionsType } from "../../types/ActionOptionsType";
3
+ /**
4
+ * TemplateRenderAction is responsible for rendering and writing multiple files
5
+ * from Nunjucks templates in a single action. It allows batch generation of
6
+ * output files based on a shared template context.
7
+ */
8
+ export declare class TemplateRenderAction extends Action {
9
+ /**
10
+ * Executes the template rendering process for multiple templates.
11
+ *
12
+ * @param options - The options specifying the template directory,
13
+ * template-output mapping, and rendering context.
14
+ * @returns A Promise that resolves when all templates have been rendered.
15
+ * @throws {Error} Throws an error if template processing fails.
16
+ */
17
+ execute(options: ActionOptionsType): Promise<void>;
18
+ /**
19
+ * Provides a description of the action.
20
+ *
21
+ * @returns A string description of the action.
22
+ */
23
+ describe(): string;
24
+ }
25
+ export default TemplateRenderAction;
@@ -0,0 +1,91 @@
1
+ "use strict";
2
+ // ============================================================================
3
+ // Imports
4
+ // ============================================================================
5
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
6
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
7
+ return new (P || (P = Promise))(function (resolve, reject) {
8
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
9
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
10
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
11
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
12
+ });
13
+ };
14
+ var __importDefault = (this && this.__importDefault) || function (mod) {
15
+ return (mod && mod.__esModule) ? mod : { "default": mod };
16
+ };
17
+ Object.defineProperty(exports, "__esModule", { value: true });
18
+ exports.TemplateRenderAction = void 0;
19
+ const promises_1 = require("fs/promises");
20
+ const nunjucks_1 = __importDefault(require("nunjucks"));
21
+ const path_1 = __importDefault(require("path"));
22
+ const Action_1 = require("../../core/pipeline/Action");
23
+ const nunjucks_config_js_1 = __importDefault(require("./nunjucks.config.js"));
24
+ // ============================================================================
25
+ // Classes
26
+ // ============================================================================
27
+ /**
28
+ * TemplateRenderAction is responsible for rendering and writing multiple files
29
+ * from Nunjucks templates in a single action. It allows batch generation of
30
+ * output files based on a shared template context.
31
+ */
32
+ class TemplateRenderAction extends Action_1.Action {
33
+ /**
34
+ * Executes the template rendering process for multiple templates.
35
+ *
36
+ * @param options - The options specifying the template directory,
37
+ * template-output mapping, and rendering context.
38
+ * @returns A Promise that resolves when all templates have been rendered.
39
+ * @throws {Error} Throws an error if template processing fails.
40
+ */
41
+ execute(options) {
42
+ return __awaiter(this, void 0, void 0, function* () {
43
+ const { templatesDir = "./templates", templates = [], context = {}, customConfig = {}, } = options;
44
+ if (!Array.isArray(templates) || templates.length === 0) {
45
+ throw new Error("Invalid options: 'templates' must be an array containing template-output pairs.");
46
+ }
47
+ this.logInfo(`Rendering ${templates.length} templates...`);
48
+ try {
49
+ // Merge Nunjucks configurations
50
+ const config = Object.assign(Object.assign({}, nunjucks_config_js_1.default), customConfig);
51
+ nunjucks_1.default.configure(templatesDir, config);
52
+ // Render each template and save to its corresponding output path
53
+ for (const { template, outputFile } of templates) {
54
+ if (!template || !outputFile) {
55
+ throw new Error(`Invalid template entry: ${JSON.stringify({
56
+ template,
57
+ outputFile,
58
+ })}`);
59
+ }
60
+ this.logInfo(`Rendering: ${template} → ${outputFile}`);
61
+ // Render template content
62
+ const content = nunjucks_1.default.render(template, context);
63
+ // Ensure the output directory exists
64
+ const dir = path_1.default.dirname(outputFile);
65
+ yield (0, promises_1.mkdir)(dir, { recursive: true });
66
+ // Write the rendered template to file
67
+ yield (0, promises_1.writeFile)(outputFile, content, "utf-8");
68
+ this.logInfo(`✓ Successfully rendered: ${outputFile}`);
69
+ }
70
+ this.logInfo("All templates rendered successfully.");
71
+ }
72
+ catch (error) {
73
+ this.logError("Error rendering templates.", error);
74
+ throw error;
75
+ }
76
+ });
77
+ }
78
+ /**
79
+ * Provides a description of the action.
80
+ *
81
+ * @returns A string description of the action.
82
+ */
83
+ describe() {
84
+ return "Renders multiple Nunjucks templates into files using a shared context.";
85
+ }
86
+ }
87
+ exports.TemplateRenderAction = TemplateRenderAction;
88
+ // ============================================================================
89
+ // Export
90
+ // ============================================================================
91
+ exports.default = TemplateRenderAction;
@@ -0,0 +1,2 @@
1
+ import { TemplateRenderAction } from "./TemplateRenderAction";
2
+ export { TemplateRenderAction };
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ // ============================================================================
3
+ // Import
4
+ // ============================================================================
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.TemplateRenderAction = void 0;
7
+ const TemplateRenderAction_1 = require("./TemplateRenderAction");
8
+ Object.defineProperty(exports, "TemplateRenderAction", { enumerable: true, get: function () { return TemplateRenderAction_1.TemplateRenderAction; } });
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Configuration options for Nunjucks to ensure safe and efficient template rendering.
3
+ * This setup is ideal for both development and production environments, providing a balance
4
+ * between performance optimizations and security best practices.
5
+ */
6
+ declare const nunjucksConfig: {
7
+ autoescape: boolean;
8
+ throwOnUndefined: boolean;
9
+ trimBlocks: boolean;
10
+ lstripBlocks: boolean;
11
+ noCache: boolean;
12
+ };
13
+ export default nunjucksConfig;
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ // This configuration is tailored to a typical web application setup. Adjust the `noCache` option
3
+ // according to your caching strategy for production environments to optimize performance.
4
+ Object.defineProperty(exports, "__esModule", { value: true });
5
+ // ============================================================================
6
+ // Constants
7
+ // ============================================================================
8
+ /**
9
+ * Configuration options for Nunjucks to ensure safe and efficient template rendering.
10
+ * This setup is ideal for both development and production environments, providing a balance
11
+ * between performance optimizations and security best practices.
12
+ */
13
+ const nunjucksConfig = {
14
+ autoescape: true, // Controls if output with dangerous characters are escaped automatically
15
+ throwOnUndefined: false, // Throw errors when outputting a null/undefined value
16
+ trimBlocks: true, // Automatically remove trailing newlines from a block/tag
17
+ lstripBlocks: true, // Automatically remove leading whitespace from a block/tag
18
+ noCache: true,
19
+ };
20
+ // ============================================================================
21
+ // Export
22
+ // ============================================================================
23
+ exports.default = nunjucksConfig;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kist",
3
- "version": "0.1.31",
3
+ "version": "0.1.32",
4
4
  "description": "Package Pipeline Processor",
5
5
  "keywords": [
6
6
  "kist",
@@ -15,6 +15,7 @@ import { JavaScriptMinifyAction } from "../actions/JavaScriptMinifyAction";
15
15
  import { LintAction } from "../actions/LintAction";
16
16
 
17
17
  import { PackageManagerAction } from "../actions/PackageManagerAction";
18
+ import { RunScriptAction } from "../actions/RunScriptAction";
18
19
 
19
20
  import { StyleProcessingAction } from "../actions/StyleProcessingAction";
20
21
 
@@ -23,6 +24,7 @@ import { SvgReaderAction } from "../actions/SvgReaderAction";
23
24
  import { SvgSpriteAction } from "../actions/SvgSpriteAction";
24
25
  import { SvgToPngAction } from "../actions/SvgToPngAction";
25
26
 
27
+ import { TemplateRenderAction } from "../actions/TemplateRenderAction";
26
28
  import { TypeScriptCompilerAction } from "../actions/TypeScriptCompilerAction";
27
29
 
28
30
  import { VersionWriteAction } from "../actions/VersionWriteAction";
@@ -51,6 +53,7 @@ export const coreActions: Record<string, new () => ActionInterface> = {
51
53
  [new LintAction().name]: LintAction,
52
54
 
53
55
  [new PackageManagerAction().name]: PackageManagerAction,
56
+ [new RunScriptAction().name]: RunScriptAction,
54
57
  [new StyleProcessingAction().name]: StyleProcessingAction,
55
58
 
56
59
  [new SvgPackagerAction().name]: SvgPackagerAction,
@@ -58,6 +61,7 @@ export const coreActions: Record<string, new () => ActionInterface> = {
58
61
  [new SvgSpriteAction().name]: SvgSpriteAction,
59
62
  [new SvgToPngAction().name]: SvgToPngAction,
60
63
 
64
+ [new TemplateRenderAction().name]: TemplateRenderAction,
61
65
  [new TypeScriptCompilerAction().name]: TypeScriptCompilerAction,
62
66
 
63
67
  [new VersionWriteAction().name]: VersionWriteAction,
@@ -0,0 +1,71 @@
1
+ // ============================================================================
2
+ // Imports
3
+ // ============================================================================
4
+
5
+ import { execFile } from "child_process";
6
+ import path from "path";
7
+ import util from "util";
8
+ import { Action } from "../../core/pipeline/Action";
9
+ import { ActionOptionsType } from "../../types/ActionOptionsType";
10
+
11
+ // ============================================================================
12
+ // Constants
13
+ // ============================================================================
14
+
15
+ const execFileAsync = util.promisify(execFile);
16
+
17
+ // ============================================================================
18
+ // Classes
19
+ // ============================================================================
20
+
21
+ /**
22
+ * RunScriptAction executes an external JavaScript file as part of a KIST pipeline.
23
+ * The script is executed in a separate process to avoid blocking the main application.
24
+ */
25
+ export class RunScriptAction extends Action {
26
+ /**
27
+ * Executes the external script file.
28
+ *
29
+ * @param options - The options specifying the script file to execute.
30
+ * @returns A Promise that resolves when the script execution completes.
31
+ * @throws {Error} If the script execution fails.
32
+ */
33
+ async execute(options: ActionOptionsType): Promise<void> {
34
+ const { scriptPath, args = [] } = options;
35
+
36
+ if (!scriptPath) {
37
+ throw new Error("Invalid options: 'scriptPath' is required.");
38
+ }
39
+
40
+ const resolvedScriptPath = path.resolve(scriptPath);
41
+
42
+ this.logInfo(`Executing external script: ${resolvedScriptPath}...`);
43
+
44
+ try {
45
+ const { stdout, stderr } = await execFileAsync("node", [
46
+ resolvedScriptPath,
47
+ ...args,
48
+ ]);
49
+
50
+ if (stderr) {
51
+ this.logError(`Script execution failed: ${stderr}`);
52
+ throw new Error(stderr);
53
+ }
54
+
55
+ this.logInfo(stdout);
56
+ this.logInfo("Script executed successfully.");
57
+ } catch (error) {
58
+ this.logError("Error occurred while executing the script.", error);
59
+ throw error;
60
+ }
61
+ }
62
+
63
+ /**
64
+ * Provides a description of the action.
65
+ *
66
+ * @returns A string description of the action.
67
+ */
68
+ describe(): string {
69
+ return "Executes an external JavaScript file as part of the KIST pipeline.";
70
+ }
71
+ }
@@ -0,0 +1,11 @@
1
+ // ============================================================================
2
+ // Import
3
+ // ============================================================================
4
+
5
+ import { RunScriptAction } from "./RunScriptAction";
6
+
7
+ // ============================================================================
8
+ // Export
9
+ // ============================================================================
10
+
11
+ export { RunScriptAction };
@@ -0,0 +1,98 @@
1
+ // ============================================================================
2
+ // Imports
3
+ // ============================================================================
4
+
5
+ import { mkdir, writeFile } from "fs/promises";
6
+ import nunjucks from "nunjucks";
7
+ import path from "path";
8
+ import { Action } from "../../core/pipeline/Action";
9
+ import { ActionOptionsType } from "../../types/ActionOptionsType";
10
+ import nunjucksConfig from "./nunjucks.config.js";
11
+
12
+ // ============================================================================
13
+ // Classes
14
+ // ============================================================================
15
+
16
+ /**
17
+ * TemplateRenderAction is responsible for rendering and writing multiple files
18
+ * from Nunjucks templates in a single action. It allows batch generation of
19
+ * output files based on a shared template context.
20
+ */
21
+ export class TemplateRenderAction extends Action {
22
+ /**
23
+ * Executes the template rendering process for multiple templates.
24
+ *
25
+ * @param options - The options specifying the template directory,
26
+ * template-output mapping, and rendering context.
27
+ * @returns A Promise that resolves when all templates have been rendered.
28
+ * @throws {Error} Throws an error if template processing fails.
29
+ */
30
+ async execute(options: ActionOptionsType): Promise<void> {
31
+ const {
32
+ templatesDir = "./templates",
33
+ templates = [],
34
+ context = {},
35
+ customConfig = {},
36
+ } = options;
37
+
38
+ if (!Array.isArray(templates) || templates.length === 0) {
39
+ throw new Error(
40
+ "Invalid options: 'templates' must be an array containing template-output pairs."
41
+ );
42
+ }
43
+
44
+ this.logInfo(`Rendering ${templates.length} templates...`);
45
+
46
+ try {
47
+ // Merge Nunjucks configurations
48
+ const config = { ...nunjucksConfig, ...customConfig };
49
+ nunjucks.configure(templatesDir, config);
50
+
51
+ // Render each template and save to its corresponding output path
52
+ for (const { template, outputFile } of templates) {
53
+ if (!template || !outputFile) {
54
+ throw new Error(
55
+ `Invalid template entry: ${JSON.stringify({
56
+ template,
57
+ outputFile,
58
+ })}`
59
+ );
60
+ }
61
+
62
+ this.logInfo(`Rendering: ${template} → ${outputFile}`);
63
+
64
+ // Render template content
65
+ const content = nunjucks.render(template, context);
66
+
67
+ // Ensure the output directory exists
68
+ const dir = path.dirname(outputFile);
69
+ await mkdir(dir, { recursive: true });
70
+
71
+ // Write the rendered template to file
72
+ await writeFile(outputFile, content, "utf-8");
73
+
74
+ this.logInfo(`✓ Successfully rendered: ${outputFile}`);
75
+ }
76
+
77
+ this.logInfo("All templates rendered successfully.");
78
+ } catch (error) {
79
+ this.logError("Error rendering templates.", error);
80
+ throw error;
81
+ }
82
+ }
83
+
84
+ /**
85
+ * Provides a description of the action.
86
+ *
87
+ * @returns A string description of the action.
88
+ */
89
+ describe(): string {
90
+ return "Renders multiple Nunjucks templates into files using a shared context.";
91
+ }
92
+ }
93
+
94
+ // ============================================================================
95
+ // Export
96
+ // ============================================================================
97
+
98
+ export default TemplateRenderAction;
@@ -0,0 +1,11 @@
1
+ // ============================================================================
2
+ // Import
3
+ // ============================================================================
4
+
5
+ import { TemplateRenderAction } from "./TemplateRenderAction";
6
+
7
+ // ============================================================================
8
+ // Export
9
+ // ============================================================================
10
+
11
+ export { TemplateRenderAction };
@@ -0,0 +1,32 @@
1
+ // This configuration is tailored to a typical web application setup. Adjust the `noCache` option
2
+ // according to your caching strategy for production environments to optimize performance.
3
+
4
+ // ============================================================================
5
+ // Import
6
+ // ============================================================================
7
+
8
+ // Importing path for potential future use in specifying template directories or other file paths
9
+ import path from "node:path";
10
+
11
+ // ============================================================================
12
+ // Constants
13
+ // ============================================================================
14
+
15
+ /**
16
+ * Configuration options for Nunjucks to ensure safe and efficient template rendering.
17
+ * This setup is ideal for both development and production environments, providing a balance
18
+ * between performance optimizations and security best practices.
19
+ */
20
+ const nunjucksConfig = {
21
+ autoescape: true, // Controls if output with dangerous characters are escaped automatically
22
+ throwOnUndefined: false, // Throw errors when outputting a null/undefined value
23
+ trimBlocks: true, // Automatically remove trailing newlines from a block/tag
24
+ lstripBlocks: true, // Automatically remove leading whitespace from a block/tag
25
+ noCache: true,
26
+ };
27
+
28
+ // ============================================================================
29
+ // Export
30
+ // ============================================================================
31
+
32
+ export default nunjucksConfig;