@gregorlohaus/tdir 0.1.6 → 0.1.8

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 CHANGED
@@ -60,6 +60,7 @@ render("./output", {
60
60
  |---|---|
61
61
  | `<@if(context.x)>` | Conditional block — boolean check (must end with `<@endif>`) |
62
62
  | `<@if(eq(context.x,"value"))>` | Conditional block — string equality check |
63
+ | `<@if(neq(context.x,"value"))>` | Conditional block — string inequality check |
63
64
  | `<@elseif(context.y)>` | Else-if branch (same forms as `@if`) |
64
65
  | `<@else>` | Else branch |
65
66
  | `<@endif>` | End conditional block |
@@ -72,6 +73,7 @@ render("./output", {
72
73
  |---|---|
73
74
  | `<@if(context.x)>dirname` | Conditionally include directory/file (boolean check) |
74
75
  | `<@if(eq(context.x,"value"))>dirname` | Conditionally include by string equality |
76
+ | `<@if(neq(context.x,"value"))>dirname` | Conditionally include by string inequality |
75
77
  | `<@var(context.x)>` | Dynamic directory/file name |
76
78
 
77
79
  These can be combined: `<@if(context.web.create)><@var(context.web.dir)>` creates a directory named by `context.web.dir` only if `context.web.create` is true.
package/dist/cli.js CHANGED
@@ -199,6 +199,16 @@ function writeSkippedTemplate(templateRoot, skipped) {
199
199
  writeFileSync(templatePath, content);
200
200
  return 1;
201
201
  }
202
+ function replaceFlatTokens(content, manifest) {
203
+ const entries = Object.entries(manifest.tokens).filter(([, tokens]) => tokens.length > 0).sort(([a], [b]) => b.length - a.length);
204
+ let result = content;
205
+ for (const [rendered, tokens] of entries) {
206
+ if (rendered === "")
207
+ continue;
208
+ result = result.split(rendered).join(tokens[0]);
209
+ }
210
+ return result;
211
+ }
202
212
  function dirnamePath(path) {
203
213
  const normalized = normalizePath(path);
204
214
  const index = normalized.lastIndexOf("/");
@@ -271,13 +281,18 @@ function walkFiles(root, excludedRoots = []) {
271
281
  }
272
282
  return files;
273
283
  }
274
- function copyIncludedRenderedFiles(renderedRoot, templateRoot, includedOutputPaths, directoryMap) {
284
+ function copyIncludedRenderedFiles(renderedRoot, templateRoot, includedOutputPaths, directoryMap, manifest) {
275
285
  let filesWritten = 0;
276
286
  for (const outputPath of includedOutputPaths) {
277
287
  const renderedPath = resolveInside(renderedRoot, outputPath);
278
288
  const templatePath = resolveInside(templateRoot, inferTemplatePath(outputPath, directoryMap));
279
289
  mkdirSync(dirname(templatePath), { recursive: true });
280
- copyFileSync(renderedPath, templatePath);
290
+ const content = readFileSync(renderedPath);
291
+ if (isUtf8Text(content)) {
292
+ writeFileSync(templatePath, replaceFlatTokens(content.toString("utf-8"), manifest));
293
+ } else {
294
+ copyFileSync(renderedPath, templatePath);
295
+ }
281
296
  filesWritten += 1;
282
297
  }
283
298
  return filesWritten;
@@ -333,7 +348,7 @@ function reverseDir(renderedDir, templateDir, options = {}) {
333
348
  for (const skipped of manifest.skipped ?? []) {
334
349
  filesWritten += writeSkippedTemplate(templateRoot, skipped);
335
350
  }
336
- filesWritten += copyIncludedRenderedFiles(renderedRoot, templateRoot, includedOutputPaths, directoryMap);
351
+ filesWritten += copyIncludedRenderedFiles(renderedRoot, templateRoot, includedOutputPaths, directoryMap, manifest);
337
352
  return { filesWritten, warnings };
338
353
  }
339
354
 
package/dist/index.js CHANGED
@@ -8,14 +8,14 @@ import { TextDecoder } from "node:util";
8
8
  var IF_RE = /<@(?:if|elseif)\((.+?)\)>/g;
9
9
  var VAR_RE = /<@var\(context\.(.+?)(?::(\w+))?\)>/g;
10
10
  var DIRECTIVE_RE = /<@(if|elseif|else|endif)(?:\((.+?)\))?>/g;
11
- var EQ_RE = /^eq\(context\.(.+?),\s*"(.*)"\)$/;
11
+ var STRING_COMPARE_RE = /^(?:eq|neq)\(context\.(.+?),\s*"(.*)"\)$/;
12
12
  var PATH_RE = /^context\.(.+)$/;
13
13
  function extractCondition(expr, vars) {
14
14
  if (!expr)
15
15
  throw new Error("Missing condition expression");
16
- const eqMatch = expr.match(EQ_RE);
17
- if (eqMatch) {
18
- vars.push({ path: eqMatch[1], type: "string" });
16
+ const stringCompareMatch = expr.match(STRING_COMPARE_RE);
17
+ if (stringCompareMatch) {
18
+ vars.push({ path: stringCompareMatch[1], type: "string" });
19
19
  return;
20
20
  }
21
21
  const pathMatch = expr.match(PATH_RE);
@@ -122,14 +122,15 @@ import { TextDecoder as TextDecoder2 } from "node:util";
122
122
  var IF_PATH_RE = /^<@if\((.+?)\)>(.*)$/;
123
123
  var VAR_RE2 = /<@var\(context\.(.+?)(?::(\w+))?\)>/g;
124
124
  var DIRECTIVE_RE2 = /<@(if|elseif|else|endif)(?:\((.+?)\))?>/g;
125
- var EQ_RE2 = /^eq\(context\.(.+?),\s*"(.*)"\)$/;
125
+ var STRING_COMPARE_RE2 = /^(eq|neq)\(context\.(.+?),\s*"(.*)"\)$/;
126
126
  var PATH_RE2 = /^context\.(.+)$/;
127
127
  function evalCondition(expr, context) {
128
128
  if (!expr)
129
129
  throw new Error("Missing condition expression");
130
- const eqMatch = expr.match(EQ_RE2);
131
- if (eqMatch) {
132
- return resolveContext(context, eqMatch[1]) === eqMatch[2];
130
+ const stringCompareMatch = expr.match(STRING_COMPARE_RE2);
131
+ if (stringCompareMatch) {
132
+ const result = resolveContext(context, stringCompareMatch[2]) === stringCompareMatch[3];
133
+ return stringCompareMatch[1] === "eq" ? result : !result;
133
134
  }
134
135
  const pathMatch = expr.match(PATH_RE2);
135
136
  if (pathMatch) {
@@ -186,6 +187,14 @@ function addReverseMapToken(state, file, token) {
186
187
  tokens.push(token.token);
187
188
  state.manifest.tokens[token.result] = tokens;
188
189
  }
190
+ function addFlatToken(state, result, token) {
191
+ if (!state?.manifest)
192
+ return;
193
+ const tokens = state.manifest.tokens[result] ?? [];
194
+ if (!tokens.includes(token))
195
+ tokens.push(token);
196
+ state.manifest.tokens[result] = tokens;
197
+ }
189
198
  function getReverseMapPath(destRoot, reverseMap) {
190
199
  if (reverseMap === true)
191
200
  return resolveOutputPath(destRoot, ".tdir-map.json");
@@ -341,6 +350,11 @@ function processIfBlocksWithMap(content, context) {
341
350
  };
342
351
  }
343
352
  function renderContentWithMap(content, context, state, file) {
353
+ for (const match of content.matchAll(VAR_RE2)) {
354
+ const token = match[0];
355
+ const path = match[1];
356
+ addFlatToken(state, String(resolveContext(context, path) ?? ""), token);
357
+ }
344
358
  const processedResult = processIfBlocksWithMap(content, context);
345
359
  const processed = processedResult.content;
346
360
  for (const token of processedResult.conditionalTokens) {
@@ -685,6 +699,16 @@ function writeSkippedTemplate(templateRoot, skipped) {
685
699
  writeFileSync2(templatePath, content);
686
700
  return 1;
687
701
  }
702
+ function replaceFlatTokens(content, manifest) {
703
+ const entries = Object.entries(manifest.tokens).filter(([, tokens]) => tokens.length > 0).sort(([a], [b]) => b.length - a.length);
704
+ let result = content;
705
+ for (const [rendered, tokens] of entries) {
706
+ if (rendered === "")
707
+ continue;
708
+ result = result.split(rendered).join(tokens[0]);
709
+ }
710
+ return result;
711
+ }
688
712
  function dirnamePath(path) {
689
713
  const normalized = normalizePath(path);
690
714
  const index = normalized.lastIndexOf("/");
@@ -757,13 +781,18 @@ function walkFiles(root, excludedRoots = []) {
757
781
  }
758
782
  return files;
759
783
  }
760
- function copyIncludedRenderedFiles(renderedRoot, templateRoot, includedOutputPaths, directoryMap) {
784
+ function copyIncludedRenderedFiles(renderedRoot, templateRoot, includedOutputPaths, directoryMap, manifest) {
761
785
  let filesWritten = 0;
762
786
  for (const outputPath of includedOutputPaths) {
763
787
  const renderedPath = resolveInside(renderedRoot, outputPath);
764
788
  const templatePath = resolveInside(templateRoot, inferTemplatePath(outputPath, directoryMap));
765
789
  mkdirSync2(dirname2(templatePath), { recursive: true });
766
- copyFileSync2(renderedPath, templatePath);
790
+ const content = readFileSync3(renderedPath);
791
+ if (isUtf8Text3(content)) {
792
+ writeFileSync2(templatePath, replaceFlatTokens(content.toString("utf-8"), manifest));
793
+ } else {
794
+ copyFileSync2(renderedPath, templatePath);
795
+ }
767
796
  filesWritten += 1;
768
797
  }
769
798
  return filesWritten;
@@ -819,7 +848,7 @@ function reverseDir(renderedDir, templateDir, options = {}) {
819
848
  for (const skipped of manifest.skipped ?? []) {
820
849
  filesWritten += writeSkippedTemplate(templateRoot, skipped);
821
850
  }
822
- filesWritten += copyIncludedRenderedFiles(renderedRoot, templateRoot, includedOutputPaths, directoryMap);
851
+ filesWritten += copyIncludedRenderedFiles(renderedRoot, templateRoot, includedOutputPaths, directoryMap, manifest);
823
852
  return { filesWritten, warnings };
824
853
  }
825
854
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gregorlohaus/tdir",
3
- "version": "0.1.6",
3
+ "version": "0.1.8",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",