@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,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;
|