@podosoft/podokit-template-engine 0.1.0 → 0.2.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.
package/README.md ADDED
@@ -0,0 +1,46 @@
1
+ # @podosoft/podokit-template-engine
2
+
3
+ Template utilities used by the [PodoKit](https://github.com/podosoft-dev/podokit) CLI: token rendering, recursive template copying, and `package.json` merging.
4
+
5
+ > This package is primarily an internal building block for `@podosoft/podokit`. It is published so the CLI is installable from the registry, but the API is small and reusable on its own.
6
+
7
+ ## Install
8
+
9
+ ```bash
10
+ npm install @podosoft/podokit-template-engine
11
+ ```
12
+
13
+ ## API
14
+
15
+ ```ts
16
+ import {
17
+ renderTokens,
18
+ copyTemplate,
19
+ mergePackageJson,
20
+ resolveOutputName,
21
+ } from "@podosoft/podokit-template-engine";
22
+ ```
23
+
24
+ ### `renderTokens(content, vars)`
25
+
26
+ Replace `{{key}}` tokens with values from `vars`. Unknown tokens are left untouched.
27
+
28
+ ```ts
29
+ renderTokens("# {{name}}", { name: "my-app" }); // "# my-app"
30
+ ```
31
+
32
+ ### `copyTemplate(srcDir, destDir, vars)`
33
+
34
+ Recursively copy a template directory, rendering tokens in text files. Files named `dot-<x>` are written as `.<x>` (so `dot-gitignore` → `.gitignore`), which lets templates ship files that npm would otherwise strip.
35
+
36
+ ### `mergePackageJson(base, overlay)`
37
+
38
+ Deep-merge two `package.json`-shaped objects: objects merge recursively, arrays concatenate and de-duplicate, and scalar overlay values win. Neither input is mutated.
39
+
40
+ ### `resolveOutputName(name)`
41
+
42
+ Map a template file name to its output name (applies the `dot-` convention).
43
+
44
+ ## License
45
+
46
+ [Apache-2.0](https://github.com/podosoft-dev/podokit/blob/main/LICENSE)
package/dist/index.d.ts CHANGED
@@ -19,6 +19,13 @@ export declare function resolveOutputName(name: string): string;
19
19
  * as needed. Binary files are copied verbatim.
20
20
  */
21
21
  export declare function copyTemplate(srcDir: string, destDir: string, vars: TemplateVars): void;
22
+ /**
23
+ * Insert `text` on its own line immediately after the first line containing
24
+ * `marker`, preserving the marker line and its indentation. No-op if `text`
25
+ * is already present (so re-applying a module is idempotent). Throws if the
26
+ * marker is not found.
27
+ */
28
+ export declare function insertAtMarker(content: string, marker: string, text: string): string;
22
29
  /**
23
30
  * Deep-merge `overlay` onto `base`. Objects merge recursively, arrays are
24
31
  * concatenated and de-duplicated, and scalar overlay values win. Neither input
package/dist/index.js CHANGED
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.renderTokens = renderTokens;
4
4
  exports.resolveOutputName = resolveOutputName;
5
5
  exports.copyTemplate = copyTemplate;
6
+ exports.insertAtMarker = insertAtMarker;
6
7
  exports.mergePackageJson = mergePackageJson;
7
8
  const node_fs_1 = require("node:fs");
8
9
  const node_path_1 = require("node:path");
@@ -52,6 +53,25 @@ function copyTemplate(srcDir, destDir, vars) {
52
53
  }
53
54
  }
54
55
  }
56
+ /**
57
+ * Insert `text` on its own line immediately after the first line containing
58
+ * `marker`, preserving the marker line and its indentation. No-op if `text`
59
+ * is already present (so re-applying a module is idempotent). Throws if the
60
+ * marker is not found.
61
+ */
62
+ function insertAtMarker(content, marker, text) {
63
+ if (content.includes(text)) {
64
+ return content;
65
+ }
66
+ const lines = content.split("\n");
67
+ const index = lines.findIndex((line) => line.includes(marker));
68
+ if (index === -1) {
69
+ throw new Error(`Marker not found: ${marker}`);
70
+ }
71
+ const indent = lines[index].match(/^\s*/)?.[0] ?? "";
72
+ lines.splice(index, 0, `${indent}${text}`);
73
+ return lines.join("\n");
74
+ }
55
75
  function isPlainObject(value) {
56
76
  return typeof value === "object" && value !== null && !Array.isArray(value);
57
77
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@podosoft/podokit-template-engine",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "Template rendering, copying, and package.json merge utilities for PodoKit.",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -10,7 +10,9 @@
10
10
  },
11
11
  "main": "dist/index.js",
12
12
  "types": "dist/index.d.ts",
13
- "files": ["dist"],
13
+ "files": [
14
+ "dist"
15
+ ],
14
16
  "engines": {
15
17
  "node": ">=20"
16
18
  },