Skip to content
This repository was archived by the owner on Feb 20, 2026. It is now read-only.

Commit c39b83b

Browse files
committed
support geographical area nanopub templates
1 parent b6fae7b commit c39b83b

2 files changed

Lines changed: 59 additions & 34 deletions

File tree

src/core/formGenerator.js

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -100,19 +100,16 @@ const FieldComponents = {
100100
const input = document.createElement('input');
101101
input.type = 'text';
102102
input.className = 'form-input';
103-
input.placeholder = placeholder.label || '';
103+
input.placeholder = placeholder.label || 'Enter identifier';
104104
return input;
105105
},
106106

107107
'LocalResource': (placeholder) => {
108-
// LocalResource is auto-generated, should not render as input
109-
// Return a hidden input or null - handled specially in renderStatement
110-
return null;
111-
},
112-
113-
'IntroducedResource': (placeholder) => {
114-
// IntroducedResource is auto-generated, should not render as input
115-
return null;
108+
const input = document.createElement('input');
109+
input.type = 'text';
110+
input.className = 'form-input';
111+
input.placeholder = placeholder.label || 'Enter identifier';
112+
return input;
116113
},
117114

118115
'ValuePlaceholder': (placeholder) => {

src/core/nanopubBuilder.js

Lines changed: 53 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/**
22
* NanopubBuilder - Builds nanopubs from complete template structure
3-
* FINAL VERSION - properly handles empty instances and optional fields
4-
* FIXED: Handles nt:CREATOR placeholder
3+
* properly handles empty instances and optional fields
4+
* Handles nt:CREATOR placeholder
55
*/
66

77
export class NanopubBuilder {
@@ -23,6 +23,9 @@ export class NanopubBuilder {
2323
const tempId = this.generateRandomId();
2424
const baseUri = `http://purl.org/nanopub/temp/${tempId}`;
2525

26+
// Store base URI for IntroducedResource resolution
27+
this.currentNanopubBaseUri = baseUri;
28+
2629
const prefixes = this.buildPrefixes(tempId);
2730
const head = this.buildHead();
2831
const assertion = this.buildAssertion();
@@ -154,24 +157,32 @@ ${triples.join('\n')}
154157
object: this.formData[`${stmt.id}_object${suffix}`]
155158
};
156159

157-
// If subject is a placeholder but not in form data, try to find it
160+
// Check if subject/object are IntroducedResource or LocalResource
161+
const subjectPlaceholder = this.template.placeholders?.find(p => p.id === stmt.subject);
162+
const objectPlaceholder = this.template.placeholders?.find(p => p.id === stmt.object);
163+
164+
const subjectIsResource = subjectPlaceholder &&
165+
(subjectPlaceholder.isIntroducedResource || subjectPlaceholder.isLocalResource);
166+
const objectIsResource = objectPlaceholder &&
167+
(objectPlaceholder.isIntroducedResource || objectPlaceholder.isLocalResource);
168+
169+
// If subject is IntroducedResource/LocalResource and we don't have form data for it,
170+
// look for it in other statements (shared resource across multiple statements)
158171
if (!data.subject && stmt.subjectIsPlaceholder) {
159172
const subjectId = stmt.subject;
160-
for (const otherStmt of this.template.statements) {
161-
if (otherStmt.subjectIsPlaceholder && otherStmt.subject === subjectId) {
162-
const val = this.formData[`${otherStmt.id}_subject`];
163-
if (val) {
164-
data.subject = val;
165-
break;
166-
}
167-
}
168-
if (otherStmt.objectIsPlaceholder && otherStmt.object === subjectId) {
169-
const val = this.formData[`${otherStmt.id}_object`];
170-
if (val) {
171-
data.subject = val;
172-
break;
173-
}
174-
}
173+
const foundValue = this.findPlaceholderValue(subjectId);
174+
if (foundValue) {
175+
data.subject = foundValue;
176+
}
177+
}
178+
179+
// If object is IntroducedResource/LocalResource and we don't have form data for it,
180+
// look for it in other statements
181+
if (!data.object && stmt.objectIsPlaceholder) {
182+
const objectId = stmt.object;
183+
const foundValue = this.findPlaceholderValue(objectId);
184+
if (foundValue) {
185+
data.object = foundValue;
175186
}
176187
}
177188

@@ -180,12 +191,14 @@ ${triples.join('\n')}
180191
const hasPredicate = data.predicate && data.predicate !== '';
181192
const hasObject = data.object && data.object !== '';
182193

183-
// For optional statements, skip if no object data
184-
if (stmt.optional && !hasObject) {
194+
// For optional statements, skip if no object data (unless object is a resource type)
195+
if (stmt.optional && !hasObject && !objectIsResource) {
185196
return null;
186197
}
187198

188-
// For non-optional, we need data for editable fields
199+
// For non-optional statements:
200+
// - If both subject and object placeholders are empty, skip
201+
// - Otherwise, proceed
189202
if (!stmt.optional) {
190203
if (stmt.objectIsPlaceholder && !hasObject) {
191204
return null;
@@ -282,6 +295,13 @@ ${triples.join('\n')}
282295
// Get placeholder metadata
283296
const placeholder = this.template.placeholders?.find(p => p.id === placeholderId);
284297

298+
// Handle IntroducedResource/LocalResource - these create new URIs based on current nanopub
299+
if (placeholder && (placeholder.isIntroducedResource || placeholder.isLocalResource)) {
300+
// Use the current nanopub's base URI + the user's input as suffix
301+
const baseUri = this.currentNanopubBaseUri || 'http://purl.org/nanopub/temp/unknown';
302+
return `<${baseUri}/${value}>`;
303+
}
304+
285305
// Handle AutoEscapeUriPlaceholder
286306
if (placeholder?.type === 'AutoEscapeUriPlaceholder' && placeholder.prefix) {
287307
const encoded = encodeURIComponent(value).replace(/%20/g, '+');
@@ -341,17 +361,22 @@ ${triples.join('\n')}
341361
}
342362

343363
// Add npx:introduces for introduced resources
364+
const introducedUris = [];
344365
for (const placeholder of this.template.placeholders || []) {
345-
if (placeholder.isIntroducedResource && placeholder.prefix) {
366+
if (placeholder.isIntroducedResource) {
346367
const value = this.findPlaceholderValue(placeholder.id);
347368
if (value) {
348-
const encoded = encodeURIComponent(value).replace(/%20/g, '+');
349-
lines.push(`;
350-
npx:introduces <${placeholder.prefix}${encoded}>`);
369+
const uri = `${this.currentNanopubBaseUri}/${value}`;
370+
introducedUris.push(`<${uri}>`);
351371
}
352372
}
353373
}
354374

375+
if (introducedUris.length > 0) {
376+
lines.push(`;
377+
npx:introduces ${introducedUris.join(', ')}`);
378+
}
379+
355380
// Add label
356381
if (this.template.labelPattern) {
357382
const label = this.generateLabel();
@@ -376,7 +401,9 @@ ${lines.join('\n')}
376401
* Find value for a placeholder in form data
377402
*/
378403
findPlaceholderValue(placeholderId) {
404+
// Check all statements for this placeholder in either subject or object position
379405
for (const stmt of this.template.statements || []) {
406+
// Check if placeholder is the subject
380407
if (stmt.subject === placeholderId || stmt.subject === `sub:${placeholderId}`) {
381408
const value = this.formData[`${stmt.id}_subject`];
382409
if (value) return value;
@@ -389,6 +416,7 @@ ${lines.join('\n')}
389416
}
390417
}
391418

419+
// Check if placeholder is the object
392420
if (stmt.object === placeholderId || stmt.object === `sub:${placeholderId}`) {
393421
const value = this.formData[`${stmt.id}_object`];
394422
if (value) return value;

0 commit comments

Comments
 (0)