@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.
Files changed (68) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +210 -0
  3. package/package.json +90 -0
  4. package/src/MIGRATION_COMPLETE.md +186 -0
  5. package/src/PORT-MAP.md +302 -0
  6. package/src/base/filter-templates.js +479 -0
  7. package/src/base/index.js +92 -0
  8. package/src/base/injection-targets.js +583 -0
  9. package/src/base/macro-templates.js +298 -0
  10. package/src/base/macro-templates.js.bak +461 -0
  11. package/src/base/shacl-templates.js +617 -0
  12. package/src/base/template-base.js +388 -0
  13. package/src/core/attestor.js +381 -0
  14. package/src/core/filters.js +518 -0
  15. package/src/core/index.js +21 -0
  16. package/src/core/kgen-engine.js +372 -0
  17. package/src/core/parser.js +447 -0
  18. package/src/core/post-processor.js +313 -0
  19. package/src/core/renderer.js +469 -0
  20. package/src/doc-generator/cli.mjs +122 -0
  21. package/src/doc-generator/index.mjs +28 -0
  22. package/src/doc-generator/mdx-generator.mjs +71 -0
  23. package/src/doc-generator/nav-generator.mjs +136 -0
  24. package/src/doc-generator/parser.mjs +291 -0
  25. package/src/doc-generator/rdf-builder.mjs +306 -0
  26. package/src/doc-generator/scanner.mjs +189 -0
  27. package/src/engine/index.js +42 -0
  28. package/src/engine/pipeline.js +448 -0
  29. package/src/engine/renderer.js +604 -0
  30. package/src/engine/template-engine.js +566 -0
  31. package/src/filters/array.js +436 -0
  32. package/src/filters/data.js +479 -0
  33. package/src/filters/index.js +270 -0
  34. package/src/filters/rdf.js +264 -0
  35. package/src/filters/text.js +369 -0
  36. package/src/index.js +109 -0
  37. package/src/inheritance/index.js +40 -0
  38. package/src/injection/api.js +260 -0
  39. package/src/injection/atomic-writer.js +327 -0
  40. package/src/injection/constants.js +136 -0
  41. package/src/injection/idempotency-manager.js +295 -0
  42. package/src/injection/index.js +28 -0
  43. package/src/injection/injection-engine.js +378 -0
  44. package/src/injection/integration.js +339 -0
  45. package/src/injection/modes/index.js +341 -0
  46. package/src/injection/rollback-manager.js +373 -0
  47. package/src/injection/target-resolver.js +323 -0
  48. package/src/injection/tests/atomic-writer.test.js +382 -0
  49. package/src/injection/tests/injection-engine.test.js +611 -0
  50. package/src/injection/tests/integration.test.js +392 -0
  51. package/src/injection/tests/run-tests.js +283 -0
  52. package/src/injection/validation-engine.js +547 -0
  53. package/src/linter/determinism-linter.js +473 -0
  54. package/src/linter/determinism.js +410 -0
  55. package/src/linter/index.js +6 -0
  56. package/src/linter/test-doubles.js +475 -0
  57. package/src/parser/frontmatter.js +228 -0
  58. package/src/parser/variables.js +344 -0
  59. package/src/renderer/deterministic.js +245 -0
  60. package/src/renderer/index.js +6 -0
  61. package/src/templates/latex/academic-paper.njk +186 -0
  62. package/src/templates/latex/index.js +104 -0
  63. package/src/templates/nextjs/app-page.njk +66 -0
  64. package/src/templates/nextjs/index.js +80 -0
  65. package/src/templates/office/docx/document.njk +368 -0
  66. package/src/templates/office/index.js +79 -0
  67. package/src/templates/office/word-report.njk +129 -0
  68. 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;