@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,388 @@
1
+ /**
2
+ * KGEN Template Base Class - Foundation for all template types
3
+ *
4
+ * Provides core functionality for template inheritance, composition, and validation
5
+ * All template generators should extend this base class for consistency
6
+ */
7
+
8
+ import crypto from 'crypto';
9
+ import { KGenTemplateEngine } from '../core/kgen-engine.js';
10
+ import { TemplateInheritanceEngine } from '../inheritance/index.js';
11
+
12
+ export class KGenTemplateBase {
13
+ constructor(options = {}) {
14
+ this.options = {
15
+ strictMode: options.strictMode !== false,
16
+ deterministicMode: options.deterministicMode !== false,
17
+ staticBuildTime: options.staticBuildTime || '2024-01-01T00:00:00.000Z',
18
+ enableInheritance: options.enableInheritance !== false,
19
+ enableValidation: options.enableValidation !== false,
20
+ templateDir: options.templateDir || './templates',
21
+ ...options
22
+ };
23
+
24
+ // Core engines
25
+ this.engine = new KGenTemplateEngine(this.options);
26
+ this.inheritanceEngine = new TemplateInheritanceEngine(this.options);
27
+
28
+ // Template metadata
29
+ this.metadata = {
30
+ name: options.name || this.constructor.name,
31
+ version: options.version || '1.0.0',
32
+ description: options.description || 'KGEN Template',
33
+ author: options.author || 'KGEN Generator',
34
+ created: this.options.staticBuildTime,
35
+ modified: this.options.staticBuildTime,
36
+ namespace: options.namespace || 'kgen',
37
+ category: options.category || 'base',
38
+ tags: options.tags || [],
39
+ dependencies: options.dependencies || [],
40
+ extends: options.extends || null
41
+ };
42
+
43
+ // Template registry for inheritance
44
+ this.templates = new Map();
45
+ this.blocks = new Map();
46
+ this.macros = new Map();
47
+
48
+ // Validation rules
49
+ this.validationRules = new Map();
50
+
51
+ // Initialize base templates
52
+ this.initializeBaseTemplates();
53
+ }
54
+
55
+ /**
56
+ * Initialize base templates and blocks
57
+ */
58
+ initializeBaseTemplates() {
59
+ // Base layout template
60
+ this.registerTemplate('base.layout', `{%- block doctype -%}
61
+ <!DOCTYPE html>
62
+ {%- endblock -%}
63
+ {%- block html_attrs -%}
64
+ <html lang="{{ lang | default('en') }}">
65
+ {%- endblock -%}
66
+ {%- block head -%}
67
+ <head>
68
+ {%- block meta -%}
69
+ <meta charset="{{ charset | default('UTF-8') }}">
70
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
71
+ {%- endblock -%}
72
+ {%- block title -%}
73
+ <title>{{ title | default('KGEN Generated') }}</title>
74
+ {%- endblock -%}
75
+ {%- block styles -%}
76
+ {%- endblock -%}
77
+ </head>
78
+ {%- endblock -%}
79
+ {%- block body -%}
80
+ <body>
81
+ {%- block content -%}
82
+ <!-- Content goes here -->
83
+ {%- endblock -%}
84
+ {%- block scripts -%}
85
+ {%- endblock -%}
86
+ </body>
87
+ {%- endblock -%}
88
+ </html>`);
89
+
90
+ // Base component template
91
+ this.registerTemplate('base.component', `{%- set componentName = name | default('Component') -%}
92
+ {%- set componentId = componentName | lower | replace(' ', '-') -%}
93
+ {%- block wrapper -%}
94
+ <div id="{{ componentId }}" class="{{ cssClass | default('kgen-component') }}">
95
+ {%- block header -%}
96
+ {%- if title -%}
97
+ <header class="component-header">
98
+ <h3>{{ title }}</h3>
99
+ </header>
100
+ {%- endif -%}
101
+ {%- endblock -%}
102
+
103
+ {%- block content -%}
104
+ <div class="component-content">
105
+ {{ content | default('<!-- Component content -->') }}
106
+ </div>
107
+ {%- endblock -%}
108
+
109
+ {%- block footer -%}
110
+ {%- if showFooter -%}
111
+ <footer class="component-footer">
112
+ {{ footerContent | default('') }}
113
+ </footer>
114
+ {%- endif -%}
115
+ {%- endblock -%}
116
+ </div>
117
+ {%- endblock -%}`);
118
+
119
+ // Base module template
120
+ this.registerTemplate('base.module', `{%- set moduleName = name | default('Module') -%}
121
+ /**
122
+ * {{ moduleName }} - Generated by KGEN
123
+ *
124
+ * {%- if description %}
125
+ * {{ description }}
126
+ * {%- endif %}
127
+ *
128
+ * @generated {{ __kgen.renderTime }}
129
+ */
130
+
131
+ {%- block imports -%}
132
+ {%- for import in imports | default([]) %}
133
+ import {{ import.name }}{{ import.from ? ' from ' + import.from : '' }};
134
+ {%- endfor -%}
135
+ {%- endblock -%}
136
+
137
+ {%- block constants -%}
138
+ {%- for constant in constants | default([]) %}
139
+ const {{ constant.name }} = {{ constant.value | json }};
140
+ {%- endfor -%}
141
+ {%- endblock -%}
142
+
143
+ {%- block main -%}
144
+ export class {{ moduleName }} {
145
+ constructor(options = {}) {
146
+ this.options = { ...options };
147
+ }
148
+
149
+ {%- block methods -%}
150
+ {%- for method in methods | default([]) %}
151
+
152
+ {{ method.name }}({{ method.params | default('') }}) {
153
+ {{ method.body | default('// Method implementation') }}
154
+ }
155
+ {%- endfor -%}
156
+ {%- endblock -%}
157
+ }
158
+ {%- endblock -%}
159
+
160
+ {%- block exports -%}
161
+ export default {{ moduleName }};
162
+ {%- endblock -%}`);
163
+
164
+ // Register base macros
165
+ this.registerMacro('kgen_header', `{%- macro kgen_header(title, level=1) -%}
166
+ <h{{ level }}>{{ title }}</h{{ level }}>
167
+ {%- endmacro -%}`);
168
+
169
+ this.registerMacro('kgen_timestamp', `{%- macro kgen_timestamp(format='iso') -%}
170
+ {%- if format == 'iso' -%}
171
+ {{ __kgen.renderTime }}
172
+ {%- else -%}
173
+ {{ __kgen.renderTime | formatDate(format) }}
174
+ {%- endif -%}
175
+ {%- endmacro -%}`);
176
+
177
+ this.registerMacro('kgen_hash', `{%- macro kgen_hash(content) -%}
178
+ {{ content | hash | shortHash(8) }}
179
+ {%- endmacro -%}`);
180
+ }
181
+
182
+ /**
183
+ * Register a template with the base class
184
+ */
185
+ registerTemplate(name, content, metadata = {}) {
186
+ this.templates.set(name, {
187
+ content,
188
+ metadata: {
189
+ name,
190
+ registered: this.options.staticBuildTime,
191
+ ...metadata
192
+ }
193
+ });
194
+ }
195
+
196
+ /**
197
+ * Register a block for inheritance
198
+ */
199
+ registerBlock(name, content, metadata = {}) {
200
+ this.blocks.set(name, {
201
+ content,
202
+ metadata: {
203
+ name,
204
+ registered: this.options.staticBuildTime,
205
+ ...metadata
206
+ }
207
+ });
208
+ }
209
+
210
+ /**
211
+ * Register a macro for reuse
212
+ */
213
+ registerMacro(name, content, metadata = {}) {
214
+ this.macros.set(name, {
215
+ content,
216
+ metadata: {
217
+ name,
218
+ registered: this.options.staticBuildTime,
219
+ ...metadata
220
+ }
221
+ });
222
+ }
223
+
224
+ /**
225
+ * Register validation rule
226
+ */
227
+ registerValidationRule(name, rule) {
228
+ this.validationRules.set(name, rule);
229
+ }
230
+
231
+ /**
232
+ * Generate template from registered template
233
+ */
234
+ async generateFromTemplate(templateName, context = {}, options = {}) {
235
+ if (!this.templates.has(templateName)) {
236
+ throw new Error(`Template '${templateName}' not found`);
237
+ }
238
+
239
+ const template = this.templates.get(templateName);
240
+ const mergedContext = {
241
+ ...context,
242
+ __template: {
243
+ name: templateName,
244
+ metadata: template.metadata
245
+ }
246
+ };
247
+
248
+ return await this.engine.execute(template.content, mergedContext);
249
+ }
250
+
251
+ /**
252
+ * Generate with inheritance processing
253
+ */
254
+ async generateWithInheritance(templatePath, context = {}, options = {}) {
255
+ if (!this.options.enableInheritance) {
256
+ return await this.engine.execute(templatePath, context);
257
+ }
258
+
259
+ const result = await this.inheritanceEngine.processTemplate(templatePath, context, options);
260
+
261
+ if (!result.compiled || !result.compiled.content) {
262
+ throw new Error(`Failed to process inheritance for ${templatePath}`);
263
+ }
264
+
265
+ return {
266
+ success: true,
267
+ content: result.compiled.content,
268
+ metadata: result.metadata,
269
+ dependencies: result.dependencies,
270
+ hash: result.hash
271
+ };
272
+ }
273
+
274
+ /**
275
+ * Validate generated content
276
+ */
277
+ async validateContent(content, rules = []) {
278
+ if (!this.options.enableValidation) {
279
+ return { valid: true, errors: [] };
280
+ }
281
+
282
+ const errors = [];
283
+ const rulesToApply = rules.length > 0 ? rules : Array.from(this.validationRules.keys());
284
+
285
+ for (const ruleName of rulesToApply) {
286
+ const rule = this.validationRules.get(ruleName);
287
+ if (rule) {
288
+ try {
289
+ const result = await rule(content);
290
+ if (!result.valid) {
291
+ errors.push({
292
+ rule: ruleName,
293
+ message: result.message,
294
+ line: result.line,
295
+ column: result.column
296
+ });
297
+ }
298
+ } catch (error) {
299
+ errors.push({
300
+ rule: ruleName,
301
+ message: `Validation rule failed: ${error.message}`
302
+ });
303
+ }
304
+ }
305
+ }
306
+
307
+ return {
308
+ valid: errors.length === 0,
309
+ errors,
310
+ rulesApplied: rulesToApply.length
311
+ };
312
+ }
313
+
314
+ /**
315
+ * Get template metadata
316
+ */
317
+ getMetadata() {
318
+ return {
319
+ ...this.metadata,
320
+ templates: Array.from(this.templates.keys()),
321
+ blocks: Array.from(this.blocks.keys()),
322
+ macros: Array.from(this.macros.keys()),
323
+ validationRules: Array.from(this.validationRules.keys())
324
+ };
325
+ }
326
+
327
+ /**
328
+ * Generate deterministic hash for template
329
+ */
330
+ generateTemplateHash(content, context = {}) {
331
+ const hashData = {
332
+ content,
333
+ context: Object.keys(context).sort(),
334
+ metadata: this.metadata,
335
+ templates: Array.from(this.templates.keys()).sort(),
336
+ timestamp: this.options.staticBuildTime
337
+ };
338
+
339
+ return crypto.createHash('sha256')
340
+ .update(JSON.stringify(hashData), 'utf8')
341
+ .digest('hex');
342
+ }
343
+
344
+ /**
345
+ * Clone template base with new options
346
+ */
347
+ clone(newOptions = {}) {
348
+ const cloned = new this.constructor({
349
+ ...this.options,
350
+ ...newOptions
351
+ });
352
+
353
+ // Copy registered templates
354
+ for (const [name, template] of this.templates) {
355
+ cloned.templates.set(name, { ...template });
356
+ }
357
+
358
+ for (const [name, block] of this.blocks) {
359
+ cloned.blocks.set(name, { ...block });
360
+ }
361
+
362
+ for (const [name, macro] of this.macros) {
363
+ cloned.macros.set(name, { ...macro });
364
+ }
365
+
366
+ for (const [name, rule] of this.validationRules) {
367
+ cloned.validationRules.set(name, rule);
368
+ }
369
+
370
+ return cloned;
371
+ }
372
+
373
+ /**
374
+ * Get template statistics
375
+ */
376
+ getStats() {
377
+ return {
378
+ templates: this.templates.size,
379
+ blocks: this.blocks.size,
380
+ macros: this.macros.size,
381
+ validationRules: this.validationRules.size,
382
+ options: this.options,
383
+ metadata: this.metadata
384
+ };
385
+ }
386
+ }
387
+
388
+ export default KGenTemplateBase;