fitch-js 0.1.0 → 1.0.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 +34 -13
- package/dist/cjs/index.js +6 -0
- package/dist/cjs/proof/index.js +6 -0
- package/dist/cjs/proof/textParser.js +74 -21
- package/dist/cjs/proof/types.js +1 -1
- package/dist/esm/index.js +1 -1
- package/dist/esm/proof/index.js +1 -1
- package/dist/esm/proof/textParser.js +73 -21
- package/dist/esm/proof/types.js +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
# Fitch-JS
|
|
2
2
|
|
|
3
|
+
[](https://www.npmjs.com/package/fitch-js)
|
|
4
|
+
[](https://github.com/lagomorph-labs/fitch-js/blob/main/LICENSE)
|
|
5
|
+
|
|
3
6
|
**We are not affiliated with the [Open Logic Project](https://openlogicproject.org/) or [Carnap](https://carnap.io/) in any way. (Currently)**
|
|
4
7
|
|
|
5
8
|
This is a JavaScript library for validating Fitch-style natural deduction proofs. It provides functionality to check the validity of logical proofs in both propositional and first-order logic entirely in the browser, with no server-side dependencies.
|
|
@@ -154,24 +157,26 @@ fitch-js/
|
|
|
154
157
|
└── package.json
|
|
155
158
|
```
|
|
156
159
|
|
|
157
|
-
##
|
|
160
|
+
## Installation
|
|
158
161
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
```
|
|
162
|
+
```bash
|
|
163
|
+
npm install fitch-js
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
Or with yarn:
|
|
167
|
+
|
|
168
|
+
```bash
|
|
169
|
+
yarn add fitch-js
|
|
170
|
+
```
|
|
169
171
|
|
|
170
172
|
## Usage
|
|
171
173
|
|
|
172
174
|
```javascript
|
|
173
|
-
|
|
174
|
-
|
|
175
|
+
// ESM
|
|
176
|
+
import { parseFormula, checkProof, parseProofText } from 'fitch-js';
|
|
177
|
+
|
|
178
|
+
// CommonJS
|
|
179
|
+
const { parseFormula, checkProof, parseProofText } = require('fitch-js');
|
|
175
180
|
|
|
176
181
|
// Example: Existential Elimination
|
|
177
182
|
const proof = {
|
|
@@ -251,6 +256,22 @@ Restrictions:
|
|
|
251
256
|
- Subproof must start with assumption P(c)
|
|
252
257
|
- Q must be derivable from the subproof
|
|
253
258
|
|
|
259
|
+
## Development
|
|
260
|
+
|
|
261
|
+
1. Clone the repository
|
|
262
|
+
2. Install dependencies:
|
|
263
|
+
```bash
|
|
264
|
+
npm install
|
|
265
|
+
```
|
|
266
|
+
3. Run tests:
|
|
267
|
+
```bash
|
|
268
|
+
npm test
|
|
269
|
+
```
|
|
270
|
+
4. Build:
|
|
271
|
+
```bash
|
|
272
|
+
npm run build
|
|
273
|
+
```
|
|
274
|
+
|
|
254
275
|
## Contributing
|
|
255
276
|
|
|
256
277
|
Contributions are welcome! Please feel free to submit a Pull Request. Before contributing:
|
package/dist/cjs/index.js
CHANGED
|
@@ -75,6 +75,12 @@ Object.defineProperty(exports, "getLineForPosition", {
|
|
|
75
75
|
return _index.getLineForPosition;
|
|
76
76
|
}
|
|
77
77
|
});
|
|
78
|
+
Object.defineProperty(exports, "getProofLineForDocumentLine", {
|
|
79
|
+
enumerable: true,
|
|
80
|
+
get: function get() {
|
|
81
|
+
return _index.getProofLineForDocumentLine;
|
|
82
|
+
}
|
|
83
|
+
});
|
|
78
84
|
Object.defineProperty(exports, "isLineAvailable", {
|
|
79
85
|
enumerable: true,
|
|
80
86
|
get: function get() {
|
package/dist/cjs/proof/index.js
CHANGED
|
@@ -21,6 +21,12 @@ Object.defineProperty(exports, "getLineForPosition", {
|
|
|
21
21
|
return _textParser.getLineForPosition;
|
|
22
22
|
}
|
|
23
23
|
});
|
|
24
|
+
Object.defineProperty(exports, "getProofLineForDocumentLine", {
|
|
25
|
+
enumerable: true,
|
|
26
|
+
get: function get() {
|
|
27
|
+
return _textParser.getProofLineForDocumentLine;
|
|
28
|
+
}
|
|
29
|
+
});
|
|
24
30
|
Object.defineProperty(exports, "parseProofText", {
|
|
25
31
|
enumerable: true,
|
|
26
32
|
get: function get() {
|
|
@@ -5,6 +5,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.getDocumentLineForProofLine = getDocumentLineForProofLine;
|
|
7
7
|
exports.getLineForPosition = getLineForPosition;
|
|
8
|
+
exports.getProofLineForDocumentLine = getProofLineForDocumentLine;
|
|
8
9
|
exports.parseProofText = parseProofText;
|
|
9
10
|
var _parser = require("../parser.js");
|
|
10
11
|
var _symbols = require("../symbols.js");
|
|
@@ -59,17 +60,30 @@ function parseProofText(text) {
|
|
|
59
60
|
var goalText = null;
|
|
60
61
|
/** @type {number[]} */
|
|
61
62
|
var subproofStack = [];
|
|
63
|
+
|
|
64
|
+
// Build document line -> proof line mapping for citation translation
|
|
65
|
+
// Users write document line numbers (1-indexed), we need proof line numbers
|
|
66
|
+
/** @type {Map<number, number>} */
|
|
67
|
+
var docToProofLine = new Map();
|
|
68
|
+
var proofCount = 0;
|
|
62
69
|
for (var i = 0; i < rawLines.length; i++) {
|
|
63
|
-
var
|
|
64
|
-
|
|
70
|
+
var trimmed = rawLines[i].trim();
|
|
71
|
+
if (trimmed && !trimmed.startsWith('//')) {
|
|
72
|
+
proofCount++;
|
|
73
|
+
docToProofLine.set(i + 1, proofCount); // 1-indexed doc line -> 1-indexed proof line
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
for (var _i = 0; _i < rawLines.length; _i++) {
|
|
77
|
+
var raw = rawLines[_i];
|
|
78
|
+
var _trimmed = raw.trim();
|
|
65
79
|
|
|
66
80
|
// Skip empty lines
|
|
67
|
-
if (!
|
|
81
|
+
if (!_trimmed) continue;
|
|
68
82
|
|
|
69
83
|
// Handle comments
|
|
70
|
-
if (
|
|
84
|
+
if (_trimmed.startsWith('//')) {
|
|
71
85
|
// Check for goal declaration
|
|
72
|
-
var goalMatch =
|
|
86
|
+
var goalMatch = _trimmed.match(/\/\/\s*Goal:\s*(.+)/i);
|
|
73
87
|
if (goalMatch) {
|
|
74
88
|
goalText = goalMatch[1].trim();
|
|
75
89
|
try {
|
|
@@ -95,38 +109,55 @@ function parseProofText(text) {
|
|
|
95
109
|
}
|
|
96
110
|
|
|
97
111
|
// Parse the line content (strip leading pipes and whitespace)
|
|
98
|
-
var content =
|
|
112
|
+
var content = _trimmed.replace(/^\|+\s*/, '');
|
|
99
113
|
var colonIndex = content.lastIndexOf(':');
|
|
100
114
|
var formulaText = '';
|
|
101
115
|
var ruleText = '';
|
|
102
116
|
/** @type {number[]} */
|
|
103
117
|
var citations = [];
|
|
104
118
|
/** @type {SubproofCitation[]} */
|
|
105
|
-
var
|
|
119
|
+
var subproofs = [];
|
|
120
|
+
/** @type {string[]} */
|
|
121
|
+
var issues = [];
|
|
106
122
|
if (colonIndex !== -1) {
|
|
107
123
|
formulaText = content.substring(0, colonIndex).trim();
|
|
108
124
|
var rulePart = content.substring(colonIndex + 1).trim();
|
|
109
125
|
var ruleParts = rulePart.split(/\s+/);
|
|
110
126
|
ruleText = ruleParts[0] || '';
|
|
111
127
|
|
|
112
|
-
// Parse citations
|
|
128
|
+
// Parse citations - translate from document line numbers to proof line numbers
|
|
113
129
|
for (var j = 1; j < ruleParts.length; j++) {
|
|
114
130
|
var cit = ruleParts[j];
|
|
115
131
|
if (cit.includes('-')) {
|
|
116
132
|
var _cit$split$map = cit.split('-').map(Number),
|
|
117
133
|
_cit$split$map2 = _slicedToArray(_cit$split$map, 2),
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
if (!isNaN(
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
134
|
+
startDoc = _cit$split$map2[0],
|
|
135
|
+
endDoc = _cit$split$map2[1];
|
|
136
|
+
if (!isNaN(startDoc) && !isNaN(endDoc)) {
|
|
137
|
+
// Translate document lines to proof lines
|
|
138
|
+
var start = docToProofLine.get(startDoc);
|
|
139
|
+
var end = docToProofLine.get(endDoc);
|
|
140
|
+
if (start === undefined || end === undefined) {
|
|
141
|
+
// Invalid citation - reference to non-proof line (comment/blank)
|
|
142
|
+
issues.push("Invalid subproof citation ".concat(cit, ": references non-proof line"));
|
|
143
|
+
} else {
|
|
144
|
+
subproofs.push({
|
|
145
|
+
start: start,
|
|
146
|
+
end: end
|
|
147
|
+
});
|
|
148
|
+
}
|
|
125
149
|
}
|
|
126
150
|
} else {
|
|
127
|
-
var
|
|
128
|
-
if (!isNaN(
|
|
129
|
-
|
|
151
|
+
var docLineNum = parseInt(cit, 10);
|
|
152
|
+
if (!isNaN(docLineNum)) {
|
|
153
|
+
// Translate document line to proof line
|
|
154
|
+
var proofLineNum = docToProofLine.get(docLineNum);
|
|
155
|
+
if (proofLineNum === undefined) {
|
|
156
|
+
// Invalid citation - reference to non-proof line (comment/blank)
|
|
157
|
+
issues.push("Invalid citation ".concat(docLineNum, ": references non-proof line"));
|
|
158
|
+
} else {
|
|
159
|
+
citations.push(proofLineNum);
|
|
160
|
+
}
|
|
130
161
|
}
|
|
131
162
|
}
|
|
132
163
|
}
|
|
@@ -137,8 +168,6 @@ function parseProofText(text) {
|
|
|
137
168
|
// Parse formula
|
|
138
169
|
/** @type {Formula|null} */
|
|
139
170
|
var formula = null;
|
|
140
|
-
/** @type {string[]} */
|
|
141
|
-
var issues = [];
|
|
142
171
|
try {
|
|
143
172
|
if (formulaText) {
|
|
144
173
|
formula = (0, _parser.parseFormula)((0, _symbols.convertAsciiToSymbols)(formulaText));
|
|
@@ -161,7 +190,7 @@ function parseProofText(text) {
|
|
|
161
190
|
formula: formula,
|
|
162
191
|
rule: normalizedRule,
|
|
163
192
|
citations: citations,
|
|
164
|
-
|
|
193
|
+
subproofs: subproofs,
|
|
165
194
|
depth: depth,
|
|
166
195
|
location: [].concat(subproofStack),
|
|
167
196
|
issues: issues
|
|
@@ -219,4 +248,28 @@ function getDocumentLineForProofLine(text, proofLineNum) {
|
|
|
219
248
|
}
|
|
220
249
|
}
|
|
221
250
|
return 0;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* Finds the proof line number for a given document line number
|
|
255
|
+
*
|
|
256
|
+
* @param {string} text - The original document text
|
|
257
|
+
* @param {number} documentLineNum - The 1-indexed document line number (as users see it)
|
|
258
|
+
* @returns {number} The 1-indexed proof line number, or 0 if not a proof line
|
|
259
|
+
*/
|
|
260
|
+
function getProofLineForDocumentLine(text, documentLineNum) {
|
|
261
|
+
var textLines = text.split('\n');
|
|
262
|
+
var proofLineCount = 0;
|
|
263
|
+
var targetIndex = documentLineNum - 1; // Convert to 0-indexed
|
|
264
|
+
|
|
265
|
+
for (var i = 0; i < textLines.length; i++) {
|
|
266
|
+
var trimmed = textLines[i].trim();
|
|
267
|
+
if (trimmed && !trimmed.startsWith('//')) {
|
|
268
|
+
proofLineCount++;
|
|
269
|
+
if (i === targetIndex) {
|
|
270
|
+
return proofLineCount;
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
return 0; // Not a valid proof line
|
|
222
275
|
}
|
package/dist/cjs/proof/types.js
CHANGED
|
@@ -21,7 +21,7 @@ exports["default"] = exports.RULE_MAP = void 0;
|
|
|
21
21
|
* @property {Formula|null} formula - The parsed formula, or null if parsing failed
|
|
22
22
|
* @property {string} rule - The normalized rule name (e.g., '∧I', 'Pr')
|
|
23
23
|
* @property {number[]} citations - Line numbers cited in justification
|
|
24
|
-
* @property {SubproofCitation[]}
|
|
24
|
+
* @property {SubproofCitation[]} subproofs - Subproof ranges cited
|
|
25
25
|
* @property {number} depth - Subproof nesting depth (0 = main proof)
|
|
26
26
|
* @property {number[]} location - Path through subproof tree
|
|
27
27
|
* @property {string[]} issues - Parse errors for this line
|
package/dist/esm/index.js
CHANGED
|
@@ -14,4 +14,4 @@ export { isVariable, isLineAvailable, isValidCitation } from './ruleValidators.j
|
|
|
14
14
|
export { convertAsciiToSymbols, convertSymbolsToAscii, symbolMappings } from './symbols.js';
|
|
15
15
|
|
|
16
16
|
// Text-format proof parsing
|
|
17
|
-
export { parseProofText, getLineForPosition, getDocumentLineForProofLine, RULE_MAP } from './proof/index.js';
|
|
17
|
+
export { parseProofText, getLineForPosition, getDocumentLineForProofLine, getProofLineForDocumentLine, RULE_MAP } from './proof/index.js';
|
package/dist/esm/proof/index.js
CHANGED
|
@@ -3,5 +3,5 @@
|
|
|
3
3
|
* @module proof
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
export { parseProofText, getLineForPosition, getDocumentLineForProofLine } from './textParser.js';
|
|
6
|
+
export { parseProofText, getLineForPosition, getDocumentLineForProofLine, getProofLineForDocumentLine } from './textParser.js';
|
|
7
7
|
export { RULE_MAP } from './types.js';
|
|
@@ -54,17 +54,30 @@ export function parseProofText(text) {
|
|
|
54
54
|
var goalText = null;
|
|
55
55
|
/** @type {number[]} */
|
|
56
56
|
var subproofStack = [];
|
|
57
|
+
|
|
58
|
+
// Build document line -> proof line mapping for citation translation
|
|
59
|
+
// Users write document line numbers (1-indexed), we need proof line numbers
|
|
60
|
+
/** @type {Map<number, number>} */
|
|
61
|
+
var docToProofLine = new Map();
|
|
62
|
+
var proofCount = 0;
|
|
57
63
|
for (var i = 0; i < rawLines.length; i++) {
|
|
58
|
-
var
|
|
59
|
-
|
|
64
|
+
var trimmed = rawLines[i].trim();
|
|
65
|
+
if (trimmed && !trimmed.startsWith('//')) {
|
|
66
|
+
proofCount++;
|
|
67
|
+
docToProofLine.set(i + 1, proofCount); // 1-indexed doc line -> 1-indexed proof line
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
for (var _i = 0; _i < rawLines.length; _i++) {
|
|
71
|
+
var raw = rawLines[_i];
|
|
72
|
+
var _trimmed = raw.trim();
|
|
60
73
|
|
|
61
74
|
// Skip empty lines
|
|
62
|
-
if (!
|
|
75
|
+
if (!_trimmed) continue;
|
|
63
76
|
|
|
64
77
|
// Handle comments
|
|
65
|
-
if (
|
|
78
|
+
if (_trimmed.startsWith('//')) {
|
|
66
79
|
// Check for goal declaration
|
|
67
|
-
var goalMatch =
|
|
80
|
+
var goalMatch = _trimmed.match(/\/\/\s*Goal:\s*(.+)/i);
|
|
68
81
|
if (goalMatch) {
|
|
69
82
|
goalText = goalMatch[1].trim();
|
|
70
83
|
try {
|
|
@@ -90,38 +103,55 @@ export function parseProofText(text) {
|
|
|
90
103
|
}
|
|
91
104
|
|
|
92
105
|
// Parse the line content (strip leading pipes and whitespace)
|
|
93
|
-
var content =
|
|
106
|
+
var content = _trimmed.replace(/^\|+\s*/, '');
|
|
94
107
|
var colonIndex = content.lastIndexOf(':');
|
|
95
108
|
var formulaText = '';
|
|
96
109
|
var ruleText = '';
|
|
97
110
|
/** @type {number[]} */
|
|
98
111
|
var citations = [];
|
|
99
112
|
/** @type {SubproofCitation[]} */
|
|
100
|
-
var
|
|
113
|
+
var subproofs = [];
|
|
114
|
+
/** @type {string[]} */
|
|
115
|
+
var issues = [];
|
|
101
116
|
if (colonIndex !== -1) {
|
|
102
117
|
formulaText = content.substring(0, colonIndex).trim();
|
|
103
118
|
var rulePart = content.substring(colonIndex + 1).trim();
|
|
104
119
|
var ruleParts = rulePart.split(/\s+/);
|
|
105
120
|
ruleText = ruleParts[0] || '';
|
|
106
121
|
|
|
107
|
-
// Parse citations
|
|
122
|
+
// Parse citations - translate from document line numbers to proof line numbers
|
|
108
123
|
for (var j = 1; j < ruleParts.length; j++) {
|
|
109
124
|
var cit = ruleParts[j];
|
|
110
125
|
if (cit.includes('-')) {
|
|
111
126
|
var _cit$split$map = cit.split('-').map(Number),
|
|
112
127
|
_cit$split$map2 = _slicedToArray(_cit$split$map, 2),
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
if (!isNaN(
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
128
|
+
startDoc = _cit$split$map2[0],
|
|
129
|
+
endDoc = _cit$split$map2[1];
|
|
130
|
+
if (!isNaN(startDoc) && !isNaN(endDoc)) {
|
|
131
|
+
// Translate document lines to proof lines
|
|
132
|
+
var start = docToProofLine.get(startDoc);
|
|
133
|
+
var end = docToProofLine.get(endDoc);
|
|
134
|
+
if (start === undefined || end === undefined) {
|
|
135
|
+
// Invalid citation - reference to non-proof line (comment/blank)
|
|
136
|
+
issues.push("Invalid subproof citation ".concat(cit, ": references non-proof line"));
|
|
137
|
+
} else {
|
|
138
|
+
subproofs.push({
|
|
139
|
+
start: start,
|
|
140
|
+
end: end
|
|
141
|
+
});
|
|
142
|
+
}
|
|
120
143
|
}
|
|
121
144
|
} else {
|
|
122
|
-
var
|
|
123
|
-
if (!isNaN(
|
|
124
|
-
|
|
145
|
+
var docLineNum = parseInt(cit, 10);
|
|
146
|
+
if (!isNaN(docLineNum)) {
|
|
147
|
+
// Translate document line to proof line
|
|
148
|
+
var proofLineNum = docToProofLine.get(docLineNum);
|
|
149
|
+
if (proofLineNum === undefined) {
|
|
150
|
+
// Invalid citation - reference to non-proof line (comment/blank)
|
|
151
|
+
issues.push("Invalid citation ".concat(docLineNum, ": references non-proof line"));
|
|
152
|
+
} else {
|
|
153
|
+
citations.push(proofLineNum);
|
|
154
|
+
}
|
|
125
155
|
}
|
|
126
156
|
}
|
|
127
157
|
}
|
|
@@ -132,8 +162,6 @@ export function parseProofText(text) {
|
|
|
132
162
|
// Parse formula
|
|
133
163
|
/** @type {Formula|null} */
|
|
134
164
|
var formula = null;
|
|
135
|
-
/** @type {string[]} */
|
|
136
|
-
var issues = [];
|
|
137
165
|
try {
|
|
138
166
|
if (formulaText) {
|
|
139
167
|
formula = parseFormula(convertAsciiToSymbols(formulaText));
|
|
@@ -156,7 +184,7 @@ export function parseProofText(text) {
|
|
|
156
184
|
formula: formula,
|
|
157
185
|
rule: normalizedRule,
|
|
158
186
|
citations: citations,
|
|
159
|
-
|
|
187
|
+
subproofs: subproofs,
|
|
160
188
|
depth: depth,
|
|
161
189
|
location: [].concat(subproofStack),
|
|
162
190
|
issues: issues
|
|
@@ -214,4 +242,28 @@ export function getDocumentLineForProofLine(text, proofLineNum) {
|
|
|
214
242
|
}
|
|
215
243
|
}
|
|
216
244
|
return 0;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* Finds the proof line number for a given document line number
|
|
249
|
+
*
|
|
250
|
+
* @param {string} text - The original document text
|
|
251
|
+
* @param {number} documentLineNum - The 1-indexed document line number (as users see it)
|
|
252
|
+
* @returns {number} The 1-indexed proof line number, or 0 if not a proof line
|
|
253
|
+
*/
|
|
254
|
+
export function getProofLineForDocumentLine(text, documentLineNum) {
|
|
255
|
+
var textLines = text.split('\n');
|
|
256
|
+
var proofLineCount = 0;
|
|
257
|
+
var targetIndex = documentLineNum - 1; // Convert to 0-indexed
|
|
258
|
+
|
|
259
|
+
for (var i = 0; i < textLines.length; i++) {
|
|
260
|
+
var trimmed = textLines[i].trim();
|
|
261
|
+
if (trimmed && !trimmed.startsWith('//')) {
|
|
262
|
+
proofLineCount++;
|
|
263
|
+
if (i === targetIndex) {
|
|
264
|
+
return proofLineCount;
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
return 0; // Not a valid proof line
|
|
217
269
|
}
|
package/dist/esm/proof/types.js
CHANGED
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
* @property {Formula|null} formula - The parsed formula, or null if parsing failed
|
|
16
16
|
* @property {string} rule - The normalized rule name (e.g., '∧I', 'Pr')
|
|
17
17
|
* @property {number[]} citations - Line numbers cited in justification
|
|
18
|
-
* @property {SubproofCitation[]}
|
|
18
|
+
* @property {SubproofCitation[]} subproofs - Subproof ranges cited
|
|
19
19
|
* @property {number} depth - Subproof nesting depth (0 = main proof)
|
|
20
20
|
* @property {number[]} location - Path through subproof tree
|
|
21
21
|
* @property {string[]} issues - Parse errors for this line
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fitch-js",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"description": "A JavaScript library for validating Fitch-style natural deduction proofs",
|
|
5
5
|
"main": "dist/cjs/index.js",
|
|
6
6
|
"module": "dist/esm/index.js",
|
|
@@ -42,4 +42,4 @@
|
|
|
42
42
|
"jest": "^29.7.0",
|
|
43
43
|
"typescript": "^5.3.3"
|
|
44
44
|
}
|
|
45
|
-
}
|
|
45
|
+
}
|