@openuji/vocab-build 0.1.0
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 +221 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +126 -0
- package/dist/cli.js.map +1 -0
- package/dist/generate/context.d.ts +10 -0
- package/dist/generate/context.d.ts.map +1 -0
- package/dist/generate/context.js +48 -0
- package/dist/generate/context.js.map +1 -0
- package/dist/generate/html.d.ts +11 -0
- package/dist/generate/html.d.ts.map +1 -0
- package/dist/generate/html.js +37 -0
- package/dist/generate/html.js.map +1 -0
- package/dist/generate/redirects.d.ts +17 -0
- package/dist/generate/redirects.d.ts.map +1 -0
- package/dist/generate/redirects.js +59 -0
- package/dist/generate/redirects.js.map +1 -0
- package/dist/generate/turtle.d.ts +10 -0
- package/dist/generate/turtle.d.ts.map +1 -0
- package/dist/generate/turtle.js +66 -0
- package/dist/generate/turtle.js.map +1 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +143 -0
- package/dist/index.js.map +1 -0
- package/dist/model.d.ts +258 -0
- package/dist/model.d.ts.map +1 -0
- package/dist/model.js +96 -0
- package/dist/model.js.map +1 -0
- package/dist/templates/vocab.html +281 -0
- package/package.json +52 -0
package/README.md
ADDED
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
# @openuji/vocab-build
|
|
2
|
+
|
|
3
|
+
Generate publishable semantic web vocabulary assets from JSON-LD schema source files.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- 🎯 **Dual Mode Support**: Editor's Draft (ED) and Technical Report (TR) versioned snapshots
|
|
8
|
+
- 📦 **Complete Asset Generation**: JSON-LD contexts, Turtle/RDF vocabularies, and HTML documentation
|
|
9
|
+
- 🔒 **TR Immutability**: Prevents accidental overwrites of published snapshots
|
|
10
|
+
- 🎨 **Modern HTML Output**: Responsive, accessible vocabulary pages with copy-to-clipboard
|
|
11
|
+
- 🔄 **Redirect Manifests**: Support for Netlify, Cloudflare, and generic JSON formats
|
|
12
|
+
- ✅ **Full Validation**: Zod-based schema validation with detailed error messages
|
|
13
|
+
|
|
14
|
+
## Installation
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npm install @openuji/vocab-build
|
|
18
|
+
# or
|
|
19
|
+
pnpm add @openuji/vocab-build
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## CLI Usage
|
|
23
|
+
|
|
24
|
+
### Build Command
|
|
25
|
+
|
|
26
|
+
Build vocabulary assets in Editor's Draft mode:
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
vocab-build build \
|
|
30
|
+
--input vocab.core.jsonld \
|
|
31
|
+
--out dist \
|
|
32
|
+
--module core \
|
|
33
|
+
--mode ED
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Build a Technical Report snapshot:
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
vocab-build build \
|
|
40
|
+
--input vocab.core.jsonld \
|
|
41
|
+
--out dist \
|
|
42
|
+
--module core \
|
|
43
|
+
--mode TR \
|
|
44
|
+
--version 1.0.0
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### Validate Command
|
|
48
|
+
|
|
49
|
+
Validate a vocabulary source file:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
vocab-build validate --input vocab.core.jsonld
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Release Command
|
|
56
|
+
|
|
57
|
+
Convenience command for releasing a TR version:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
vocab-build release --input vocab.core.jsonld
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### CLI Options
|
|
64
|
+
|
|
65
|
+
| Option | Description | Default |
|
|
66
|
+
|--------|-------------|---------|
|
|
67
|
+
| `-i, --input <path>` | Path to vocab source file (required) | - |
|
|
68
|
+
| `-o, --out <dir>` | Output directory | `dist` |
|
|
69
|
+
| `-m, --module <core\|ui>` | Module name (required) | - |
|
|
70
|
+
| `--mode <ED\|TR>` | Build mode (required) | - |
|
|
71
|
+
| `-v, --version <semver>` | Version for TR mode (x.y.z) | - |
|
|
72
|
+
| `-f, --force` | Overwrite existing TR snapshot | `false` |
|
|
73
|
+
| `-b, --base-url <url>` | Base URL for deployment | - |
|
|
74
|
+
| `-r, --redirects <type>` | Redirect type (none\|netlify\|cloudflare\|json) | `netlify` |
|
|
75
|
+
| `-s, --strict` | Fail on unknown fields | `false` |
|
|
76
|
+
|
|
77
|
+
## Library API
|
|
78
|
+
|
|
79
|
+
```typescript
|
|
80
|
+
import { buildVocab, validateVocab } from '@openuji/vocab-build';
|
|
81
|
+
|
|
82
|
+
const result = await buildVocab({
|
|
83
|
+
input: 'vocab.core.jsonld',
|
|
84
|
+
output: 'dist',
|
|
85
|
+
module: 'core',
|
|
86
|
+
mode: 'ED',
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
if (result.success) {
|
|
90
|
+
console.log('Generated files:', result.files);
|
|
91
|
+
} else {
|
|
92
|
+
console.error('Errors:', result.errors);
|
|
93
|
+
}
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## Input Format
|
|
97
|
+
|
|
98
|
+
Vocabulary source files use an extended JSON-LD format:
|
|
99
|
+
|
|
100
|
+
```json
|
|
101
|
+
{
|
|
102
|
+
"module": "core",
|
|
103
|
+
"namespace": "https://ujm.specs.openuji.org/ns#",
|
|
104
|
+
"docBase": "https://ujm.specs.openuji.org/ns",
|
|
105
|
+
"title": "User Journey Map Core Vocabulary",
|
|
106
|
+
"description": "Core vocabulary for defining user journey maps",
|
|
107
|
+
"status": "ED",
|
|
108
|
+
"updated": "2025-12-23",
|
|
109
|
+
"terms": [
|
|
110
|
+
{
|
|
111
|
+
"id": "Journey",
|
|
112
|
+
"kind": "Class",
|
|
113
|
+
"label": "Journey",
|
|
114
|
+
"comment": "A complete user journey"
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
"id": "start",
|
|
118
|
+
"kind": "Property",
|
|
119
|
+
"label": "start",
|
|
120
|
+
"comment": "The starting step",
|
|
121
|
+
"domain": "https://ujm.specs.openuji.org/ns#Journey",
|
|
122
|
+
"range": "https://ujm.specs.openuji.org/ns#Step"
|
|
123
|
+
}
|
|
124
|
+
],
|
|
125
|
+
"context": {
|
|
126
|
+
"Journey": {
|
|
127
|
+
"@id": "https://ujm.specs.openuji.org/ns#Journey",
|
|
128
|
+
"@type": "@id"
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
### Required Fields
|
|
135
|
+
|
|
136
|
+
- `module`: `"core"` or `"ui"`
|
|
137
|
+
- `namespace`: Base IRI ending in `#`
|
|
138
|
+
- `docBase`: Base document IRI without `#`
|
|
139
|
+
- `title`, `description`: Human-readable strings
|
|
140
|
+
- `status`: `"ED"` or `"TR"`
|
|
141
|
+
- `terms`: Array of term definitions
|
|
142
|
+
|
|
143
|
+
### ED-Specific
|
|
144
|
+
|
|
145
|
+
- `updated`: ISO date string (YYYY-MM-DD)
|
|
146
|
+
|
|
147
|
+
### TR-Specific
|
|
148
|
+
|
|
149
|
+
- `version`: SemVer string (x.y.z)
|
|
150
|
+
|
|
151
|
+
### Term Definition
|
|
152
|
+
|
|
153
|
+
- `id`: Fragment name (valid identifier)
|
|
154
|
+
- `kind`: `"Class"` or `"Property"`
|
|
155
|
+
- `label`, `comment`: Human-readable strings
|
|
156
|
+
- `domain`, `range`: Optional IRIs
|
|
157
|
+
- `deprecated`: Optional boolean
|
|
158
|
+
- `seeAlso`: Optional array of URLs
|
|
159
|
+
|
|
160
|
+
## Output Structure
|
|
161
|
+
|
|
162
|
+
### For `core` module:
|
|
163
|
+
|
|
164
|
+
```
|
|
165
|
+
dist/
|
|
166
|
+
ns/
|
|
167
|
+
index.html # Latest HTML
|
|
168
|
+
ns.ttl # Latest Turtle
|
|
169
|
+
contexts/
|
|
170
|
+
core.jsonld # Latest JSON-LD context
|
|
171
|
+
ED/
|
|
172
|
+
core/
|
|
173
|
+
index.html # Editor's Draft
|
|
174
|
+
TR/
|
|
175
|
+
core/
|
|
176
|
+
1.0.0/
|
|
177
|
+
index.html # TR snapshot
|
|
178
|
+
context.jsonld
|
|
179
|
+
ns.ttl
|
|
180
|
+
_redirects # Optional redirect manifest
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
### For `ui` module:
|
|
184
|
+
|
|
185
|
+
```
|
|
186
|
+
dist/
|
|
187
|
+
ui/
|
|
188
|
+
index.html
|
|
189
|
+
ui.ttl
|
|
190
|
+
contexts/
|
|
191
|
+
ui.jsonld
|
|
192
|
+
ED/
|
|
193
|
+
ui/
|
|
194
|
+
index.html
|
|
195
|
+
TR/
|
|
196
|
+
ui/
|
|
197
|
+
1.0.0/
|
|
198
|
+
index.html
|
|
199
|
+
context.jsonld
|
|
200
|
+
ui.ttl
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
## Development
|
|
204
|
+
|
|
205
|
+
```bash
|
|
206
|
+
# Install dependencies
|
|
207
|
+
pnpm install
|
|
208
|
+
|
|
209
|
+
# Build
|
|
210
|
+
pnpm build
|
|
211
|
+
|
|
212
|
+
# Run tests
|
|
213
|
+
pnpm test
|
|
214
|
+
|
|
215
|
+
# Type check
|
|
216
|
+
pnpm typecheck
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
## License
|
|
220
|
+
|
|
221
|
+
MIT
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { Command } from 'commander';
|
|
3
|
+
import { buildVocab, validateVocab } from './index.js';
|
|
4
|
+
import { readFile } from 'fs/promises';
|
|
5
|
+
const program = new Command();
|
|
6
|
+
program
|
|
7
|
+
.name('vocab-build')
|
|
8
|
+
.description('Generate publishable semantic web vocabulary assets from JSON-LD schema source files')
|
|
9
|
+
.version('0.1.0');
|
|
10
|
+
/**
|
|
11
|
+
* Build command
|
|
12
|
+
*/
|
|
13
|
+
program
|
|
14
|
+
.command('build')
|
|
15
|
+
.description('Build vocabulary assets')
|
|
16
|
+
.requiredOption('-i, --input <path>', 'Path to vocab source file')
|
|
17
|
+
.option('-o, --out <dir>', 'Output directory', 'dist')
|
|
18
|
+
.requiredOption('-m, --module <core|ui>', 'Module name (core or ui)')
|
|
19
|
+
.requiredOption('--mode <ED|TR>', 'Build mode (ED or TR)')
|
|
20
|
+
.option('-v, --version <semver>', 'Version for TR mode (x.y.z)')
|
|
21
|
+
.option('-f, --force', 'Overwrite existing TR snapshot', false)
|
|
22
|
+
.option('-b, --base-url <url>', 'Base URL for deployment')
|
|
23
|
+
.option('-g, --git', 'Use git commit hash and date', false)
|
|
24
|
+
.option('-r, --redirects <type>', 'Redirect type (none|netlify|cloudflare|json)', 'netlify')
|
|
25
|
+
.option('-s, --strict', 'Fail on unknown fields', false)
|
|
26
|
+
.action(async (options) => {
|
|
27
|
+
const config = {
|
|
28
|
+
input: options.input,
|
|
29
|
+
output: options.out,
|
|
30
|
+
module: options.module,
|
|
31
|
+
mode: options.mode,
|
|
32
|
+
version: options.version,
|
|
33
|
+
force: options.force,
|
|
34
|
+
baseUrl: options.baseUrl,
|
|
35
|
+
git: options.git,
|
|
36
|
+
redirects: options.redirects,
|
|
37
|
+
strict: options.strict,
|
|
38
|
+
};
|
|
39
|
+
console.log('🏗️ Building vocabulary...');
|
|
40
|
+
console.log(` Input: ${config.input}`);
|
|
41
|
+
console.log(` Module: ${config.module}`);
|
|
42
|
+
console.log(` Mode: ${config.mode}`);
|
|
43
|
+
if (config.version) {
|
|
44
|
+
console.log(` Version: ${config.version}`);
|
|
45
|
+
}
|
|
46
|
+
const result = await buildVocab(config);
|
|
47
|
+
if (result.success) {
|
|
48
|
+
console.log('\n✅ Build successful!\n');
|
|
49
|
+
console.log('Generated files:');
|
|
50
|
+
result.files.forEach(file => console.log(` - ${file}`));
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
console.error('\n❌ Build failed:\n');
|
|
54
|
+
result.errors?.forEach(error => console.error(` ${error}`));
|
|
55
|
+
process.exit(1);
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
/**
|
|
59
|
+
* Validate command
|
|
60
|
+
*/
|
|
61
|
+
program
|
|
62
|
+
.command('validate')
|
|
63
|
+
.description('Validate vocabulary source file')
|
|
64
|
+
.requiredOption('-i, --input <path>', 'Path to vocab source file')
|
|
65
|
+
.action(async (options) => {
|
|
66
|
+
console.log('🔍 Validating vocabulary source...');
|
|
67
|
+
console.log(` Input: ${options.input}`);
|
|
68
|
+
const result = await validateVocab(options.input);
|
|
69
|
+
if (result.success) {
|
|
70
|
+
console.log('\n✅ Validation successful!');
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
console.error('\n❌ Validation failed:\n');
|
|
74
|
+
result.errors?.forEach(error => console.error(` ${error}`));
|
|
75
|
+
process.exit(1);
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
/**
|
|
79
|
+
* Release command (convenience)
|
|
80
|
+
*/
|
|
81
|
+
program
|
|
82
|
+
.command('release')
|
|
83
|
+
.description('Release a new TR version (builds TR + updates latest + generates redirects)')
|
|
84
|
+
.requiredOption('-i, --input <path>', 'Path to vocab source file')
|
|
85
|
+
.option('-o, --out <dir>', 'Output directory', 'dist')
|
|
86
|
+
.option('-b, --base-url <url>', 'Base URL for deployment')
|
|
87
|
+
.action(async (options) => {
|
|
88
|
+
console.log('🚀 Releasing vocabulary...');
|
|
89
|
+
// Read source to get version and module
|
|
90
|
+
const sourceContent = await readFile(options.input, 'utf-8');
|
|
91
|
+
const sourceData = JSON.parse(sourceContent);
|
|
92
|
+
if (!sourceData.version) {
|
|
93
|
+
console.error('❌ Source file must include a version for release');
|
|
94
|
+
process.exit(1);
|
|
95
|
+
}
|
|
96
|
+
if (sourceData.status !== 'TR') {
|
|
97
|
+
console.error('❌ Source file status must be "TR" for release');
|
|
98
|
+
process.exit(1);
|
|
99
|
+
}
|
|
100
|
+
const config = {
|
|
101
|
+
input: options.input,
|
|
102
|
+
output: options.out,
|
|
103
|
+
module: sourceData.module,
|
|
104
|
+
mode: 'TR',
|
|
105
|
+
version: sourceData.version,
|
|
106
|
+
baseUrl: options.baseUrl,
|
|
107
|
+
redirects: 'netlify',
|
|
108
|
+
force: false,
|
|
109
|
+
git: false,
|
|
110
|
+
strict: false,
|
|
111
|
+
};
|
|
112
|
+
const result = await buildVocab(config);
|
|
113
|
+
if (result.success) {
|
|
114
|
+
console.log('\n✅ Release successful!\n');
|
|
115
|
+
console.log(`Released ${config.module} v${config.version}`);
|
|
116
|
+
console.log('\nGenerated files:');
|
|
117
|
+
result.files.forEach(file => console.log(` - ${file}`));
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
console.error('\n❌ Release failed:\n');
|
|
121
|
+
result.errors?.forEach(error => console.error(` ${error}`));
|
|
122
|
+
process.exit(1);
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
program.parse();
|
|
126
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { VocabSource } from '../model.js';
|
|
2
|
+
/**
|
|
3
|
+
* Generate JSON-LD context from vocabulary source
|
|
4
|
+
*/
|
|
5
|
+
export declare function generateContext(source: VocabSource): object;
|
|
6
|
+
/**
|
|
7
|
+
* Format JSON-LD context with Prettier for consistent output
|
|
8
|
+
*/
|
|
9
|
+
export declare function formatContext(context: object): Promise<string>;
|
|
10
|
+
//# sourceMappingURL=context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/generate/context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAkB,MAAM,aAAa,CAAC;AAG/D;;GAEG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,CAiC3D;AAED;;GAEG;AACH,wBAAsB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAMpE"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import prettier from 'prettier';
|
|
2
|
+
/**
|
|
3
|
+
* Generate JSON-LD context from vocabulary source
|
|
4
|
+
*/
|
|
5
|
+
export function generateContext(source) {
|
|
6
|
+
const context = {
|
|
7
|
+
'@version': 0.1,
|
|
8
|
+
};
|
|
9
|
+
// Add custom context mappings if provided
|
|
10
|
+
if (source.context) {
|
|
11
|
+
Object.assign(context, source.context);
|
|
12
|
+
}
|
|
13
|
+
else {
|
|
14
|
+
// Auto-generate context from terms if not provided
|
|
15
|
+
for (const term of source.terms) {
|
|
16
|
+
context[term.id] = {
|
|
17
|
+
'@id': `${source.namespace}${term.id}`,
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
// Sort keys for deterministic output
|
|
22
|
+
const sortedContext = {};
|
|
23
|
+
const keys = Object.keys(context).sort((a, b) => {
|
|
24
|
+
// Put @version first
|
|
25
|
+
if (a === '@version')
|
|
26
|
+
return -1;
|
|
27
|
+
if (b === '@version')
|
|
28
|
+
return 1;
|
|
29
|
+
return a.localeCompare(b);
|
|
30
|
+
});
|
|
31
|
+
for (const key of keys) {
|
|
32
|
+
sortedContext[key] = context[key];
|
|
33
|
+
}
|
|
34
|
+
return {
|
|
35
|
+
'@context': sortedContext,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Format JSON-LD context with Prettier for consistent output
|
|
40
|
+
*/
|
|
41
|
+
export async function formatContext(context) {
|
|
42
|
+
return prettier.format(JSON.stringify(context, null, 2), {
|
|
43
|
+
parser: 'json',
|
|
44
|
+
printWidth: 80,
|
|
45
|
+
tabWidth: 2,
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/generate/context.ts"],"names":[],"mappings":"AACA,OAAO,QAAQ,MAAM,UAAU,CAAC;AAEhC;;GAEG;AACH,MAAM,UAAU,eAAe,CAAC,MAAmB;IAC/C,MAAM,OAAO,GAA4B;QACrC,UAAU,EAAE,GAAG;KAClB,CAAC;IAEF,0CAA0C;IAC1C,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;QACjB,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;IAC3C,CAAC;SAAM,CAAC;QACJ,mDAAmD;QACnD,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;YAC9B,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG;gBACf,KAAK,EAAE,GAAG,MAAM,CAAC,SAAS,GAAG,IAAI,CAAC,EAAE,EAAE;aACzC,CAAC;QACN,CAAC;IACL,CAAC;IAED,qCAAqC;IACrC,MAAM,aAAa,GAA4B,EAAE,CAAC;IAClD,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;QAC5C,qBAAqB;QACrB,IAAI,CAAC,KAAK,UAAU;YAAE,OAAO,CAAC,CAAC,CAAC;QAChC,IAAI,CAAC,KAAK,UAAU;YAAE,OAAO,CAAC,CAAC;QAC/B,OAAO,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;IAC9B,CAAC,CAAC,CAAC;IAEH,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACrB,aAAa,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;IACtC,CAAC;IAED,OAAO;QACH,UAAU,EAAE,aAAa;KAC5B,CAAC;AACN,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,OAAe;IAC/C,OAAO,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE;QACrD,MAAM,EAAE,MAAM;QACd,UAAU,EAAE,EAAE;QACd,QAAQ,EAAE,CAAC;KACd,CAAC,CAAC;AACP,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { VocabSource } from '../model.js';
|
|
2
|
+
export interface HTMLOptions {
|
|
3
|
+
mode: 'ED' | 'TR';
|
|
4
|
+
version?: string;
|
|
5
|
+
baseUrl?: string;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Generate HTML vocabulary page
|
|
9
|
+
*/
|
|
10
|
+
export declare function generateHTML(source: VocabSource, options: HTMLOptions): string;
|
|
11
|
+
//# sourceMappingURL=html.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"html.d.ts","sourceRoot":"","sources":["../../src/generate/html.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAkB,MAAM,aAAa,CAAC;AAO/D,MAAM,WAAW,WAAW;IACxB,IAAI,EAAE,IAAI,GAAG,IAAI,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,WAAW,GAAG,MAAM,CA8B9E"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import nunjucks from 'nunjucks';
|
|
2
|
+
import { fileURLToPath } from 'url';
|
|
3
|
+
import { dirname, join } from 'path';
|
|
4
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
5
|
+
const __dirname = dirname(__filename);
|
|
6
|
+
/**
|
|
7
|
+
* Generate HTML vocabulary page
|
|
8
|
+
*/
|
|
9
|
+
export function generateHTML(source, options) {
|
|
10
|
+
// Configure Nunjucks to load templates from the templates directory
|
|
11
|
+
const templatesDir = join(__dirname, '..', 'templates');
|
|
12
|
+
const env = nunjucks.configure(templatesDir, {
|
|
13
|
+
autoescape: true,
|
|
14
|
+
trimBlocks: true,
|
|
15
|
+
lstripBlocks: true,
|
|
16
|
+
});
|
|
17
|
+
// Group terms by kind
|
|
18
|
+
const classes = source.terms.filter((t) => t.kind === 'Class').sort((a, b) => a.id.localeCompare(b.id));
|
|
19
|
+
const properties = source.terms.filter((t) => t.kind === 'Property').sort((a, b) => a.id.localeCompare(b.id));
|
|
20
|
+
// Prepare template data
|
|
21
|
+
const templateData = {
|
|
22
|
+
title: source.title,
|
|
23
|
+
description: source.description,
|
|
24
|
+
namespace: source.namespace,
|
|
25
|
+
docBase: source.docBase,
|
|
26
|
+
module: source.module,
|
|
27
|
+
status: source.status,
|
|
28
|
+
mode: options.mode,
|
|
29
|
+
version: options.version || source.version,
|
|
30
|
+
updated: source.updated,
|
|
31
|
+
classes,
|
|
32
|
+
properties,
|
|
33
|
+
baseUrl: options.baseUrl || '',
|
|
34
|
+
};
|
|
35
|
+
return env.render('vocab.html', templateData);
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=html.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"html.js","sourceRoot":"","sources":["../../src/generate/html.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,UAAU,CAAC;AAEhC,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAErC,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;AAQtC;;GAEG;AACH,MAAM,UAAU,YAAY,CAAC,MAAmB,EAAE,OAAoB;IAClE,oEAAoE;IACpE,MAAM,YAAY,GAAG,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,WAAW,CAAC,CAAC;IACxD,MAAM,GAAG,GAAG,QAAQ,CAAC,SAAS,CAAC,YAAY,EAAE;QACzC,UAAU,EAAE,IAAI;QAChB,UAAU,EAAE,IAAI;QAChB,YAAY,EAAE,IAAI;KACrB,CAAC,CAAC;IAEH,sBAAsB;IACtB,MAAM,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAiB,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAiB,EAAE,CAAiB,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACxJ,MAAM,UAAU,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAiB,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC,IAAI,CAAC,CAAC,CAAiB,EAAE,CAAiB,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAE9J,wBAAwB;IACxB,MAAM,YAAY,GAAG;QACjB,KAAK,EAAE,MAAM,CAAC,KAAK;QACnB,WAAW,EAAE,MAAM,CAAC,WAAW;QAC/B,SAAS,EAAE,MAAM,CAAC,SAAS;QAC3B,OAAO,EAAE,MAAM,CAAC,OAAO;QACvB,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,IAAI,EAAE,OAAO,CAAC,IAAI;QAClB,OAAO,EAAE,OAAO,CAAC,OAAO,IAAI,MAAM,CAAC,OAAO;QAC1C,OAAO,EAAE,MAAM,CAAC,OAAO;QACvB,OAAO;QACP,UAAU;QACV,OAAO,EAAE,OAAO,CAAC,OAAO,IAAI,EAAE;KACjC,CAAC;IAEF,OAAO,GAAG,CAAC,MAAM,CAAC,YAAY,EAAE,YAAY,CAAC,CAAC;AAClD,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export type RedirectType = 'none' | 'netlify' | 'cloudflare' | 'json';
|
|
2
|
+
export interface RedirectConfig {
|
|
3
|
+
type: RedirectType;
|
|
4
|
+
module: 'core' | 'ui';
|
|
5
|
+
latestVersion?: string;
|
|
6
|
+
baseUrl?: string;
|
|
7
|
+
}
|
|
8
|
+
export interface Redirect {
|
|
9
|
+
from: string;
|
|
10
|
+
to: string;
|
|
11
|
+
status?: number;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Generate redirect rules based on configuration
|
|
15
|
+
*/
|
|
16
|
+
export declare function generateRedirects(config: RedirectConfig): string;
|
|
17
|
+
//# sourceMappingURL=redirects.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"redirects.d.ts","sourceRoot":"","sources":["../../src/generate/redirects.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,SAAS,GAAG,YAAY,GAAG,MAAM,CAAC;AAEtE,MAAM,WAAW,cAAc;IAC3B,IAAI,EAAE,YAAY,CAAC;IACnB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,QAAQ;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,cAAc,GAAG,MAAM,CAmChE"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generate redirect rules based on configuration
|
|
3
|
+
*/
|
|
4
|
+
export function generateRedirects(config) {
|
|
5
|
+
if (config.type === 'none') {
|
|
6
|
+
return '';
|
|
7
|
+
}
|
|
8
|
+
const redirects = [];
|
|
9
|
+
const pathPrefix = config.module === 'core' ? 'ns' : 'ui';
|
|
10
|
+
// Trailing slash normalization
|
|
11
|
+
redirects.push({
|
|
12
|
+
from: `/${pathPrefix}`,
|
|
13
|
+
to: `/${pathPrefix}/`,
|
|
14
|
+
status: 301,
|
|
15
|
+
});
|
|
16
|
+
// TR latest version redirect
|
|
17
|
+
if (config.latestVersion) {
|
|
18
|
+
redirects.push({
|
|
19
|
+
from: `/TR/${config.module}/`,
|
|
20
|
+
to: `/TR/${config.module}/${config.latestVersion}/`,
|
|
21
|
+
status: 302,
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
// Format based on type
|
|
25
|
+
switch (config.type) {
|
|
26
|
+
case 'netlify':
|
|
27
|
+
return formatNetlifyRedirects(redirects);
|
|
28
|
+
case 'cloudflare':
|
|
29
|
+
return formatCloudflareRedirects(redirects);
|
|
30
|
+
case 'json':
|
|
31
|
+
return formatJsonRedirects(redirects);
|
|
32
|
+
default:
|
|
33
|
+
return '';
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Format redirects for Netlify _redirects file
|
|
38
|
+
*/
|
|
39
|
+
function formatNetlifyRedirects(redirects) {
|
|
40
|
+
return redirects.map(r => `${r.from} ${r.to} ${r.status || 301}`).join('\n') + '\n';
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Format redirects for Cloudflare Pages
|
|
44
|
+
*/
|
|
45
|
+
function formatCloudflareRedirects(redirects) {
|
|
46
|
+
const rules = redirects.map(r => ({
|
|
47
|
+
source: r.from,
|
|
48
|
+
destination: r.to,
|
|
49
|
+
permanent: r.status === 301,
|
|
50
|
+
}));
|
|
51
|
+
return JSON.stringify({ redirects: rules }, null, 2);
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Format redirects as generic JSON
|
|
55
|
+
*/
|
|
56
|
+
function formatJsonRedirects(redirects) {
|
|
57
|
+
return JSON.stringify(redirects, null, 2);
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=redirects.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"redirects.js","sourceRoot":"","sources":["../../src/generate/redirects.ts"],"names":[],"mappings":"AAeA;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAAC,MAAsB;IACpD,IAAI,MAAM,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;QACzB,OAAO,EAAE,CAAC;IACd,CAAC;IAED,MAAM,SAAS,GAAe,EAAE,CAAC;IACjC,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;IAE1D,+BAA+B;IAC/B,SAAS,CAAC,IAAI,CAAC;QACX,IAAI,EAAE,IAAI,UAAU,EAAE;QACtB,EAAE,EAAE,IAAI,UAAU,GAAG;QACrB,MAAM,EAAE,GAAG;KACd,CAAC,CAAC;IAEH,6BAA6B;IAC7B,IAAI,MAAM,CAAC,aAAa,EAAE,CAAC;QACvB,SAAS,CAAC,IAAI,CAAC;YACX,IAAI,EAAE,OAAO,MAAM,CAAC,MAAM,GAAG;YAC7B,EAAE,EAAE,OAAO,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC,aAAa,GAAG;YACnD,MAAM,EAAE,GAAG;SACd,CAAC,CAAC;IACP,CAAC;IAED,uBAAuB;IACvB,QAAQ,MAAM,CAAC,IAAI,EAAE,CAAC;QAClB,KAAK,SAAS;YACV,OAAO,sBAAsB,CAAC,SAAS,CAAC,CAAC;QAC7C,KAAK,YAAY;YACb,OAAO,yBAAyB,CAAC,SAAS,CAAC,CAAC;QAChD,KAAK,MAAM;YACP,OAAO,mBAAmB,CAAC,SAAS,CAAC,CAAC;QAC1C;YACI,OAAO,EAAE,CAAC;IAClB,CAAC;AACL,CAAC;AAED;;GAEG;AACH,SAAS,sBAAsB,CAAC,SAAqB;IACjD,OAAO,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,MAAM,IAAI,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;AAC1F,CAAC;AAED;;GAEG;AACH,SAAS,yBAAyB,CAAC,SAAqB;IACpD,MAAM,KAAK,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAC9B,MAAM,EAAE,CAAC,CAAC,IAAI;QACd,WAAW,EAAE,CAAC,CAAC,EAAE;QACjB,SAAS,EAAE,CAAC,CAAC,MAAM,KAAK,GAAG;KAC9B,CAAC,CAAC,CAAC;IACJ,OAAO,IAAI,CAAC,SAAS,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;AACzD,CAAC;AAED;;GAEG;AACH,SAAS,mBAAmB,CAAC,SAAqB;IAC9C,OAAO,IAAI,CAAC,SAAS,CAAC,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;AAC9C,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { VocabSource } from '../model.js';
|
|
2
|
+
export interface TurtleOptions {
|
|
3
|
+
mode: 'ED' | 'TR';
|
|
4
|
+
version?: string;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Generate Turtle/RDF vocabulary from source
|
|
8
|
+
*/
|
|
9
|
+
export declare function generateTurtle(source: VocabSource, options: TurtleOptions): string;
|
|
10
|
+
//# sourceMappingURL=turtle.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"turtle.d.ts","sourceRoot":"","sources":["../../src/generate/turtle.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAI/C,MAAM,WAAW,aAAa;IAC1B,IAAI,EAAE,IAAI,GAAG,IAAI,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,aAAa,GAAG,MAAM,CAuGlF"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { Writer, DataFactory } from 'n3';
|
|
2
|
+
const { namedNode, literal } = DataFactory;
|
|
3
|
+
/**
|
|
4
|
+
* Generate Turtle/RDF vocabulary from source
|
|
5
|
+
*/
|
|
6
|
+
export function generateTurtle(source, options) {
|
|
7
|
+
const writer = new Writer({
|
|
8
|
+
prefixes: {
|
|
9
|
+
rdf: 'http://www.w3.org/1999/02/22-rdf-syntax-ns#',
|
|
10
|
+
rdfs: 'http://www.w3.org/2000/01/rdf-schema#',
|
|
11
|
+
owl: 'http://www.w3.org/2002/07/owl#',
|
|
12
|
+
xsd: 'http://www.w3.org/2001/XMLSchema#',
|
|
13
|
+
'': source.namespace,
|
|
14
|
+
},
|
|
15
|
+
});
|
|
16
|
+
// Add ontology header
|
|
17
|
+
const ontologyIRI = source.docBase;
|
|
18
|
+
writer.addQuad(namedNode(ontologyIRI), namedNode('http://www.w3.org/1999/02/22-rdf-syntax-ns#type'), namedNode('http://www.w3.org/2002/07/owl#Ontology'));
|
|
19
|
+
writer.addQuad(namedNode(ontologyIRI), namedNode('http://www.w3.org/2000/01/rdf-schema#label'), literal(source.title));
|
|
20
|
+
writer.addQuad(namedNode(ontologyIRI), namedNode('http://www.w3.org/2000/01/rdf-schema#comment'), literal(source.description));
|
|
21
|
+
// Add version metadata for TR
|
|
22
|
+
if (options.mode === 'TR' && options.version) {
|
|
23
|
+
writer.addQuad(namedNode(ontologyIRI), namedNode('http://www.w3.org/2002/07/owl#versionInfo'), literal(options.version));
|
|
24
|
+
const versionIRI = `${ontologyIRI}/TR/${source.module}/${options.version}/vocab.ttl`;
|
|
25
|
+
writer.addQuad(namedNode(ontologyIRI), namedNode('http://www.w3.org/2002/07/owl#versionIRI'), namedNode(versionIRI));
|
|
26
|
+
}
|
|
27
|
+
// Add imports for UI module (imports core)
|
|
28
|
+
if (source.module === 'ui') {
|
|
29
|
+
writer.addQuad(namedNode(ontologyIRI), namedNode('http://www.w3.org/2002/07/owl#imports'), namedNode('https://ujm.specs.openuji.org/ns'));
|
|
30
|
+
}
|
|
31
|
+
// Add terms
|
|
32
|
+
for (const term of source.terms) {
|
|
33
|
+
const termIRI = `${source.namespace}${term.id}`;
|
|
34
|
+
const termType = term.kind === 'Class'
|
|
35
|
+
? 'http://www.w3.org/2000/01/rdf-schema#Class'
|
|
36
|
+
: 'http://www.w3.org/1999/02/22-rdf-syntax-ns#Property';
|
|
37
|
+
writer.addQuad(namedNode(termIRI), namedNode('http://www.w3.org/1999/02/22-rdf-syntax-ns#type'), namedNode(termType));
|
|
38
|
+
writer.addQuad(namedNode(termIRI), namedNode('http://www.w3.org/2000/01/rdf-schema#label'), literal(term.label));
|
|
39
|
+
writer.addQuad(namedNode(termIRI), namedNode('http://www.w3.org/2000/01/rdf-schema#comment'), literal(term.comment));
|
|
40
|
+
// Add domain and range if present
|
|
41
|
+
if (term.domain) {
|
|
42
|
+
writer.addQuad(namedNode(termIRI), namedNode('http://www.w3.org/2000/01/rdf-schema#domain'), namedNode(term.domain));
|
|
43
|
+
}
|
|
44
|
+
if (term.range) {
|
|
45
|
+
writer.addQuad(namedNode(termIRI), namedNode('http://www.w3.org/2000/01/rdf-schema#range'), namedNode(term.range));
|
|
46
|
+
}
|
|
47
|
+
// Add deprecated marker
|
|
48
|
+
if (term.deprecated) {
|
|
49
|
+
writer.addQuad(namedNode(termIRI), namedNode('http://www.w3.org/2002/07/owl#deprecated'), literal('true', namedNode('http://www.w3.org/2001/XMLSchema#boolean')));
|
|
50
|
+
}
|
|
51
|
+
// Add seeAlso links
|
|
52
|
+
if (term.seeAlso) {
|
|
53
|
+
for (const url of term.seeAlso) {
|
|
54
|
+
writer.addQuad(namedNode(termIRI), namedNode('http://www.w3.org/2000/01/rdf-schema#seeAlso'), namedNode(url));
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
let result = '';
|
|
59
|
+
writer.end((error, output) => {
|
|
60
|
+
if (error)
|
|
61
|
+
throw error;
|
|
62
|
+
result = output;
|
|
63
|
+
});
|
|
64
|
+
return result;
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=turtle.js.map
|