eyeling 1.13.2 → 1.13.4

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/tools/n3gen.js CHANGED
@@ -1032,7 +1032,7 @@ class TurtleParser {
1032
1032
  if (typ === 'Var') return new Var(val || '');
1033
1033
  if (typ === 'LParen') return this.parseList();
1034
1034
  if (typ === 'LBracket') return this.parseBlank();
1035
- if (typ === 'LBrace') return this.parseGraph(); // N3 graph term
1035
+ if (typ === 'LBrace') throw new Error('N3 graph terms { ... } are not supported in Turtle/TriG input');
1036
1036
  if (typ === 'StarOpen') return this.parseStarTerm();
1037
1037
 
1038
1038
  throw new Error(`Unexpected term token: ${tok.toString()}`);
@@ -1239,7 +1239,18 @@ class TurtleParser {
1239
1239
  const o = invert ? subject : obj;
1240
1240
 
1241
1241
  // asserted triple
1242
- out.push(new Triple(s, verb, o));
1242
+ // Special-case RDF 1.2 explicit triple reification:
1243
+ // _:r rdf:reifies <<( s p o )>> .
1244
+ // Emit as:
1245
+ // _:r log:nameOf { s p o . } .
1246
+ // This matches the mapping we already use for reifiedTriple sugar and annotations.
1247
+ let assertedVerb = verb;
1248
+ let assertedObj = o;
1249
+ if (!invert && verb instanceof Iri && verb.value === RDF_NS + 'reifies' && obj instanceof GraphTerm) {
1250
+ assertedVerb = internIri(log.nameOf);
1251
+ assertedObj = obj;
1252
+ }
1253
+ out.push(new Triple(s, assertedVerb, assertedObj));
1243
1254
 
1244
1255
  // optional reifier and/or annotation blocks
1245
1256
  let reifier = null;
@@ -1257,7 +1268,7 @@ class TurtleParser {
1257
1268
  }
1258
1269
 
1259
1270
  if (reifier) {
1260
- const tripleTerm = new GraphTerm([new Triple(s, verb, o)]);
1271
+ const tripleTerm = new GraphTerm([new Triple(s, assertedVerb, assertedObj)]);
1261
1272
  this.emitReifies(reifier, tripleTerm);
1262
1273
  if (this.pendingTriples.length) {
1263
1274
  out.push(...this.pendingTriples);
@@ -1790,8 +1801,23 @@ function renderPrefixPrologue(prefixes) {
1790
1801
  function ensureSkolemPrefix(prefixes, skolemMap) {
1791
1802
  if (!skolemMap || skolemMap.size === 0) return prefixes;
1792
1803
 
1793
- // If initSkolemForInput() was not called (library usage), fall back to a fresh UUID.
1794
- if (!SKOLEM_PREFIX_IRI) SKOLEM_PREFIX_IRI = `${SKOLEM_ROOT}${crypto.randomUUID()}#`;
1804
+ // Make skolem: prefix IRI deterministic.
1805
+ //
1806
+ // Preferred: initSkolemForInput(text) sets SKOLEM_UUID / SKOLEM_PREFIX_IRI
1807
+ // deterministically from the input text (CLI and turtleToN3/trigToN3).
1808
+ //
1809
+ // Fallback (library/advanced usage): derive a stable UUID from the *set of
1810
+ // blank-node labels that actually require skolemization* (plus @base if any).
1811
+ // This removes the last source of non-determinism (crypto.randomUUID()).
1812
+ if (!SKOLEM_UUID) {
1813
+ const base = prefixes ? prefixes.baseIri || '' : '';
1814
+ const labels = [...skolemMap.keys()].sort().join('\n');
1815
+ const seed = ['n3gen-skolem', SKOLEM_ROOT, base, labels, ''].join('\n');
1816
+ const uuid = _deterministicUuidFromText(seed);
1817
+ SKOLEM_PREFIX_IRI = `${SKOLEM_ROOT}${uuid}#`;
1818
+ } else if (!SKOLEM_PREFIX_IRI) {
1819
+ SKOLEM_PREFIX_IRI = `${SKOLEM_ROOT}${SKOLEM_UUID}#`;
1820
+ }
1795
1821
 
1796
1822
  const baseMap = prefixes && prefixes.map ? prefixes.map : {};
1797
1823
  const newMap = { ...baseMap, [SKOLEM_PREFIX]: SKOLEM_PREFIX_IRI };
@@ -2043,7 +2069,7 @@ function writeN3LogNameOf({ datasetQuads, prefixes }) {
2043
2069
  }
2044
2070
 
2045
2071
  // ---------------------------------------------------------------------------
2046
- // Roundtrip: TriG <-> N3 (log:nameOf mapping)
2072
+ // Parsing + N3 output (Turtle/TriG -> N3)
2047
2073
  // ---------------------------------------------------------------------------
2048
2074
 
2049
2075
  function parseTriG(text) {
@@ -2079,11 +2105,15 @@ function writeN3Triples({ triples, prefixes }) {
2079
2105
  }
2080
2106
 
2081
2107
  function turtleToN3(ttlText) {
2108
+ // Ensure deterministic per-input Skolem prefix IRI even when used as a library.
2109
+ initSkolemForInput(ttlText);
2082
2110
  const { triples, prefixes } = parseTurtle(ttlText);
2083
2111
  return writeN3Triples({ triples, prefixes });
2084
2112
  }
2085
2113
 
2086
2114
  function trigToN3(trigText) {
2115
+ // Ensure deterministic per-input Skolem prefix IRI even when used as a library.
2116
+ initSkolemForInput(trigText);
2087
2117
  const { quads, prefixes } = parseTriG(trigText);
2088
2118
  return writeN3LogNameOf({ datasetQuads: quads, prefixes });
2089
2119
  }
@@ -2117,7 +2147,6 @@ async function main() {
2117
2147
  const ext = path.extname(inputFile).toLowerCase();
2118
2148
 
2119
2149
  const text = await fs.readFile(inputFile, 'utf8');
2120
- initSkolemForInput(text);
2121
2150
 
2122
2151
  if (ext === '.ttl') {
2123
2152
  process.stdout.write(turtleToN3(text));