eyeling 1.16.1 → 1.16.2

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.
@@ -2,6 +2,8 @@
2
2
 
3
3
  ARCtifacts are trustworthy programs telling a concise story in three parts. First comes the **Answer** to a specific question. This is followed by the **Reason Why** that answer is correct, articulated in everyday language and supported by the relevant identities, rules, or ideas. Finally, every case includes a **Check**—a concrete test designed to fail loudly if an assumption doesn't hold or an edge case bites. The result is a computation with a complete, auditable trail: you can see precisely what was done, why it was valid, and how the page verifies its own work.
4
4
 
5
+ At the core of this approach are three familiar ingredients: **Data**, **Logic**, and a **Question**. We summarize the workflow as **P3 — Prompt → Program → Proof**: the prompt supplies the task and materials, the program turns them into a concrete, repeatable procedure, and the proof is practical rather than ceremonial, consisting of the **Reason Why** together with the **Check**. This is what makes each ARCtifact not just a result, but a portable, auditable, and trustworthy computational artifact.
6
+
5
7
  ## Science
6
8
 
7
9
  - [**Body Mass Index**](https://eyereasoner.github.io/eyeling/arctifacts/bmi.html) — Compute BMI categories with explainable thresholds and sanity checks.
package/eyeling.js CHANGED
@@ -294,7 +294,7 @@ function termToJsString(t) {
294
294
  if (t instanceof Iri) return t.value;
295
295
  if (!(t instanceof Literal)) return null;
296
296
 
297
- const [lex, _dt] = literalParts(t.value);
297
+ const [lex] = literalParts(t.value);
298
298
 
299
299
  if (isQuotedLexical(lex)) {
300
300
  // Interpret N3/Turtle string escapes (\" \n \uXXXX \UXXXXXXXX …)
@@ -316,7 +316,7 @@ function termToJsStringDecoded(t) {
316
316
  // Like termToJsString, but for short literals it *also* interprets escapes
317
317
  // (\" \n \uXXXX …) by attempting JSON.parse on the quoted lexical form.
318
318
  if (!(t instanceof Literal)) return null;
319
- const [lex, _dt] = literalParts(t.value);
319
+ const [lex] = literalParts(t.value);
320
320
 
321
321
  // Long strings: """ ... """ are taken verbatim.
322
322
  if (lex.length >= 6 && lex.startsWith('"""') && lex.endsWith('"""')) {
@@ -327,7 +327,7 @@ function termToJsStringDecoded(t) {
327
327
  if (lex.length >= 2 && lex[0] === '"' && lex[lex.length - 1] === '"') {
328
328
  try {
329
329
  return JSON.parse(lex);
330
- } catch (_e) {
330
+ } catch {
331
331
  /* fall through */
332
332
  }
333
333
  return stripQuotes(lex);
@@ -392,13 +392,13 @@ function compileSwapRegex(pattern, extraFlags) {
392
392
  const flags = (extraFlags || '') + (needU ? 'u' : '');
393
393
  try {
394
394
  return new RegExp(pattern, flags);
395
- } catch (_e) {
395
+ } catch {
396
396
  if (needU) {
397
397
  const p2 = sanitizeForUnicodeMode(pattern);
398
398
  if (p2 !== pattern) {
399
399
  try {
400
400
  return new RegExp(p2, flags);
401
- } catch (_e2) {}
401
+ } catch {}
402
402
  }
403
403
  }
404
404
  return null;
@@ -1420,7 +1420,7 @@ function hashLiteralTerm(t, algo) {
1420
1420
  try {
1421
1421
  const digest = nodeCrypto.createHash(algo).update(input, 'utf8').digest('hex');
1422
1422
  return internLiteral(JSON.stringify(digest));
1423
- } catch (_e) {
1423
+ } catch {
1424
1424
  return null;
1425
1425
  }
1426
1426
  }
@@ -2617,7 +2617,7 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen, maxResults) {
2617
2617
 
2618
2618
  const results = [];
2619
2619
  for (const el of inputList) {
2620
- const yvar = new Var('_mapY');
2620
+ const yvar = new Var('mapY');
2621
2621
  const goal2 = new Triple(el, pred, yvar);
2622
2622
  const sols = proveGoals([goal2], subst, facts, backRules, depth + 1, [], varGen);
2623
2623
 
@@ -4020,7 +4020,7 @@ function main() {
4020
4020
  }
4021
4021
 
4022
4022
  if (showAst) {
4023
- function astReplacer(_key, value) {
4023
+ function astReplacer(unusedJsonKey, value) {
4024
4024
  if (value instanceof Set) return Array.from(value);
4025
4025
  if (value && typeof value === 'object' && value.constructor) {
4026
4026
  const t = value.constructor.name;
@@ -4160,7 +4160,7 @@ function main() {
4160
4160
  engine.setTracePrefixes(outPrefixes);
4161
4161
 
4162
4162
  const entries = Object.entries(outPrefixes.map)
4163
- .filter(([_p, base]) => !!base)
4163
+ .filter(([, base]) => !!base)
4164
4164
  .sort((a, b) => (a[0] < b[0] ? -1 : a[0] > b[0] ? 1 : 0));
4165
4165
 
4166
4166
  for (const [pfx, base] of entries) {
@@ -4594,7 +4594,7 @@ function parseSemanticsToFormula(text, baseIri) {
4594
4594
  const parser = new Parser(toks);
4595
4595
  if (typeof baseIri === 'string' && baseIri) parser.prefixes.setBase(baseIri);
4596
4596
 
4597
- const [_prefixes, triples, frules, brules] = parser.parseDocument();
4597
+ const [, triples, frules, brules] = parser.parseDocument();
4598
4598
 
4599
4599
  const all = triples.slice();
4600
4600
 
@@ -7974,7 +7974,7 @@ function makeExplain(deps) {
7974
7974
  // log:outputString support
7975
7975
  // ===========================================================================
7976
7976
 
7977
- function __compareOutputStringKeys(a, b, _prefixes) {
7977
+ function compareOutputStringKeys(a, b) {
7978
7978
  // Deterministic ordering of keys. The spec only requires "order of the subject keys"
7979
7979
  // and leaves concrete term ordering reasoner-dependent. We implement:
7980
7980
  // 1) numeric literals (numeric value)
@@ -8052,7 +8052,7 @@ function makeExplain(deps) {
8052
8052
  }
8053
8053
 
8054
8054
  pairs.sort((a, b) => {
8055
- const c = __compareOutputStringKeys(a.key, b.key, prefixes);
8055
+ const c = compareOutputStringKeys(a.key, b.key, prefixes);
8056
8056
  if (c !== 0) return c;
8057
8057
  return a.idx - b.idx; // stable tie-breaker
8058
8058
  });
@@ -10053,7 +10053,7 @@ function collectIrisInTerm(t) {
10053
10053
  if (t instanceof Iri) {
10054
10054
  out.push(t.value);
10055
10055
  } else if (t instanceof Literal) {
10056
- const [_lex, dt] = literalParts(t.value);
10056
+ const [, dt] = literalParts(t.value);
10057
10057
  if (dt) out.push(dt); // so rdf/xsd prefixes are emitted when only used in ^^...
10058
10058
  } else if (t instanceof ListTerm) {
10059
10059
  for (const x of t.elems) out.push(...collectIrisInTerm(x));
@@ -11624,8 +11624,8 @@ module.exports = {
11624
11624
  const __entry = __loadEntry();
11625
11625
  const __api = { reasonStream: __entry.reasonStream, reasonRdfJs: __entry.reasonRdfJs };
11626
11626
 
11627
- try { if (__outerModule && __outerModule.exports) __outerModule.exports = __api; } catch (_e) {}
11628
- try { if (__outerSelf) __outerSelf.eyeling = __api; } catch (_e) {}
11627
+ try { if (__outerModule && __outerModule.exports) __outerModule.exports = __api; } catch (ignoredError) {}
11628
+ try { if (__outerSelf) __outerSelf.eyeling = __api; } catch (ignoredError) {}
11629
11629
 
11630
11630
  // ---- demo.html compatibility ----
11631
11631
  // The original monolithic eyeling.js exposed internal functions/flags as globals.
@@ -11653,18 +11653,18 @@ module.exports = {
11653
11653
  // Fallback (no live linkage)
11654
11654
  if (typeof getFn === "function") __outerSelf[name] = getFn();
11655
11655
  }
11656
- } catch (_e) {}
11656
+ } catch (ignoredError) {}
11657
11657
  };
11658
11658
 
11659
11659
  def("enforceHttpsEnabled", __entry.getEnforceHttpsEnabled, __entry.setEnforceHttpsEnabled);
11660
11660
  def("proofCommentsEnabled", __entry.getProofCommentsEnabled, __entry.setProofCommentsEnabled);
11661
11661
  def("__tracePrefixes", __entry.getTracePrefixes, __entry.setTracePrefixes);
11662
11662
  }
11663
- } catch (_e) {}
11663
+ } catch (ignoredError) {}
11664
11664
 
11665
11665
  try {
11666
11666
  if (__outerModule && __outerRequire && __outerRequire.main === __outerModule && typeof __entry.main === "function") {
11667
11667
  __entry.main();
11668
11668
  }
11669
- } catch (_e) {}
11669
+ } catch (ignoredError) {}
11670
11670
  })();
package/lib/builtins.js CHANGED
@@ -282,7 +282,7 @@ function termToJsString(t) {
282
282
  if (t instanceof Iri) return t.value;
283
283
  if (!(t instanceof Literal)) return null;
284
284
 
285
- const [lex, _dt] = literalParts(t.value);
285
+ const [lex] = literalParts(t.value);
286
286
 
287
287
  if (isQuotedLexical(lex)) {
288
288
  // Interpret N3/Turtle string escapes (\" \n \uXXXX \UXXXXXXXX …)
@@ -304,7 +304,7 @@ function termToJsStringDecoded(t) {
304
304
  // Like termToJsString, but for short literals it *also* interprets escapes
305
305
  // (\" \n \uXXXX …) by attempting JSON.parse on the quoted lexical form.
306
306
  if (!(t instanceof Literal)) return null;
307
- const [lex, _dt] = literalParts(t.value);
307
+ const [lex] = literalParts(t.value);
308
308
 
309
309
  // Long strings: """ ... """ are taken verbatim.
310
310
  if (lex.length >= 6 && lex.startsWith('"""') && lex.endsWith('"""')) {
@@ -315,7 +315,7 @@ function termToJsStringDecoded(t) {
315
315
  if (lex.length >= 2 && lex[0] === '"' && lex[lex.length - 1] === '"') {
316
316
  try {
317
317
  return JSON.parse(lex);
318
- } catch (_e) {
318
+ } catch {
319
319
  /* fall through */
320
320
  }
321
321
  return stripQuotes(lex);
@@ -380,13 +380,13 @@ function compileSwapRegex(pattern, extraFlags) {
380
380
  const flags = (extraFlags || '') + (needU ? 'u' : '');
381
381
  try {
382
382
  return new RegExp(pattern, flags);
383
- } catch (_e) {
383
+ } catch {
384
384
  if (needU) {
385
385
  const p2 = sanitizeForUnicodeMode(pattern);
386
386
  if (p2 !== pattern) {
387
387
  try {
388
388
  return new RegExp(p2, flags);
389
- } catch (_e2) {}
389
+ } catch {}
390
390
  }
391
391
  }
392
392
  return null;
@@ -1408,7 +1408,7 @@ function hashLiteralTerm(t, algo) {
1408
1408
  try {
1409
1409
  const digest = nodeCrypto.createHash(algo).update(input, 'utf8').digest('hex');
1410
1410
  return internLiteral(JSON.stringify(digest));
1411
- } catch (_e) {
1411
+ } catch {
1412
1412
  return null;
1413
1413
  }
1414
1414
  }
@@ -2605,7 +2605,7 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen, maxResults) {
2605
2605
 
2606
2606
  const results = [];
2607
2607
  for (const el of inputList) {
2608
- const yvar = new Var('_mapY');
2608
+ const yvar = new Var('mapY');
2609
2609
  const goal2 = new Triple(el, pred, yvar);
2610
2610
  const sols = proveGoals([goal2], subst, facts, backRules, depth + 1, [], varGen);
2611
2611
 
package/lib/cli.js CHANGED
@@ -153,7 +153,7 @@ function main() {
153
153
  }
154
154
 
155
155
  if (showAst) {
156
- function astReplacer(_key, value) {
156
+ function astReplacer(unusedJsonKey, value) {
157
157
  if (value instanceof Set) return Array.from(value);
158
158
  if (value && typeof value === 'object' && value.constructor) {
159
159
  const t = value.constructor.name;
@@ -293,7 +293,7 @@ function main() {
293
293
  engine.setTracePrefixes(outPrefixes);
294
294
 
295
295
  const entries = Object.entries(outPrefixes.map)
296
- .filter(([_p, base]) => !!base)
296
+ .filter(([, base]) => !!base)
297
297
  .sort((a, b) => (a[0] < b[0] ? -1 : a[0] > b[0] ? 1 : 0));
298
298
 
299
299
  for (const [pfx, base] of entries) {
package/lib/deref.js CHANGED
@@ -359,7 +359,7 @@ function parseSemanticsToFormula(text, baseIri) {
359
359
  const parser = new Parser(toks);
360
360
  if (typeof baseIri === 'string' && baseIri) parser.prefixes.setBase(baseIri);
361
361
 
362
- const [_prefixes, triples, frules, brules] = parser.parseDocument();
362
+ const [, triples, frules, brules] = parser.parseDocument();
363
363
 
364
364
  const all = triples.slice();
365
365
 
package/lib/explain.js CHANGED
@@ -118,7 +118,7 @@ function makeExplain(deps) {
118
118
  // log:outputString support
119
119
  // ===========================================================================
120
120
 
121
- function __compareOutputStringKeys(a, b, _prefixes) {
121
+ function compareOutputStringKeys(a, b) {
122
122
  // Deterministic ordering of keys. The spec only requires "order of the subject keys"
123
123
  // and leaves concrete term ordering reasoner-dependent. We implement:
124
124
  // 1) numeric literals (numeric value)
@@ -196,7 +196,7 @@ function makeExplain(deps) {
196
196
  }
197
197
 
198
198
  pairs.sort((a, b) => {
199
- const c = __compareOutputStringKeys(a.key, b.key, prefixes);
199
+ const c = compareOutputStringKeys(a.key, b.key, prefixes);
200
200
  if (c !== 0) return c;
201
201
  return a.idx - b.idx; // stable tie-breaker
202
202
  });
package/lib/prelude.js CHANGED
@@ -426,7 +426,7 @@ function collectIrisInTerm(t) {
426
426
  if (t instanceof Iri) {
427
427
  out.push(t.value);
428
428
  } else if (t instanceof Literal) {
429
- const [_lex, dt] = literalParts(t.value);
429
+ const [, dt] = literalParts(t.value);
430
430
  if (dt) out.push(dt); // so rdf/xsd prefixes are emitted when only used in ^^...
431
431
  } else if (t instanceof ListTerm) {
432
432
  for (const x of t.elems) out.push(...collectIrisInTerm(x));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eyeling",
3
- "version": "1.16.1",
3
+ "version": "1.16.2",
4
4
  "description": "A minimal Notation3 (N3) reasoner in JavaScript.",
5
5
  "main": "./index.js",
6
6
  "keywords": [
package/test/api.test.js CHANGED
@@ -1305,15 +1305,15 @@ ex:a p:trig ex:b.
1305
1305
  });
1306
1306
 
1307
1307
  // stash for check()
1308
- this._seen = seen;
1309
- this._result = r;
1308
+ this.seen = seen;
1309
+ this.result = r;
1310
1310
  return r.closureN3;
1311
1311
  },
1312
1312
  expect: [/http:\/\/example\.org\/q/m],
1313
1313
  notExpect: [/http:\/\/example\.org\/p/m],
1314
1314
  check(out, tc) {
1315
- assert.equal(tc._seen.length, 1, 'Expected onDerived to be called once');
1316
- assert.match(tc._seen[0], /http:\/\/example\.org\/q/, 'Expected streamed triple to be the derived one');
1315
+ assert.equal(tc.seen.length, 1, 'Expected onDerived to be called once');
1316
+ assert.match(tc.seen[0], /http:\/\/example\.org\/q/, 'Expected streamed triple to be the derived one');
1317
1317
  // closureN3 should be exactly the derived triple (no input facts).
1318
1318
  assert.ok(String(out).trim().includes('http://example.org/q'));
1319
1319
  assert.ok(!String(out).includes('http://example.org/p'));
@@ -1584,19 +1584,19 @@ _:x :hates { _:foo :making :mess }.
1584
1584
  onDerived: ({ quad }) => seen.push(quad),
1585
1585
  },
1586
1586
  );
1587
- this._seen = seen;
1588
- this._result = result;
1587
+ this.seen = seen;
1588
+ this.result = result;
1589
1589
  return result.closureN3;
1590
1590
  },
1591
1591
  expect: [/http:\/\/example\.org\/q/m],
1592
1592
  notExpect: [/http:\/\/example\.org\/p/m],
1593
- check(_out, tc) {
1594
- assert.equal(tc._seen.length, 1, 'Expected one streamed RDF/JS quad');
1595
- assert.equal(tc._seen[0].termType, 'Quad');
1596
- assert.equal(tc._seen[0].predicate.value, 'http://example.org/q');
1597
- assert.ok(Array.isArray(tc._result.closureQuads), 'Expected closureQuads array');
1598
- assert.equal(tc._result.closureQuads.length, 1);
1599
- assert.equal(tc._result.closureQuads[0].object.value, 'http://example.org/o');
1593
+ check(outputIgnored, tc) {
1594
+ assert.equal(tc.seen.length, 1, 'Expected one streamed RDF/JS quad');
1595
+ assert.equal(tc.seen[0].termType, 'Quad');
1596
+ assert.equal(tc.seen[0].predicate.value, 'http://example.org/q');
1597
+ assert.ok(Array.isArray(tc.result.closureQuads), 'Expected closureQuads array');
1598
+ assert.equal(tc.result.closureQuads.length, 1);
1599
+ assert.equal(tc.result.closureQuads[0].object.value, 'http://example.org/o');
1600
1600
  },
1601
1601
  },
1602
1602
  {
@@ -1633,14 +1633,14 @@ _:x :hates { _:foo :making :mess }.
1633
1633
  })) {
1634
1634
  quads.push(quad);
1635
1635
  }
1636
- this._quads = quads;
1636
+ this.quads = quads;
1637
1637
  return quads.map((q) => `${q.subject.value} ${q.predicate.value} ${q.object.value}`).join('\n');
1638
1638
  },
1639
1639
  expect: [/http:\/\/example\.org\/q/],
1640
- check(_out, tc) {
1641
- assert.equal(tc._quads.length, 1, 'Expected one yielded quad');
1642
- assert.equal(tc._quads[0].predicate.value, 'http://example.org/q');
1643
- assert.equal(tc._quads[0].graph.termType, 'DefaultGraph');
1640
+ check(outputIgnored, tc) {
1641
+ assert.equal(tc.quads.length, 1, 'Expected one yielded quad');
1642
+ assert.equal(tc.quads[0].predicate.value, 'http://example.org/q');
1643
+ assert.equal(tc.quads[0].graph.termType, 'DefaultGraph');
1644
1644
  },
1645
1645
  },
1646
1646
  {
@@ -74,7 +74,7 @@ function startStaticServer(rootDir) {
74
74
 
75
75
  res.writeHead(200, { 'Content-Type': guessContentType(fsPath), 'Cache-Control': 'no-store' });
76
76
  fs.createReadStream(fsPath).pipe(res);
77
- } catch (_e) {
77
+ } catch {
78
78
  res.writeHead(404, { 'Content-Type': 'text/plain; charset=utf-8' });
79
79
  res.end('Not found');
80
80
  }
package/tools/bundle.js CHANGED
@@ -140,8 +140,10 @@ out.push(' }');
140
140
  out.push(' const __entry = __loadEntry();');
141
141
  out.push(' const __api = { reasonStream: __entry.reasonStream, reasonRdfJs: __entry.reasonRdfJs };');
142
142
  out.push('');
143
- out.push(' try { if (__outerModule && __outerModule.exports) __outerModule.exports = __api; } catch (_e) {}');
144
- out.push(' try { if (__outerSelf) __outerSelf.eyeling = __api; } catch (_e) {}');
143
+ out.push(
144
+ ' try { if (__outerModule && __outerModule.exports) __outerModule.exports = __api; } catch (ignoredError) {}',
145
+ );
146
+ out.push(' try { if (__outerSelf) __outerSelf.eyeling = __api; } catch (ignoredError) {}');
145
147
  out.push('');
146
148
  out.push(' // ---- demo.html compatibility ----');
147
149
  out.push(' // The original monolithic eyeling.js exposed internal functions/flags as globals.');
@@ -175,14 +177,14 @@ out.push(' } else {');
175
177
  out.push(' // Fallback (no live linkage)');
176
178
  out.push(' if (typeof getFn === "function") __outerSelf[name] = getFn();');
177
179
  out.push(' }');
178
- out.push(' } catch (_e) {}');
180
+ out.push(' } catch (ignoredError) {}');
179
181
  out.push(' };');
180
182
  out.push('');
181
183
  out.push(' def("enforceHttpsEnabled", __entry.getEnforceHttpsEnabled, __entry.setEnforceHttpsEnabled);');
182
184
  out.push(' def("proofCommentsEnabled", __entry.getProofCommentsEnabled, __entry.setProofCommentsEnabled);');
183
185
  out.push(' def("__tracePrefixes", __entry.getTracePrefixes, __entry.setTracePrefixes);');
184
186
  out.push(' }');
185
- out.push(' } catch (_e) {}');
187
+ out.push(' } catch (ignoredError) {}');
186
188
  out.push('');
187
189
  out.push(' try {');
188
190
  out.push(
@@ -190,7 +192,7 @@ out.push(
190
192
  );
191
193
  out.push(' __entry.main();');
192
194
  out.push(' }');
193
- out.push(' } catch (_e) {}');
195
+ out.push(' } catch (ignoredError) {}');
194
196
  out.push('})();');
195
197
 
196
198
  fs.writeFileSync(OUT, out.join('\n') + '\n', { encoding: 'utf8' });
package/tools/n3gen.js CHANGED
@@ -32,7 +32,7 @@ const process = require('node:process');
32
32
 
33
33
  const crypto = require('node:crypto');
34
34
 
35
- function _stripIriRef(s) {
35
+ function stripIriRef(s) {
36
36
  // Allow passing an IRIREF like <...>
37
37
  if (typeof s !== 'string') return '';
38
38
  s = s.trim();
@@ -41,7 +41,7 @@ function _stripIriRef(s) {
41
41
  }
42
42
 
43
43
  function normalizeSkolemRoot(root) {
44
- root = _stripIriRef(root);
44
+ root = stripIriRef(root);
45
45
  if (!root) return '';
46
46
  // Ensure it ends with '/.well-known/genid/' OR at least with '/'
47
47
  if (!root.endsWith('/')) root += '/';
@@ -64,7 +64,7 @@ const SKOLEM_ROOT = normalizeSkolemRoot(process.env.SKOLEM_ROOT) || DEFAULT_SKOL
64
64
  let SKOLEM_UUID = null; // e.g., '3f2504e0-4f89-5d3a-9a0c-0305e82c3301'
65
65
  let SKOLEM_PREFIX_IRI = null; // e.g., 'https://.../.well-known/genid/<UUID>#'
66
66
 
67
- function _deterministicUuidFromText(inputText) {
67
+ function deterministicUuidFromText(inputText) {
68
68
  const h = crypto.createHash('sha256').update(inputText, 'utf8').digest();
69
69
  const b = Buffer.from(h.subarray(0, 16));
70
70
 
@@ -77,11 +77,11 @@ function _deterministicUuidFromText(inputText) {
77
77
  }
78
78
 
79
79
  function initSkolemForInput(inputText) {
80
- SKOLEM_UUID = _deterministicUuidFromText(inputText);
80
+ SKOLEM_UUID = deterministicUuidFromText(inputText);
81
81
  SKOLEM_PREFIX_IRI = `${SKOLEM_ROOT}${SKOLEM_UUID}#`;
82
82
  }
83
83
 
84
- function _pnLocalSafe(s) {
84
+ function pnLocalSafe(s) {
85
85
  // Turtle PN_LOCAL allows percent escapes (PLX). We make sure all "special"
86
86
  // encodeURIComponent survivors are percent-escaped too.
87
87
  return encodeURIComponent(s).replace(/[!'()*]/g, (c) => '%' + c.charCodeAt(0).toString(16).toUpperCase());
@@ -786,7 +786,7 @@ class TurtleParser {
786
786
  this.blankCounter = 0;
787
787
  this.pendingTriples = [];
788
788
  this.reifierCounter = 0;
789
- this._reifiesEmitted = new Set();
789
+ this.reifiesEmitted = new Set();
790
790
  }
791
791
 
792
792
  peek() {
@@ -811,16 +811,16 @@ class TurtleParser {
811
811
  return new Blank(`_:n3r${this.reifierCounter}`);
812
812
  }
813
813
 
814
- _termKey(t) {
814
+ termKey(t) {
815
815
  if (t == null) return '[]';
816
816
  if (t instanceof Iri) return `I:${t.value}`;
817
817
  if (t instanceof Blank) return `B:${t.label}`;
818
818
  if (t instanceof Literal) return `L:${t.value}`;
819
819
  if (t instanceof Var) return `V:${t.name}`;
820
- if (t instanceof ListTerm) return `T:(` + t.elems.map((x) => this._termKey(x)).join(' ') + `)`;
820
+ if (t instanceof ListTerm) return `T:(` + t.elems.map((x) => this.termKey(x)).join(' ') + `)`;
821
821
  if (t instanceof GraphTerm) {
822
822
  const inner = t.triples
823
- .map((tr) => `${this._termKey(tr.s)} ${this._termKey(tr.p)} ${this._termKey(tr.o)}`)
823
+ .map((tr) => `${this.termKey(tr.s)} ${this.termKey(tr.p)} ${this.termKey(tr.o)}`)
824
824
  .join(' | ');
825
825
  return `G:{${inner}}`;
826
826
  }
@@ -831,9 +831,9 @@ class TurtleParser {
831
831
  // reifier log:nameOf tripleTerm .
832
832
  // We represent tripleTerm in N3 as a quoted graph term: { s p o . }
833
833
  emitReifies(reifier, tripleGraph) {
834
- const key = `${this._termKey(reifier)}|${this._termKey(tripleGraph)}`;
835
- if (this._reifiesEmitted.has(key)) return;
836
- this._reifiesEmitted.add(key);
834
+ const key = `${this.termKey(reifier)}|${this.termKey(tripleGraph)}`;
835
+ if (this.reifiesEmitted.has(key)) return;
836
+ this.reifiesEmitted.add(key);
837
837
  this.pendingTriples.push(new Triple(reifier, internIri(LOG_NS + 'nameOf'), tripleGraph));
838
838
  }
839
839
 
@@ -1519,7 +1519,7 @@ function buildSkolemMapForBnodesThatCrossScopes(triples) {
1519
1519
  if (scopes.size <= 1) continue;
1520
1520
 
1521
1521
  const id = lbl.startsWith('_:') ? lbl.slice(2) : lbl;
1522
- const local = _pnLocalSafe(id);
1522
+ const local = pnLocalSafe(id);
1523
1523
  skolemMap.set(lbl, `${SKOLEM_PREFIX}:${local}`);
1524
1524
  }
1525
1525
  return skolemMap;
@@ -1538,16 +1538,16 @@ function buildSkolemMapForBnodesThatCrossScopes(triples) {
1538
1538
  // semantics-preserving.
1539
1539
  // ---------------------------------------------------------------------------
1540
1540
 
1541
- function _termKey(t) {
1541
+ function termKey(t) {
1542
1542
  if (t == null) return 'N:null';
1543
1543
  if (t instanceof Iri) return `I:${t.value}`;
1544
1544
  if (t instanceof Blank) return `B:${t.label}`;
1545
1545
  if (t instanceof Literal) return `L:${t.value}`;
1546
1546
  if (t instanceof Var) return `V:${t.name}`;
1547
- if (t instanceof ListTerm) return `T:(` + t.elems.map(_termKey).join(' ') + `)`;
1548
- if (t instanceof OpenListTerm) return `T:(` + t.prefix.map(_termKey).join(' ') + ` ... ?${t.tailVar})`;
1547
+ if (t instanceof ListTerm) return `T:(` + t.elems.map(termKey).join(' ') + `)`;
1548
+ if (t instanceof OpenListTerm) return `T:(` + t.prefix.map(termKey).join(' ') + ` ... ?${t.tailVar})`;
1549
1549
  if (t instanceof GraphTerm)
1550
- return `G:{` + t.triples.map((tr) => `${_termKey(tr.s)} ${_termKey(tr.p)} ${_termKey(tr.o)}`).join(' ; ') + `}`;
1550
+ return `G:{` + t.triples.map((tr) => `${termKey(tr.s)} ${termKey(tr.p)} ${termKey(tr.o)}`).join(' ; ') + `}`;
1551
1551
  return `X:${String(t)}`;
1552
1552
  }
1553
1553
 
@@ -1567,11 +1567,11 @@ function foldRdfLists(triples) {
1567
1567
 
1568
1568
  for (let i = 0; i < triples.length; i++) {
1569
1569
  const tr = triples[i];
1570
- const sKey = _termKey(tr.s);
1570
+ const sKey = termKey(tr.s);
1571
1571
  if (!outBySubj.has(sKey)) outBySubj.set(sKey, { term: tr.s, idxs: [] });
1572
1572
  outBySubj.get(sKey).idxs.push(i);
1573
1573
 
1574
- const oKey = _termKey(tr.o);
1574
+ const oKey = termKey(tr.o);
1575
1575
  const viaRest = isIri(tr.p, rdfRest);
1576
1576
  addIncoming(oKey, viaRest);
1577
1577
  }
@@ -1655,7 +1655,7 @@ function foldRdfLists(triples) {
1655
1655
  break;
1656
1656
  }
1657
1657
 
1658
- const nextKey = _termKey(next);
1658
+ const nextKey = termKey(next);
1659
1659
 
1660
1660
  // Intermediate node safety: only referenced via rdf:rest and exactly once.
1661
1661
  const inc = incoming.get(nextKey) || 0;
@@ -1694,7 +1694,7 @@ function foldRdfLists(triples) {
1694
1694
  if (t == null) return t;
1695
1695
 
1696
1696
  if (t instanceof Blank) {
1697
- const m = listMap.get(_termKey(t));
1697
+ const m = listMap.get(termKey(t));
1698
1698
  if (m) return replaceTerm(m.listTerm);
1699
1699
  return t;
1700
1700
  }
@@ -1813,7 +1813,7 @@ function ensureSkolemPrefix(prefixes, skolemMap) {
1813
1813
  const base = prefixes ? prefixes.baseIri || '' : '';
1814
1814
  const labels = [...skolemMap.keys()].sort().join('\n');
1815
1815
  const seed = ['n3gen-skolem', SKOLEM_ROOT, base, labels, ''].join('\n');
1816
- const uuid = _deterministicUuidFromText(seed);
1816
+ const uuid = deterministicUuidFromText(seed);
1817
1817
  SKOLEM_PREFIX_IRI = `${SKOLEM_ROOT}${uuid}#`;
1818
1818
  } else if (!SKOLEM_PREFIX_IRI) {
1819
1819
  SKOLEM_PREFIX_IRI = `${SKOLEM_ROOT}${SKOLEM_UUID}#`;