@unrdf/kgn 5.0.1
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/LICENSE +21 -0
- package/README.md +210 -0
- package/package.json +90 -0
- package/src/MIGRATION_COMPLETE.md +186 -0
- package/src/PORT-MAP.md +302 -0
- package/src/base/filter-templates.js +479 -0
- package/src/base/index.js +92 -0
- package/src/base/injection-targets.js +583 -0
- package/src/base/macro-templates.js +298 -0
- package/src/base/macro-templates.js.bak +461 -0
- package/src/base/shacl-templates.js +617 -0
- package/src/base/template-base.js +388 -0
- package/src/core/attestor.js +381 -0
- package/src/core/filters.js +518 -0
- package/src/core/index.js +21 -0
- package/src/core/kgen-engine.js +372 -0
- package/src/core/parser.js +447 -0
- package/src/core/post-processor.js +313 -0
- package/src/core/renderer.js +469 -0
- package/src/doc-generator/cli.mjs +122 -0
- package/src/doc-generator/index.mjs +28 -0
- package/src/doc-generator/mdx-generator.mjs +71 -0
- package/src/doc-generator/nav-generator.mjs +136 -0
- package/src/doc-generator/parser.mjs +291 -0
- package/src/doc-generator/rdf-builder.mjs +306 -0
- package/src/doc-generator/scanner.mjs +189 -0
- package/src/engine/index.js +42 -0
- package/src/engine/pipeline.js +448 -0
- package/src/engine/renderer.js +604 -0
- package/src/engine/template-engine.js +566 -0
- package/src/filters/array.js +436 -0
- package/src/filters/data.js +479 -0
- package/src/filters/index.js +270 -0
- package/src/filters/rdf.js +264 -0
- package/src/filters/text.js +369 -0
- package/src/index.js +109 -0
- package/src/inheritance/index.js +40 -0
- package/src/injection/api.js +260 -0
- package/src/injection/atomic-writer.js +327 -0
- package/src/injection/constants.js +136 -0
- package/src/injection/idempotency-manager.js +295 -0
- package/src/injection/index.js +28 -0
- package/src/injection/injection-engine.js +378 -0
- package/src/injection/integration.js +339 -0
- package/src/injection/modes/index.js +341 -0
- package/src/injection/rollback-manager.js +373 -0
- package/src/injection/target-resolver.js +323 -0
- package/src/injection/tests/atomic-writer.test.js +382 -0
- package/src/injection/tests/injection-engine.test.js +611 -0
- package/src/injection/tests/integration.test.js +392 -0
- package/src/injection/tests/run-tests.js +283 -0
- package/src/injection/validation-engine.js +547 -0
- package/src/linter/determinism-linter.js +473 -0
- package/src/linter/determinism.js +410 -0
- package/src/linter/index.js +6 -0
- package/src/linter/test-doubles.js +475 -0
- package/src/parser/frontmatter.js +228 -0
- package/src/parser/variables.js +344 -0
- package/src/renderer/deterministic.js +245 -0
- package/src/renderer/index.js +6 -0
- package/src/templates/latex/academic-paper.njk +186 -0
- package/src/templates/latex/index.js +104 -0
- package/src/templates/nextjs/app-page.njk +66 -0
- package/src/templates/nextjs/index.js +80 -0
- package/src/templates/office/docx/document.njk +368 -0
- package/src/templates/office/index.js +79 -0
- package/src/templates/office/word-report.njk +129 -0
- package/src/utils/template-utils.js +426 -0
|
@@ -0,0 +1,461 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* KGEN Macro Templates - Reusable template components
|
|
3
|
+
*
|
|
4
|
+
* Provides a library of pre-built macros for common template patterns
|
|
5
|
+
* All macros are deterministic and compatible with KGEN template engine
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export class KGenMacroTemplates {
|
|
9
|
+
constructor(options = {}) {
|
|
10
|
+
this.options = {
|
|
11
|
+
deterministicMode: options.deterministicMode !== false,
|
|
12
|
+
staticBuildTime: options.staticBuildTime || '2024-01-01T00:00:00.000Z',
|
|
13
|
+
namespace: options.namespace || 'kgen',
|
|
14
|
+
...options
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
this.macros = new Map();
|
|
18
|
+
this.initializeMacros();
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Initialize built-in macro templates
|
|
23
|
+
*/
|
|
24
|
+
initializeMacros() {
|
|
25
|
+
// Document structure macros
|
|
26
|
+
this.registerMacro('document_header', `{%- macro document_header(title, author, version='1.0.0') -%}
|
|
27
|
+
/**
|
|
28
|
+
* {{ title }}
|
|
29
|
+
*
|
|
30
|
+
* @author {{ author | default('KGEN Generator') }}
|
|
31
|
+
* @version {{ version }}
|
|
32
|
+
* @generated {{ __kgen.renderTime }}
|
|
33
|
+
* @hash {{ (title + author + version) | hash | shortHash(8) }}
|
|
34
|
+
*/
|
|
35
|
+
{%- endmacro -%}`);
|
|
36
|
+
|
|
37
|
+
this.registerMacro('code_block', `{%- macro code_block(content, language='javascript', indent=0) -%}
|
|
38
|
+
{%- set indentStr = ' '.repeat(indent) -%}
|
|
39
|
+
{{ indentStr }}\`\`\`{{ language }}
|
|
40
|
+
{%- for line in content.split('\n') %}
|
|
41
|
+
{{ indentStr }}{{ line }}
|
|
42
|
+
{%- endfor %}
|
|
43
|
+
{{ indentStr }}\`\`\`
|
|
44
|
+
{%- endmacro -%}`);
|
|
45
|
+
|
|
46
|
+
this.registerMacro('json_schema', `{%- macro json_schema(schema, indent=2) -%}
|
|
47
|
+
{%- set indentStr = ' '.repeat(indent) -%}
|
|
48
|
+
{{ indentStr }}{{
|
|
49
|
+
{%- for key, value in schema.items() %}
|
|
50
|
+
{{ indentStr }} "{{ key }}": {{ value | json }}{%- if not loop.last %},{% endif %}
|
|
51
|
+
{%- endfor %}
|
|
52
|
+
{{ indentStr }}}
|
|
53
|
+
{%- endmacro -%}`);
|
|
54
|
+
|
|
55
|
+
// HTML/Web macros
|
|
56
|
+
this.registerMacro('html_form', `{%- macro html_form(fields, action='#', method='POST', cssClass='kgen-form') -%}
|
|
57
|
+
<form action="{{ action }}" method="{{ method }}" class="{{ cssClass }}">
|
|
58
|
+
{%- for field in fields %}
|
|
59
|
+
<div class="form-group">
|
|
60
|
+
{%- if field.label %}
|
|
61
|
+
<label for="{{ field.name }}">{{ field.label }}</label>
|
|
62
|
+
{%- endif %}
|
|
63
|
+
<input
|
|
64
|
+
type="{{ field.type | default('text') }}"
|
|
65
|
+
name="{{ field.name }}"
|
|
66
|
+
id="{{ field.name }}"
|
|
67
|
+
{%- if field.required %} required{% endif %}
|
|
68
|
+
{%- if field.placeholder %} placeholder="{{ field.placeholder }}"{% endif %}
|
|
69
|
+
{%- if field.value %} value="{{ field.value }}"{% endif %}
|
|
70
|
+
class="form-control"
|
|
71
|
+
>
|
|
72
|
+
</div>
|
|
73
|
+
{%- endfor %}
|
|
74
|
+
<button type="submit" class="btn btn-primary">Submit</button>
|
|
75
|
+
</form>
|
|
76
|
+
{%- endmacro -%}`);
|
|
77
|
+
|
|
78
|
+
this.registerMacro('html_table', `{%- macro html_table(data, headers=[], cssClass='kgen-table') -%}
|
|
79
|
+
<table class="{{ cssClass }}">
|
|
80
|
+
{%- if headers | length > 0 %}
|
|
81
|
+
<thead>
|
|
82
|
+
<tr>
|
|
83
|
+
{%- for header in headers %}
|
|
84
|
+
<th>{{ header }}</th>
|
|
85
|
+
{%- endfor %}
|
|
86
|
+
</tr>
|
|
87
|
+
</thead>
|
|
88
|
+
{%- endif %}
|
|
89
|
+
<tbody>
|
|
90
|
+
{%- for row in data %}
|
|
91
|
+
<tr>
|
|
92
|
+
{%- if row is mapping %}
|
|
93
|
+
{%- for key in (headers if headers else row.keys()) %}
|
|
94
|
+
<td>{{ row[key] | default('') }}</td>
|
|
95
|
+
{%- endfor %}
|
|
96
|
+
{%- else %}
|
|
97
|
+
{%- for cell in row %}
|
|
98
|
+
<td>{{ cell }}</td>
|
|
99
|
+
{%- endfor %}
|
|
100
|
+
{%- endif %}
|
|
101
|
+
</tr>
|
|
102
|
+
{%- endfor %}
|
|
103
|
+
</tbody>
|
|
104
|
+
</table>
|
|
105
|
+
{%- endmacro -%}`);
|
|
106
|
+
|
|
107
|
+
// Code generation macros
|
|
108
|
+
this.registerMacro('js_class', `{%- macro js_class(className, methods=[], imports=[], exports=true) -%}
|
|
109
|
+
{%- if imports | length > 0 %}
|
|
110
|
+
{%- for import in imports %}
|
|
111
|
+
import {{ import.name }}{{ import.from ? ' from \'' + import.from + '\'' : '' }};
|
|
112
|
+
{%- endfor %}
|
|
113
|
+
|
|
114
|
+
{%- endif %}
|
|
115
|
+
{%- if exports %}export {% endif %}class {{ className }} {
|
|
116
|
+
constructor(options = {}) {
|
|
117
|
+
this.options = { ...options };
|
|
118
|
+
}
|
|
119
|
+
{%- for method in methods %}
|
|
120
|
+
|
|
121
|
+
{{ method.name }}({{ method.params | default('') }}) {
|
|
122
|
+
{{ method.body | default('// Method implementation') | indent(4) }}
|
|
123
|
+
}
|
|
124
|
+
{%- endfor %}
|
|
125
|
+
}
|
|
126
|
+
{%- if exports %}
|
|
127
|
+
|
|
128
|
+
export default {{ className }};
|
|
129
|
+
{%- endif %}
|
|
130
|
+
{%- endmacro -%}`);
|
|
131
|
+
|
|
132
|
+
this.registerMacro('js_function', `{%- macro js_function(name, params=[], body='', isAsync=false, isExport=false) -%}
|
|
133
|
+
{%- if isExport %}export {% endif %}{%- if isAsync %}async {% endif %}function {{ name }}({{ params | join(', ') }}) {
|
|
134
|
+
{{ body | indent(2) }}
|
|
135
|
+
}
|
|
136
|
+
{%- endmacro -%}`);
|
|
137
|
+
|
|
138
|
+
this.registerMacro('js_module', `{%- macro js_module(name, description='', imports=[], exports=[], constants=[]) -%}
|
|
139
|
+
/**
|
|
140
|
+
* {{ name }}
|
|
141
|
+
* {%- if description %}
|
|
142
|
+
* {{ description }}
|
|
143
|
+
* {%- endif %}
|
|
144
|
+
*
|
|
145
|
+
* @generated {{ __kgen.renderTime }}
|
|
146
|
+
*/
|
|
147
|
+
|
|
148
|
+
{%- if imports | length > 0 %}
|
|
149
|
+
{%- for import in imports %}
|
|
150
|
+
import {{ import.name }}{{ import.from ? ' from \'' + import.from + '\'' : '' }};
|
|
151
|
+
{%- endfor %}
|
|
152
|
+
|
|
153
|
+
{%- endif %}
|
|
154
|
+
{%- if constants | length > 0 %}
|
|
155
|
+
{%- for constant in constants %}
|
|
156
|
+
const {{ constant.name }} = {{ constant.value | json }};
|
|
157
|
+
{%- endfor %}
|
|
158
|
+
|
|
159
|
+
{%- endif %}
|
|
160
|
+
// Module content goes here
|
|
161
|
+
|
|
162
|
+
{%- if exports | length > 0 %}
|
|
163
|
+
// Exports
|
|
164
|
+
{%- for export in exports %}
|
|
165
|
+
export {{ export.type | default('') }} {{ export.name }}{{ export.value ? ' = ' + export.value : '' }};
|
|
166
|
+
{%- endfor %}
|
|
167
|
+
{%- endif %}
|
|
168
|
+
{%- endmacro -%}`);
|
|
169
|
+
|
|
170
|
+
// Configuration macros
|
|
171
|
+
this.registerMacro('config_json', `{%- macro config_json(config, indent=2) -%}
|
|
172
|
+
{
|
|
173
|
+
{%- for key, value in config.items() %}
|
|
174
|
+
{{ ' '.repeat(indent) }}"{{ key }}": {{ value | json }}{%- if not loop.last %},{% endif %}
|
|
175
|
+
{%- endfor %}
|
|
176
|
+
}
|
|
177
|
+
{%- endmacro -%}`);
|
|
178
|
+
|
|
179
|
+
this.registerMacro('env_file', `{%- macro env_file(vars) -%}
|
|
180
|
+
# Environment Configuration
|
|
181
|
+
# Generated {{ __kgen.renderTime }}
|
|
182
|
+
|
|
183
|
+
{%- for key, value in vars.items() %}
|
|
184
|
+
{{ key }}={{ value }}
|
|
185
|
+
{%- endfor %}
|
|
186
|
+
{%- endmacro -%}`);
|
|
187
|
+
|
|
188
|
+
// Documentation macros
|
|
189
|
+
this.registerMacro('api_doc', `{%- macro api_doc(endpoint, method='GET', params=[], responses=[]) -%}
|
|
190
|
+
## {{ method.upper() }} {{ endpoint }}
|
|
191
|
+
|
|
192
|
+
{%- if params | length > 0 %}
|
|
193
|
+
### Parameters
|
|
194
|
+
|
|
195
|
+
| Name | Type | Required | Description |
|
|
196
|
+
|------|------|----------|-------------|
|
|
197
|
+
{%- for param in params %}
|
|
198
|
+
| {{ param.name }} | {{ param.type | default('string') }} | {{ 'Yes' if param.required else 'No' }} | {{ param.description | default('') }} |
|
|
199
|
+
{%- endfor %}
|
|
200
|
+
{%- endif %}
|
|
201
|
+
|
|
202
|
+
{%- if responses | length > 0 %}
|
|
203
|
+
### Responses
|
|
204
|
+
|
|
205
|
+
{%- for response in responses %}
|
|
206
|
+
#### {{ response.code }} - {{ response.description }}
|
|
207
|
+
|
|
208
|
+
{%- if response.schema %}
|
|
209
|
+
```json
|
|
210
|
+
{{ response.schema | json(2) }}
|
|
211
|
+
```
|
|
212
|
+
{%- endif %}
|
|
213
|
+
{%- endfor %}
|
|
214
|
+
{%- endif %}
|
|
215
|
+
{%- endmacro -%}`);
|
|
216
|
+
|
|
217
|
+
this.registerMacro('readme_section', `{%- macro readme_section(title, content, level=2) -%}
|
|
218
|
+
{{ '#'.repeat(level) }} {{ title }}
|
|
219
|
+
|
|
220
|
+
{{ content }}
|
|
221
|
+
{%- endmacro -%}`);
|
|
222
|
+
|
|
223
|
+
// Testing macros
|
|
224
|
+
this.registerMacro('test_suite', `{%- macro test_suite(name, tests=[], setup='', teardown='') -%}
|
|
225
|
+
describe('{{ name }}', () => {
|
|
226
|
+
{%- if setup %}
|
|
227
|
+
beforeEach(() => {
|
|
228
|
+
{{ setup | indent(4) }}
|
|
229
|
+
});
|
|
230
|
+
{%- endif %}
|
|
231
|
+
|
|
232
|
+
{%- for test in tests %}
|
|
233
|
+
it('{{ test.description }}', {{ 'async ' if test.async }}() => {
|
|
234
|
+
{{ test.body | indent(4) }}
|
|
235
|
+
});
|
|
236
|
+
{%- endfor %}
|
|
237
|
+
|
|
238
|
+
{%- if teardown %}
|
|
239
|
+
afterEach(() => {
|
|
240
|
+
{{ teardown | indent(4) }}
|
|
241
|
+
});
|
|
242
|
+
{%- endif %}
|
|
243
|
+
});
|
|
244
|
+
{%- endmacro -%}`);
|
|
245
|
+
|
|
246
|
+
// Utility macros
|
|
247
|
+
this.registerMacro('copyright_notice', `{%- macro copyright_notice(year, holder, license='MIT') -%}
|
|
248
|
+
/**
|
|
249
|
+
* Copyright (c) {{ year }} {{ holder }}
|
|
250
|
+
*
|
|
251
|
+
* Licensed under the {{ license }} License
|
|
252
|
+
* Generated by KGEN {{ __kgen.renderTime }}
|
|
253
|
+
*/
|
|
254
|
+
{%- endmacro -%}`);
|
|
255
|
+
|
|
256
|
+
this.registerMacro('todo_comment', `{%- macro todo_comment(description, priority='NORMAL', assignee='') -%}
|
|
257
|
+
// TODO{{ '(' + priority + ')' if priority != 'NORMAL' }}{{ ': @' + assignee if assignee }}: {{ description }}
|
|
258
|
+
{%- endmacro -%}`);
|
|
259
|
+
|
|
260
|
+
this.registerMacro('version_info', `{%- macro version_info(version, date, changes=[]) -%}
|
|
261
|
+
/**
|
|
262
|
+
* Version: {{ version }}
|
|
263
|
+
* Date: {{ date }}
|
|
264
|
+
* {%- if changes | length > 0 %}
|
|
265
|
+
* Changes:
|
|
266
|
+
{%- for change in changes %}
|
|
267
|
+
* - {{ change }}
|
|
268
|
+
{%- endfor %}
|
|
269
|
+
* {%- endif %}
|
|
270
|
+
*/
|
|
271
|
+
{%- endmacro -%}`);
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
/**
|
|
275
|
+
* Register a macro template
|
|
276
|
+
*/
|
|
277
|
+
registerMacro(name, template, metadata = {}) {
|
|
278
|
+
this.macros.set(name, {
|
|
279
|
+
template,
|
|
280
|
+
metadata: {
|
|
281
|
+
name,
|
|
282
|
+
registered: this.options.staticBuildTime,
|
|
283
|
+
namespace: this.options.namespace,
|
|
284
|
+
deterministic: true,
|
|
285
|
+
...metadata
|
|
286
|
+
}
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/**
|
|
291
|
+
* Get macro template by name
|
|
292
|
+
*/
|
|
293
|
+
getMacro(name) {
|
|
294
|
+
return this.macros.get(name);
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
/**
|
|
298
|
+
* Get all macro names
|
|
299
|
+
*/
|
|
300
|
+
getMacroNames() {
|
|
301
|
+
return Array.from(this.macros.keys()).sort();
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
/**
|
|
305
|
+
* Get macros by category
|
|
306
|
+
*/
|
|
307
|
+
getMacrosByCategory(category) {
|
|
308
|
+
const macros = [];
|
|
309
|
+
|
|
310
|
+
for (const [name, macro] of this.macros) {
|
|
311
|
+
if (macro.metadata.category === category) {
|
|
312
|
+
macros.push({ name, ...macro });
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
return macros.sort((a, b) => a.name.localeCompare(b.name));
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
/**
|
|
320
|
+
* Generate macro library as template content
|
|
321
|
+
*/
|
|
322
|
+
generateMacroLibrary(macroNames = []) {
|
|
323
|
+
const macrosToInclude = macroNames.length > 0
|
|
324
|
+
? macroNames.filter(name => this.macros.has(name))
|
|
325
|
+
: Array.from(this.macros.keys());
|
|
326
|
+
|
|
327
|
+
const content = [];
|
|
328
|
+
|
|
329
|
+
content.push('{% comment %}');
|
|
330
|
+
content.push('KGEN Macro Library');
|
|
331
|
+
content.push(`Generated: ${this.options.staticBuildTime}`);
|
|
332
|
+
content.push(`Macros: ${macrosToInclude.length}`);
|
|
333
|
+
content.push('{% endcomment %}');
|
|
334
|
+
content.push('');
|
|
335
|
+
|
|
336
|
+
for (const name of macrosToInclude.sort()) {
|
|
337
|
+
const macro = this.macros.get(name);
|
|
338
|
+
if (macro) {
|
|
339
|
+
content.push(`{% comment %} Macro: ${name} {% endcomment %}`);
|
|
340
|
+
content.push(macro.template);
|
|
341
|
+
content.push('');
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
return content.join('\n');
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
/**
|
|
349
|
+
* Export macros for external use
|
|
350
|
+
*/
|
|
351
|
+
exportMacros(format = 'kgen') {
|
|
352
|
+
const exported = {
|
|
353
|
+
format,
|
|
354
|
+
generated: this.options.staticBuildTime,
|
|
355
|
+
namespace: this.options.namespace,
|
|
356
|
+
macros: {}
|
|
357
|
+
};
|
|
358
|
+
|
|
359
|
+
for (const [name, macro] of this.macros) {
|
|
360
|
+
exported.macros[name] = {
|
|
361
|
+
template: macro.template,
|
|
362
|
+
metadata: macro.metadata
|
|
363
|
+
};
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
return exported;
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
/**
|
|
370
|
+
* Import macros from external source
|
|
371
|
+
*/
|
|
372
|
+
importMacros(macroData, options = {}) {
|
|
373
|
+
const { overwrite = false, prefix = '' } = options;
|
|
374
|
+
|
|
375
|
+
if (!macroData || !macroData.macros) {
|
|
376
|
+
throw new Error('Invalid macro data format');
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
const imported = [];
|
|
380
|
+
|
|
381
|
+
for (const [name, macro] of Object.entries(macroData.macros)) {
|
|
382
|
+
const macroName = prefix + name;
|
|
383
|
+
|
|
384
|
+
if (!overwrite && this.macros.has(macroName)) {
|
|
385
|
+
continue;
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
this.registerMacro(macroName, macro.template, {
|
|
389
|
+
...macro.metadata,
|
|
390
|
+
imported: true,
|
|
391
|
+
importedFrom: macroData.namespace || 'unknown'
|
|
392
|
+
});
|
|
393
|
+
|
|
394
|
+
imported.push(macroName);
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
return imported;
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
/**
|
|
401
|
+
* Validate macro template syntax
|
|
402
|
+
*/
|
|
403
|
+
validateMacro(name) {
|
|
404
|
+
const macro = this.macros.get(name);
|
|
405
|
+
if (!macro) {
|
|
406
|
+
throw new Error(`Macro '${name}' not found`);
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
// Basic syntax validation
|
|
410
|
+
const template = macro.template;
|
|
411
|
+
const errors = [];
|
|
412
|
+
|
|
413
|
+
// Check for balanced tags
|
|
414
|
+
const macroStart = template.match(/{%-?\s*macro\s+/g) || [];
|
|
415
|
+
const macroEnd = template.match(/{%-?\s*endmacro\s*-?%}/g) || [];
|
|
416
|
+
|
|
417
|
+
if (macroStart.length !== macroEnd.length) {
|
|
418
|
+
errors.push('Unbalanced macro tags');
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
// Check for invalid syntax patterns
|
|
422
|
+
if (template.includes('{% macro %}') || template.includes('{%- macro -%}')) {
|
|
423
|
+
errors.push('Macro definition missing name');
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
return {
|
|
427
|
+
valid: errors.length === 0,
|
|
428
|
+
errors
|
|
429
|
+
};
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
/**
|
|
433
|
+
* Get macro statistics
|
|
434
|
+
*/
|
|
435
|
+
getStats() {
|
|
436
|
+
const stats = {
|
|
437
|
+
total: this.macros.size,
|
|
438
|
+
categories: {},
|
|
439
|
+
imported: 0,
|
|
440
|
+
invalid: 0
|
|
441
|
+
};
|
|
442
|
+
|
|
443
|
+
for (const [name, macro] of this.macros) {
|
|
444
|
+
const category = macro.metadata.category || 'general';
|
|
445
|
+
stats.categories[category] = (stats.categories[category] || 0) + 1;
|
|
446
|
+
|
|
447
|
+
if (macro.metadata.imported) {
|
|
448
|
+
stats.imported++;
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
const validation = this.validateMacro(name);
|
|
452
|
+
if (!validation.valid) {
|
|
453
|
+
stats.invalid++;
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
return stats;
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
export default KGenMacroTemplates;
|