eyeling 1.10.10 → 1.10.12
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/HANDBOOK.md +131 -0
- package/examples/get-uuid.n3 +18 -14
- package/examples/output/get-uuid.n3 +2 -2
- package/eyeling.js +67 -4
- package/lib/deref.js +27 -4
- package/lib/parser.js +40 -0
- package/package.json +2 -1
package/HANDBOOK.md
CHANGED
|
@@ -26,6 +26,7 @@
|
|
|
26
26
|
- [Chapter 15 — A worked example: Socrates, step by step](#ch15)
|
|
27
27
|
- [Chapter 16 — Extending Eyeling (without breaking it)](#ch16)
|
|
28
28
|
- [Epilogue](#epilogue)
|
|
29
|
+
- [Appendix A — Eyeling user notes](#app-a)
|
|
29
30
|
|
|
30
31
|
---
|
|
31
32
|
|
|
@@ -1700,3 +1701,133 @@ If you remember only one sentence from this handbook, make it this:
|
|
|
1700
1701
|
|
|
1701
1702
|
Everything else is engineering detail — interesting, careful, sometimes subtle — but always in service of that core shape.
|
|
1702
1703
|
|
|
1704
|
+
---
|
|
1705
|
+
|
|
1706
|
+
<a id="app-a"></a>
|
|
1707
|
+
## Appendix A — Eyeling user notes
|
|
1708
|
+
|
|
1709
|
+
This appendix is a compact, user-facing reference for **running Eyeling** and **writing inputs that work well**.
|
|
1710
|
+
For deeper explanations and implementation details, follow the chapter links in each section.
|
|
1711
|
+
|
|
1712
|
+
### A.1 Install and run
|
|
1713
|
+
|
|
1714
|
+
Eyeling is distributed as an npm package.
|
|
1715
|
+
|
|
1716
|
+
- Run without installing:
|
|
1717
|
+
|
|
1718
|
+
```bash
|
|
1719
|
+
npx eyeling --help
|
|
1720
|
+
npx eyeling yourfile.n3
|
|
1721
|
+
```
|
|
1722
|
+
|
|
1723
|
+
- Or install globally:
|
|
1724
|
+
|
|
1725
|
+
```bash
|
|
1726
|
+
npm i -g eyeling
|
|
1727
|
+
eyeling yourfile.n3
|
|
1728
|
+
```
|
|
1729
|
+
|
|
1730
|
+
See also: [Chapter 14 — Entry points: CLI, bundle exports, and npm API](#ch14).
|
|
1731
|
+
|
|
1732
|
+
### A.2 What Eyeling prints
|
|
1733
|
+
|
|
1734
|
+
By default, Eyeling prints **newly derived forward facts** (the heads of fired `=>` rules), serialized as N3.
|
|
1735
|
+
It does **not** reprint your input facts.
|
|
1736
|
+
|
|
1737
|
+
For proof/explanation output and output modes, see:
|
|
1738
|
+
- [Chapter 13 — Printing, proofs, and the user-facing output](#ch13)
|
|
1739
|
+
|
|
1740
|
+
### A.3 CLI quick reference
|
|
1741
|
+
|
|
1742
|
+
The authoritative list is always:
|
|
1743
|
+
|
|
1744
|
+
```bash
|
|
1745
|
+
eyeling --help
|
|
1746
|
+
```
|
|
1747
|
+
|
|
1748
|
+
Options:
|
|
1749
|
+
```
|
|
1750
|
+
-a, --ast Print parsed AST as JSON and exit.
|
|
1751
|
+
-d, --deterministic-skolem Make log:skolem stable across reasoning runs.
|
|
1752
|
+
-e, --enforce-https Rewrite http:// IRIs to https:// for log dereferencing builtins.
|
|
1753
|
+
-h, --help Show this help and exit.
|
|
1754
|
+
-p, --proof-comments Enable proof explanations.
|
|
1755
|
+
-r, --strings Print log:outputString strings (ordered by key) instead of N3 output.
|
|
1756
|
+
-s, --super-restricted Disable all builtins except => and <=.
|
|
1757
|
+
-t, --stream Stream derived triples as soon as they are derived.
|
|
1758
|
+
-v, --version Print version and exit.
|
|
1759
|
+
```
|
|
1760
|
+
|
|
1761
|
+
See also:
|
|
1762
|
+
- [Chapter 13 — Printing, proofs, and the user-facing output](#ch13)
|
|
1763
|
+
- [Chapter 12 — Dereferencing and web-like semantics](#ch12)
|
|
1764
|
+
|
|
1765
|
+
### A.4 N3 syntax notes that matter in practice
|
|
1766
|
+
|
|
1767
|
+
Eyeling implements a practical N3 subset centered around facts and rules.
|
|
1768
|
+
|
|
1769
|
+
- A **fact** is a triple ending in `.`:
|
|
1770
|
+
|
|
1771
|
+
```n3
|
|
1772
|
+
:alice :knows :bob .
|
|
1773
|
+
```
|
|
1774
|
+
|
|
1775
|
+
- A **forward rule**:
|
|
1776
|
+
|
|
1777
|
+
```n3
|
|
1778
|
+
{ ?x :p ?y } => { ?y :q ?x } .
|
|
1779
|
+
```
|
|
1780
|
+
|
|
1781
|
+
- A **backward rule**:
|
|
1782
|
+
|
|
1783
|
+
```n3
|
|
1784
|
+
{ ?x :ancestor ?z } <= { ?x :parent ?z } .
|
|
1785
|
+
```
|
|
1786
|
+
|
|
1787
|
+
Quoted graphs/formulas use `{ ... }`. Inside a quoted formula, directive scope matters:
|
|
1788
|
+
|
|
1789
|
+
- `@prefix/@base` and `PREFIX/BASE` directives may appear at top level **or inside `{ ... }`**, and apply to the formula they occur in (formula-local scoping).
|
|
1790
|
+
|
|
1791
|
+
For the formal grammar, see the N3 spec grammar:
|
|
1792
|
+
- https://w3c.github.io/N3/spec/#grammar
|
|
1793
|
+
|
|
1794
|
+
See also:
|
|
1795
|
+
- [Chapter 4 — From characters to AST: lexing and parsing](#ch04)
|
|
1796
|
+
|
|
1797
|
+
### A.5 Builtins
|
|
1798
|
+
|
|
1799
|
+
Eyeling supports a built-in “standard library” across namespaces like `log:`, `math:`, `string:`, `list:`, `time:`, `crypto:`.
|
|
1800
|
+
|
|
1801
|
+
References:
|
|
1802
|
+
- W3C N3 Built-ins overview: https://w3c.github.io/N3/reports/20230703/builtins.html
|
|
1803
|
+
- Eyeling implementation details: [Chapter 11 — Built-ins as a standard library](#ch11)
|
|
1804
|
+
- The shipped builtin catalogue: `eyeling-builtins.ttl` (in this repo)
|
|
1805
|
+
|
|
1806
|
+
If you are running untrusted inputs, consider `--super-restricted` to disable all builtins except implication.
|
|
1807
|
+
|
|
1808
|
+
### A.6 Skolemization and `log:skolem`
|
|
1809
|
+
|
|
1810
|
+
When forward rule heads contain blank nodes (existentials), Eyeling replaces them with generated Skolem IRIs so derived facts are ground.
|
|
1811
|
+
|
|
1812
|
+
See:
|
|
1813
|
+
- [Chapter 9 — Forward chaining: saturation, skolemization, and meta-rules](#ch09)
|
|
1814
|
+
|
|
1815
|
+
### A.7 Networking and `log:semantics`
|
|
1816
|
+
|
|
1817
|
+
`log:content`, `log:semantics`, and related builtins dereference IRIs and parse retrieved content.
|
|
1818
|
+
This is powerful, but it is also I/O.
|
|
1819
|
+
|
|
1820
|
+
See:
|
|
1821
|
+
- [Chapter 12 — Dereferencing and web-like semantics](#ch12)
|
|
1822
|
+
|
|
1823
|
+
Safety tip:
|
|
1824
|
+
- Use `--super-restricted` if you want to ensure *no* dereferencing (and no other builtins) can run.
|
|
1825
|
+
|
|
1826
|
+
### A.8 Embedding Eyeling in JavaScript
|
|
1827
|
+
|
|
1828
|
+
If you depend on Eyeling as a library, the package exposes:
|
|
1829
|
+
- a CLI wrapper API (`reason(...)`), and
|
|
1830
|
+
- in-process engine entry points (via the bundle exports).
|
|
1831
|
+
|
|
1832
|
+
See:
|
|
1833
|
+
- [Chapter 14 — Entry points: CLI, bundle exports, and npm API](#ch14)
|
package/examples/get-uuid.n3
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
# Example from Wout Slabbinck
|
|
4
4
|
# ===========================
|
|
5
5
|
|
|
6
|
+
@prefix list: <http://www.w3.org/2000/10/swap/list#> .
|
|
6
7
|
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
|
|
7
8
|
@prefix string: <http://www.w3.org/2000/10/swap/string#> .
|
|
8
9
|
@prefix log: <http://www.w3.org/2000/10/swap/log#> .
|
|
@@ -12,16 +13,20 @@
|
|
|
12
13
|
|
|
13
14
|
# uuid backward rule (component)
|
|
14
15
|
{
|
|
15
|
-
?input :getUUID ?urnUuid
|
|
16
|
+
?input :getUUID ?urnUuid
|
|
16
17
|
}
|
|
17
|
-
<=
|
|
18
|
+
<=
|
|
18
19
|
{
|
|
20
|
+
# 0. add some skolem uri to introduce randomness when there are multiple runs with the same ID
|
|
21
|
+
( "test" ) log:skolem ?skolem .
|
|
22
|
+
(?input (?skolem) ) list:append ?newList .
|
|
23
|
+
|
|
19
24
|
# 1. Convert input to a stable string
|
|
20
|
-
?
|
|
21
|
-
|
|
25
|
+
?newList :listToString ?inputString .
|
|
26
|
+
|
|
22
27
|
# 2. Generate a stable hash (works identically in 2026 eyeJS and Eyeling)
|
|
23
28
|
?inputString crypto:sha ?hash .
|
|
24
|
-
|
|
29
|
+
|
|
25
30
|
# 3. Format the hash into a UUID-compliant structure (8-4-4-4-12)
|
|
26
31
|
( ?hash "^(.{8}).*$" ) string:scrape ?p1 .
|
|
27
32
|
( ?hash "^.{8}(.{4}).*$" ) string:scrape ?p2 .
|
|
@@ -29,7 +34,7 @@
|
|
|
29
34
|
( ?hash "^.{16}(.{4}).*$" ) string:scrape ?p4 .
|
|
30
35
|
( ?hash "^.{20}(.{12}).*$" ) string:scrape ?p5 .
|
|
31
36
|
( "urn:uuid:" ?p1 "-" ?p2 "-" ?p3 "-" ?p4 "-" ?p5 ) string:concatenation ?urnUuidString .
|
|
32
|
-
|
|
37
|
+
|
|
33
38
|
# 4. Cast the final string to a URI
|
|
34
39
|
?urnUuid log:uri ?urnUuidString .
|
|
35
40
|
} .
|
|
@@ -38,16 +43,16 @@
|
|
|
38
43
|
{ () :listToString "" } <= { } .
|
|
39
44
|
|
|
40
45
|
# 2. Recursive Case: Process list using rdf:first and rdf:rest
|
|
41
|
-
{
|
|
46
|
+
{ ?list :listToString ?result } <= {
|
|
42
47
|
?list rdf:first ?head .
|
|
43
48
|
?list rdf:rest ?tail .
|
|
44
|
-
|
|
49
|
+
|
|
45
50
|
# Convert the current URI to a string
|
|
46
51
|
?head log:uri ?headStr .
|
|
47
|
-
|
|
52
|
+
|
|
48
53
|
# Recursively convert the tail of the list
|
|
49
54
|
?tail :listToString ?tailStr .
|
|
50
|
-
|
|
55
|
+
|
|
51
56
|
# Combine head and tail strings
|
|
52
57
|
( ?headStr ?tailStr ) string:concatenation ?result .
|
|
53
58
|
} .
|
|
@@ -55,11 +60,10 @@
|
|
|
55
60
|
<test> a odrl:Policy .
|
|
56
61
|
<lol> a odrl:Policy .
|
|
57
62
|
|
|
58
|
-
{
|
|
63
|
+
{
|
|
59
64
|
?policy a odrl:Policy .
|
|
60
65
|
( ?policy ) :getUUID ?urnUuid .
|
|
61
66
|
}
|
|
62
67
|
=>
|
|
63
|
-
{
|
|
64
|
-
|
|
65
|
-
} .
|
|
68
|
+
{ ?urnUuid <a> <b> } .
|
|
69
|
+
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
<urn:uuid:
|
|
2
|
-
<urn:uuid:
|
|
1
|
+
<urn:uuid:ad88d7b6-5b37-4eeb-a044-7bca1ffc366c> <a> <b> .
|
|
2
|
+
<urn:uuid:37d41865-0910-9953-46c7-01359fbab6fa> <a> <b> .
|
package/eyeling.js
CHANGED
|
@@ -493,6 +493,10 @@ function __fetchHttpTextViaSubprocess(url) {
|
|
|
493
493
|
path: uu.pathname + uu.search,
|
|
494
494
|
headers: {
|
|
495
495
|
'accept': 'text/n3, text/turtle, application/n-triples, application/n-quads, text/plain;q=0.1, */*;q=0.01',
|
|
496
|
+
// Ask for an uncompressed response when possible; some servers send
|
|
497
|
+
// compressed bodies that are not valid UTF-8 text for the parser.
|
|
498
|
+
// We still handle common encodings below if they are returned anyway.
|
|
499
|
+
'accept-encoding': 'identity',
|
|
496
500
|
'user-agent': 'eyeling-log-builtins'
|
|
497
501
|
}
|
|
498
502
|
};
|
|
@@ -509,10 +513,29 @@ function __fetchHttpTextViaSubprocess(url) {
|
|
|
509
513
|
console.error('HTTP status ' + sc);
|
|
510
514
|
process.exit(4);
|
|
511
515
|
}
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
res.on('
|
|
515
|
-
|
|
516
|
+
const chunks = [];
|
|
517
|
+
res.on('data', (c) => { chunks.push(c); });
|
|
518
|
+
res.on('end', () => {
|
|
519
|
+
try {
|
|
520
|
+
const { Buffer } = require('buffer');
|
|
521
|
+
const zlib = require('zlib');
|
|
522
|
+
const buf = Buffer.concat(chunks);
|
|
523
|
+
const enc = ((res.headers && res.headers['content-encoding']) || '').toString().toLowerCase();
|
|
524
|
+
let out = buf;
|
|
525
|
+
if (enc.includes('gzip')) out = zlib.gunzipSync(buf);
|
|
526
|
+
else if (enc.includes('deflate')) out = zlib.inflateSync(buf);
|
|
527
|
+
else if (enc.includes('br')) out = zlib.brotliDecompressSync(buf);
|
|
528
|
+
process.stdout.write(out.toString('utf8'));
|
|
529
|
+
} catch (e) {
|
|
530
|
+
// Best-effort fallback: treat as UTF-8.
|
|
531
|
+
try {
|
|
532
|
+
const { Buffer } = require('buffer');
|
|
533
|
+
process.stdout.write(Buffer.concat(chunks).toString('utf8'));
|
|
534
|
+
} catch {
|
|
535
|
+
process.exit(6);
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
});
|
|
516
539
|
});
|
|
517
540
|
req.on('error', (e) => { console.error(e && e.message ? e.message : String(e)); process.exit(5); });
|
|
518
541
|
req.end();
|
|
@@ -7308,6 +7331,46 @@ class Parser {
|
|
|
7308
7331
|
parseGraph() {
|
|
7309
7332
|
const triples = [];
|
|
7310
7333
|
while (this.peek().typ !== 'RBrace') {
|
|
7334
|
+
// N3 allows @prefix/@base and SPARQL-style PREFIX/BASE directives anywhere
|
|
7335
|
+
// outside of a triple. This includes inside quoted graph terms.
|
|
7336
|
+
// These directives affect parsing (prefix/base resolution) but do not emit triples.
|
|
7337
|
+
if (this.peek().typ === 'AtPrefix') {
|
|
7338
|
+
this.next();
|
|
7339
|
+
this.parsePrefixDirective();
|
|
7340
|
+
continue;
|
|
7341
|
+
}
|
|
7342
|
+
if (this.peek().typ === 'AtBase') {
|
|
7343
|
+
this.next();
|
|
7344
|
+
this.parseBaseDirective();
|
|
7345
|
+
continue;
|
|
7346
|
+
}
|
|
7347
|
+
if (
|
|
7348
|
+
this.peek().typ === 'Ident' &&
|
|
7349
|
+
typeof this.peek().value === 'string' &&
|
|
7350
|
+
this.peek().value.toLowerCase() === 'prefix' &&
|
|
7351
|
+
this.toks[this.pos + 1] &&
|
|
7352
|
+
this.toks[this.pos + 1].typ === 'Ident' &&
|
|
7353
|
+
typeof this.toks[this.pos + 1].value === 'string' &&
|
|
7354
|
+
this.toks[this.pos + 1].value.endsWith(':') &&
|
|
7355
|
+
this.toks[this.pos + 2] &&
|
|
7356
|
+
(this.toks[this.pos + 2].typ === 'IriRef' || this.toks[this.pos + 2].typ === 'Ident')
|
|
7357
|
+
) {
|
|
7358
|
+
this.next();
|
|
7359
|
+
this.parseSparqlPrefixDirective();
|
|
7360
|
+
continue;
|
|
7361
|
+
}
|
|
7362
|
+
if (
|
|
7363
|
+
this.peek().typ === 'Ident' &&
|
|
7364
|
+
typeof this.peek().value === 'string' &&
|
|
7365
|
+
this.peek().value.toLowerCase() === 'base' &&
|
|
7366
|
+
this.toks[this.pos + 1] &&
|
|
7367
|
+
(this.toks[this.pos + 1].typ === 'IriRef' || this.toks[this.pos + 1].typ === 'Ident')
|
|
7368
|
+
) {
|
|
7369
|
+
this.next();
|
|
7370
|
+
this.parseSparqlBaseDirective();
|
|
7371
|
+
continue;
|
|
7372
|
+
}
|
|
7373
|
+
|
|
7311
7374
|
const left = this.parseTerm();
|
|
7312
7375
|
if (this.peek().typ === 'OpImplies') {
|
|
7313
7376
|
this.next();
|
package/lib/deref.js
CHANGED
|
@@ -162,6 +162,10 @@ function __fetchHttpTextViaSubprocess(url) {
|
|
|
162
162
|
path: uu.pathname + uu.search,
|
|
163
163
|
headers: {
|
|
164
164
|
'accept': 'text/n3, text/turtle, application/n-triples, application/n-quads, text/plain;q=0.1, */*;q=0.01',
|
|
165
|
+
// Ask for an uncompressed response when possible; some servers send
|
|
166
|
+
// compressed bodies that are not valid UTF-8 text for the parser.
|
|
167
|
+
// We still handle common encodings below if they are returned anyway.
|
|
168
|
+
'accept-encoding': 'identity',
|
|
165
169
|
'user-agent': 'eyeling-log-builtins'
|
|
166
170
|
}
|
|
167
171
|
};
|
|
@@ -178,10 +182,29 @@ function __fetchHttpTextViaSubprocess(url) {
|
|
|
178
182
|
console.error('HTTP status ' + sc);
|
|
179
183
|
process.exit(4);
|
|
180
184
|
}
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
res.on('
|
|
184
|
-
|
|
185
|
+
const chunks = [];
|
|
186
|
+
res.on('data', (c) => { chunks.push(c); });
|
|
187
|
+
res.on('end', () => {
|
|
188
|
+
try {
|
|
189
|
+
const { Buffer } = require('buffer');
|
|
190
|
+
const zlib = require('zlib');
|
|
191
|
+
const buf = Buffer.concat(chunks);
|
|
192
|
+
const enc = ((res.headers && res.headers['content-encoding']) || '').toString().toLowerCase();
|
|
193
|
+
let out = buf;
|
|
194
|
+
if (enc.includes('gzip')) out = zlib.gunzipSync(buf);
|
|
195
|
+
else if (enc.includes('deflate')) out = zlib.inflateSync(buf);
|
|
196
|
+
else if (enc.includes('br')) out = zlib.brotliDecompressSync(buf);
|
|
197
|
+
process.stdout.write(out.toString('utf8'));
|
|
198
|
+
} catch (e) {
|
|
199
|
+
// Best-effort fallback: treat as UTF-8.
|
|
200
|
+
try {
|
|
201
|
+
const { Buffer } = require('buffer');
|
|
202
|
+
process.stdout.write(Buffer.concat(chunks).toString('utf8'));
|
|
203
|
+
} catch {
|
|
204
|
+
process.exit(6);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
});
|
|
185
208
|
});
|
|
186
209
|
req.on('error', (e) => { console.error(e && e.message ? e.message : String(e)); process.exit(5); });
|
|
187
210
|
req.end();
|
package/lib/parser.js
CHANGED
|
@@ -461,6 +461,46 @@ class Parser {
|
|
|
461
461
|
parseGraph() {
|
|
462
462
|
const triples = [];
|
|
463
463
|
while (this.peek().typ !== 'RBrace') {
|
|
464
|
+
// N3 allows @prefix/@base and SPARQL-style PREFIX/BASE directives anywhere
|
|
465
|
+
// outside of a triple. This includes inside quoted graph terms.
|
|
466
|
+
// These directives affect parsing (prefix/base resolution) but do not emit triples.
|
|
467
|
+
if (this.peek().typ === 'AtPrefix') {
|
|
468
|
+
this.next();
|
|
469
|
+
this.parsePrefixDirective();
|
|
470
|
+
continue;
|
|
471
|
+
}
|
|
472
|
+
if (this.peek().typ === 'AtBase') {
|
|
473
|
+
this.next();
|
|
474
|
+
this.parseBaseDirective();
|
|
475
|
+
continue;
|
|
476
|
+
}
|
|
477
|
+
if (
|
|
478
|
+
this.peek().typ === 'Ident' &&
|
|
479
|
+
typeof this.peek().value === 'string' &&
|
|
480
|
+
this.peek().value.toLowerCase() === 'prefix' &&
|
|
481
|
+
this.toks[this.pos + 1] &&
|
|
482
|
+
this.toks[this.pos + 1].typ === 'Ident' &&
|
|
483
|
+
typeof this.toks[this.pos + 1].value === 'string' &&
|
|
484
|
+
this.toks[this.pos + 1].value.endsWith(':') &&
|
|
485
|
+
this.toks[this.pos + 2] &&
|
|
486
|
+
(this.toks[this.pos + 2].typ === 'IriRef' || this.toks[this.pos + 2].typ === 'Ident')
|
|
487
|
+
) {
|
|
488
|
+
this.next();
|
|
489
|
+
this.parseSparqlPrefixDirective();
|
|
490
|
+
continue;
|
|
491
|
+
}
|
|
492
|
+
if (
|
|
493
|
+
this.peek().typ === 'Ident' &&
|
|
494
|
+
typeof this.peek().value === 'string' &&
|
|
495
|
+
this.peek().value.toLowerCase() === 'base' &&
|
|
496
|
+
this.toks[this.pos + 1] &&
|
|
497
|
+
(this.toks[this.pos + 1].typ === 'IriRef' || this.toks[this.pos + 1].typ === 'Ident')
|
|
498
|
+
) {
|
|
499
|
+
this.next();
|
|
500
|
+
this.parseSparqlBaseDirective();
|
|
501
|
+
continue;
|
|
502
|
+
}
|
|
503
|
+
|
|
464
504
|
const left = this.parseTerm();
|
|
465
505
|
if (this.peek().typ === 'OpImplies') {
|
|
466
506
|
this.next();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eyeling",
|
|
3
|
-
"version": "1.10.
|
|
3
|
+
"version": "1.10.12",
|
|
4
4
|
"description": "A minimal Notation3 (N3) reasoner in JavaScript.",
|
|
5
5
|
"main": "./index.js",
|
|
6
6
|
"keywords": [
|
|
@@ -40,6 +40,7 @@
|
|
|
40
40
|
"test:api": "node test/api.test.js",
|
|
41
41
|
"test:n3gen": "node test/n3gen.test.js",
|
|
42
42
|
"test:examples": "node test/examples.test.js",
|
|
43
|
+
"test:manifest": "node test/manifest.test.js",
|
|
43
44
|
"test:package": "node test/package.test.js",
|
|
44
45
|
"test": "npm run build && npm run test:packlist && npm run test:api && npm run test:n3gen && npm run test:examples",
|
|
45
46
|
"preversion": "npm test",
|