@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 +2 -0
- package/dist/cli.js +18 -3
- package/dist/index.js +40 -11
- package/package.json +1 -1
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
|
-
|
|
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
|
|
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
|
|
17
|
-
if (
|
|
18
|
-
vars.push({ path:
|
|
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
|
|
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
|
|
131
|
-
if (
|
|
132
|
-
|
|
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
|
-
|
|
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
|
|