@echecs/fen 1.0.1 → 2.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/CHANGELOG.md +21 -0
- package/README.md +12 -8
- package/dist/index.d.ts +12 -9
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,26 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [2.0.0] - 2026-04-09
|
|
4
|
+
|
|
5
|
+
### Changed
|
|
6
|
+
|
|
7
|
+
- `Color` type from `'w' | 'b'` to `'white' | 'black'`.
|
|
8
|
+
- `PieceType` type from single-char (`'p'`, `'n'`, `'b'`, `'r'`, `'q'`, `'k'`)
|
|
9
|
+
to full names (`'pawn'`, `'knight'`, `'bishop'`, `'rook'`, `'queen'`,
|
|
10
|
+
`'king'`).
|
|
11
|
+
- `CastlingRights` from flat `{ wK, wQ, bK, bQ }` to nested
|
|
12
|
+
`{ white: { king, queen }, black: { king, queen } }`.
|
|
13
|
+
- `Position.board` from `Map` to `ReadonlyMap`.
|
|
14
|
+
- En passant square type narrowed from `Square` to `` `${File}${'3' | '6'}` ``.
|
|
15
|
+
|
|
16
|
+
### Added
|
|
17
|
+
|
|
18
|
+
- `EnPassantSquare` and `SideCastlingRights` type exports.
|
|
19
|
+
|
|
20
|
+
### Fixed
|
|
21
|
+
|
|
22
|
+
- ESLint config ordering (`eslint-config-prettier` moved to end of array).
|
|
23
|
+
|
|
3
24
|
## [1.0.1] - 2026-03-19
|
|
4
25
|
|
|
5
26
|
### Fixed
|
package/README.md
CHANGED
|
@@ -103,9 +103,9 @@ The FEN string for the standard starting position.
|
|
|
103
103
|
|
|
104
104
|
```typescript
|
|
105
105
|
interface Position {
|
|
106
|
-
board:
|
|
106
|
+
board: ReadonlyMap<Square, Piece>;
|
|
107
107
|
castlingRights: CastlingRights;
|
|
108
|
-
enPassantSquare:
|
|
108
|
+
enPassantSquare: EnPassantSquare | undefined;
|
|
109
109
|
fullmoveNumber: number;
|
|
110
110
|
halfmoveClock: number;
|
|
111
111
|
turn: Color;
|
|
@@ -125,22 +125,26 @@ interface ParseWarning {
|
|
|
125
125
|
offset: number;
|
|
126
126
|
}
|
|
127
127
|
|
|
128
|
-
type Color = '
|
|
128
|
+
type Color = 'black' | 'white';
|
|
129
129
|
type Square = `${File}${Rank}`;
|
|
130
|
+
type EnPassantSquare = `${File}${'3' | '6'}`;
|
|
130
131
|
type File = 'a' | 'b' | 'c' | 'd' | 'e' | 'f' | 'g' | 'h';
|
|
131
132
|
type Rank = '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8';
|
|
132
|
-
type PieceType = '
|
|
133
|
+
type PieceType = 'bishop' | 'king' | 'knight' | 'pawn' | 'queen' | 'rook';
|
|
133
134
|
|
|
134
135
|
interface Piece {
|
|
135
136
|
color: Color;
|
|
136
137
|
type: PieceType;
|
|
137
138
|
}
|
|
138
139
|
|
|
140
|
+
interface SideCastlingRights {
|
|
141
|
+
king: boolean;
|
|
142
|
+
queen: boolean;
|
|
143
|
+
}
|
|
144
|
+
|
|
139
145
|
interface CastlingRights {
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
bK: boolean;
|
|
143
|
-
bQ: boolean;
|
|
146
|
+
black: SideCastlingRights;
|
|
147
|
+
white: SideCastlingRights;
|
|
144
148
|
}
|
|
145
149
|
```
|
|
146
150
|
|
package/dist/index.d.ts
CHANGED
|
@@ -1,23 +1,26 @@
|
|
|
1
1
|
//#region src/types.d.ts
|
|
2
|
-
type Color = '
|
|
2
|
+
type Color = 'black' | 'white';
|
|
3
3
|
type File = 'a' | 'b' | 'c' | 'd' | 'e' | 'f' | 'g' | 'h';
|
|
4
|
-
type PieceType = '
|
|
4
|
+
type PieceType = 'bishop' | 'king' | 'knight' | 'pawn' | 'queen' | 'rook';
|
|
5
5
|
type Rank = '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8';
|
|
6
6
|
type Square = `${File}${Rank}`;
|
|
7
|
+
type EnPassantSquare = `${File}${'3' | '6'}`;
|
|
8
|
+
interface SideCastlingRights {
|
|
9
|
+
king: boolean;
|
|
10
|
+
queen: boolean;
|
|
11
|
+
}
|
|
7
12
|
interface CastlingRights {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
wK: boolean;
|
|
11
|
-
wQ: boolean;
|
|
13
|
+
black: SideCastlingRights;
|
|
14
|
+
white: SideCastlingRights;
|
|
12
15
|
}
|
|
13
16
|
interface Piece {
|
|
14
17
|
color: Color;
|
|
15
18
|
type: PieceType;
|
|
16
19
|
}
|
|
17
20
|
interface Position {
|
|
18
|
-
board:
|
|
21
|
+
board: ReadonlyMap<Square, Piece>;
|
|
19
22
|
castlingRights: CastlingRights;
|
|
20
|
-
enPassantSquare:
|
|
23
|
+
enPassantSquare: EnPassantSquare | undefined;
|
|
21
24
|
fullmoveNumber: number;
|
|
22
25
|
halfmoveClock: number;
|
|
23
26
|
turn: Color;
|
|
@@ -44,4 +47,4 @@ declare const STARTING_FEN = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq
|
|
|
44
47
|
declare function parse(input: string, options?: ParseOptions): Position | null;
|
|
45
48
|
declare function stringify(position: Position): string;
|
|
46
49
|
//#endregion
|
|
47
|
-
export { type CastlingRights, type Color, type File, type ParseError, type ParseOptions, type ParseWarning, type Piece, type PieceType, type Position, type Rank, STARTING_FEN, type Square, parse as default, stringify };
|
|
50
|
+
export { type CastlingRights, type Color, type EnPassantSquare, type File, type ParseError, type ParseOptions, type ParseWarning, type Piece, type PieceType, type Position, type Rank, STARTING_FEN, type SideCastlingRights, type Square, parse as default, stringify };
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
const e=`rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1`,t=[`a`,`b`,`c`,`d`,`e`,`f`,`g`,`h`],n=
|
|
1
|
+
const e=`rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1`,t=[`a`,`b`,`c`,`d`,`e`,`f`,`g`,`h`],n=[`8`,`7`,`6`,`5`,`4`,`3`,`2`,`1`],r={b:`bishop`,k:`king`,n:`knight`,p:`pawn`,q:`queen`,r:`rook`},i={bishop:`b`,king:`k`,knight:`n`,pawn:`p`,queen:`q`,rook:`r`};function a(e,t=0){return{column:t+1,line:1,message:e,offset:t}}function o(e,t=0){return{column:t+1,line:1,message:e,offset:t}}function s(e,i){let o=new Map,s=e.split(`/`);if(s.length!==8)return null;for(let[e,c]of s.entries()){let s=n[e];if(s===void 0||c===void 0)return null;let l=0;for(let e of c){let n=Number.parseInt(e,10);if(Number.isNaN(n)){let n=r[e.toLowerCase()];if(n===void 0)return i?.(a(`Invalid piece type: "${e}"`)),null;let c=e===e.toUpperCase()?`white`:`black`,u=t[l];if(u===void 0)return null;o.set(`${u}${s}`,{color:c,type:n}),l+=1}else l+=n}if(l!==8)return i?.(a(`Invalid FEN rank "${c}": expected 8 files, got ${l}`)),null}return o}const c=/^(?:-|K?Q?k?q?)$/,l=/^[a-h][36]$/;function u(e){return!c.test(e)||e.length===0?null:{black:{king:e.includes(`k`),queen:e.includes(`q`)},white:{king:e.includes(`K`),queen:e.includes(`Q`)}}}function d(e){let r=[];for(let a of n){let n=``,o=0;for(let r of t){let t=e.get(`${r}${a}`);if(t===void 0)o+=1;else{o>0&&(n+=String(o),o=0);let e=i[t.type];n+=t.color===`white`?e.toUpperCase():e}}o>0&&(n+=String(o)),r.push(n)}return r.join(`/`)}function f(e){let t=``;return e.white.king&&(t+=`K`),e.white.queen&&(t+=`Q`),e.black.king&&(t+=`k`),e.black.queen&&(t+=`q`),t.length>0?t:`-`}function p(e,t){let n=e.replace(/^\uFEFF/,``).trim();if(n.length===0)return t?.onError?.(a(`Input is empty`)),null;let r=n.split(` `);if(r.length!==6)return t?.onError?.(a(`Expected 6 FEN fields, got ${r.length}`)),null;let[i,c,d,f,p,m]=r,h=[0];for(let e=0;e<r.length-1;e++){let t=h[e]??0,n=r[e]??``;h.push(t+n.length+1)}let g=s(i,t?.onError);if(g===null)return null;if(c!==`w`&&c!==`b`)return t?.onError?.(a(`Invalid active color: "${c}"`,h[1])),null;let _=c===`w`?`white`:`black`,v=u(d);if(v===null)return t?.onError?.(a(`Invalid castling availability: "${d}"`,h[2])),null;if(f!==`-`&&!l.test(f))return t?.onError?.(a(`Invalid en passant square: "${f}"`,h[3])),null;let y=f===`-`?void 0:f,b=Number.parseInt(p,10);if(Number.isNaN(b)||b<0)return t?.onError?.(a(`Invalid halfmove clock: "${p}"`,h[4])),null;let x=Number.parseInt(m,10);if(Number.isNaN(x)||x<1)return t?.onError?.(a(`Invalid fullmove number: "${m}"`,h[5])),null;if(t?.onWarning){let e=0,n=0,r=0,i=0,a=0,s=0,c=!1;for(let[t,o]of g)o.color===`white`?(a+=1,o.type===`king`&&(e+=1),o.type===`pawn`&&(r+=1,(t.endsWith(`1`)||t.endsWith(`8`))&&(c=!0))):(s+=1,o.type===`king`&&(n+=1),o.type===`pawn`&&(i+=1,(t.endsWith(`1`)||t.endsWith(`8`))&&(c=!0)));e===0&&t.onWarning(o(`White king is missing`)),n===0&&t.onWarning(o(`Black king is missing`)),c&&t.onWarning(o(`Pawn on rank 1 or 8`)),r>8&&t.onWarning(o(`White has ${r} pawns (maximum is 8)`)),i>8&&t.onWarning(o(`Black has ${i} pawns (maximum is 8)`)),a>16&&t.onWarning(o(`White has ${a} pieces (maximum is 16)`)),s>16&&t.onWarning(o(`Black has ${s} pieces (maximum is 16)`))}return{board:g,castlingRights:v,enPassantSquare:y,fullmoveNumber:x,halfmoveClock:b,turn:_}}function m(e){return[d(e.board),e.turn===`white`?`w`:`b`,f(e.castlingRights),e.enPassantSquare??`-`,String(e.halfmoveClock),String(e.fullmoveNumber)].join(` `)}export{e as STARTING_FEN,p as default,m as stringify};
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["import type {\n CastlingRights,\n Color,\n File,\n Piece,\n PieceType,\n Position,\n Rank,\n Square,\n} from './types.js';\n\ninterface ParseError {\n column: number;\n line: number;\n message: string;\n offset: number;\n}\n\ninterface ParseWarning {\n column: number;\n line: number;\n message: string;\n offset: number;\n}\n\ninterface ParseOptions {\n onError?: (error: ParseError) => void;\n onWarning?: (warning: ParseWarning) => void;\n}\n\nconst STARTING_FEN = 'rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1';\n\nconst FILES: File[] = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'];\nconst PIECE_TYPES = new Set<string>(['p', 'n', 'b', 'r', 'q', 'k']);\nconst RANKS: Rank[] = ['8', '7', '6', '5', '4', '3', '2', '1'];\n\nfunction makeError(message: string, offset = 0): ParseError {\n return { column: offset + 1, line: 1, message, offset };\n}\n\nfunction makeWarning(message: string, offset = 0): ParseWarning {\n return { column: offset + 1, line: 1, message, offset };\n}\n\nfunction parsePlacement(\n placement: string,\n onError?: (error: ParseError) => void,\n): Map<Square, Piece> | null {\n const board = new Map<Square, Piece>();\n const ranks = placement.split('/');\n\n if (ranks.length !== 8) {\n // eslint-disable-next-line unicorn/no-null\n return null;\n }\n\n for (const [rankIndex, rankString] of ranks.entries()) {\n const rank = RANKS[rankIndex];\n if (rank === undefined || rankString === undefined) {\n // eslint-disable-next-line unicorn/no-null\n return null;\n }\n\n let fileIndex = 0;\n for (const char of rankString) {\n const emptyCount = Number.parseInt(char, 10);\n if (Number.isNaN(emptyCount)) {\n const lower = char.toLowerCase();\n if (!PIECE_TYPES.has(lower)) {\n onError?.(makeError(`Invalid piece type: \"${char}\"`));\n // eslint-disable-next-line unicorn/no-null\n return null;\n }\n const color: Color = char === char.toUpperCase() ? 'w' : 'b';\n const type = lower as PieceType;\n const file = FILES[fileIndex];\n if (file === undefined) {\n // eslint-disable-next-line unicorn/no-null\n return null;\n }\n board.set(`${file}${rank}` as Square, { color, type });\n fileIndex += 1;\n } else {\n fileIndex += emptyCount;\n }\n }\n\n if (fileIndex !== 8) {\n onError?.(\n makeError(\n `Invalid FEN rank \"${rankString}\": expected 8 files, got ${fileIndex}`,\n ),\n );\n // eslint-disable-next-line unicorn/no-null\n return null;\n }\n }\n\n return board;\n}\n\nconst CASTLING_PATTERN = /^(?:-|K?Q?k?q?)$/;\nconst EN_PASSANT_PATTERN = /^[a-h][36]$/;\n\nfunction parseCastling(castling: string): CastlingRights | null {\n if (!CASTLING_PATTERN.test(castling) || castling.length === 0) {\n // eslint-disable-next-line unicorn/no-null\n return null;\n }\n\n return {\n bK: castling.includes('k'),\n bQ: castling.includes('q'),\n wK: castling.includes('K'),\n wQ: castling.includes('Q'),\n };\n}\n\nfunction stringifyPlacement(board: Map<Square, Piece>): string {\n const rankStrings: string[] = [];\n\n for (const rank of RANKS) {\n let rankString = '';\n let emptyCount = 0;\n\n for (const file of FILES) {\n const p = board.get(`${file}${rank}` as Square);\n if (p === undefined) {\n emptyCount += 1;\n } else {\n if (emptyCount > 0) {\n rankString += String(emptyCount);\n emptyCount = 0;\n }\n rankString += p.color === 'w' ? p.type.toUpperCase() : p.type;\n }\n }\n\n if (emptyCount > 0) {\n rankString += String(emptyCount);\n }\n rankStrings.push(rankString);\n }\n\n return rankStrings.join('/');\n}\n\nfunction stringifyCastling(rights: CastlingRights): string {\n let result = '';\n if (rights.wK) {\n result += 'K';\n }\n if (rights.wQ) {\n result += 'Q';\n }\n if (rights.bK) {\n result += 'k';\n }\n if (rights.bQ) {\n result += 'q';\n }\n return result.length > 0 ? result : '-';\n}\n\nfunction parse(input: string, options?: ParseOptions): Position | null {\n const content = input.replace(/^\\uFEFF/, '').trim();\n\n if (content.length === 0) {\n options?.onError?.(makeError('Input is empty'));\n // eslint-disable-next-line unicorn/no-null\n return null;\n }\n\n const parts = content.split(' ');\n if (parts.length !== 6) {\n options?.onError?.(makeError(`Expected 6 FEN fields, got ${parts.length}`));\n // eslint-disable-next-line unicorn/no-null\n return null;\n }\n\n const [\n placement,\n turnString,\n castlingString,\n epString,\n halfString,\n fullString,\n ] = parts as [string, string, string, string, string, string];\n\n // Compute the start offset of each field within the content string.\n // Fields are separated by single spaces.\n const fieldOffsets: number[] = [0];\n for (let index = 0; index < parts.length - 1; index++) {\n const previous = fieldOffsets[index] ?? 0;\n const field = parts[index] ?? '';\n fieldOffsets.push(previous + field.length + 1);\n }\n\n const board = parsePlacement(placement, options?.onError);\n if (board === null) {\n // eslint-disable-next-line unicorn/no-null\n return null;\n }\n\n if (turnString !== 'w' && turnString !== 'b') {\n options?.onError?.(\n makeError(`Invalid active color: \"${turnString}\"`, fieldOffsets[1]),\n );\n // eslint-disable-next-line unicorn/no-null\n return null;\n }\n\n const castlingRights = parseCastling(castlingString);\n if (castlingRights === null) {\n options?.onError?.(\n makeError(\n `Invalid castling availability: \"${castlingString}\"`,\n fieldOffsets[2],\n ),\n );\n // eslint-disable-next-line unicorn/no-null\n return null;\n }\n\n if (epString !== '-' && !EN_PASSANT_PATTERN.test(epString)) {\n options?.onError?.(\n makeError(`Invalid en passant square: \"${epString}\"`, fieldOffsets[3]),\n );\n // eslint-disable-next-line unicorn/no-null\n return null;\n }\n\n const enPassantSquare: Square | undefined =\n epString === '-' ? undefined : (epString as Square);\n\n const halfmoveClock = Number.parseInt(halfString, 10);\n if (Number.isNaN(halfmoveClock) || halfmoveClock < 0) {\n options?.onError?.(\n makeError(`Invalid halfmove clock: \"${halfString}\"`, fieldOffsets[4]),\n );\n // eslint-disable-next-line unicorn/no-null\n return null;\n }\n\n const fullmoveNumber = Number.parseInt(fullString, 10);\n if (Number.isNaN(fullmoveNumber) || fullmoveNumber < 1) {\n options?.onError?.(\n makeError(`Invalid fullmove number: \"${fullString}\"`, fieldOffsets[5]),\n );\n // eslint-disable-next-line unicorn/no-null\n return null;\n }\n\n // Position warnings — syntactically valid FEN but suspicious position.\n if (options?.onWarning) {\n let whiteKings = 0;\n let blackKings = 0;\n let whitePawns = 0;\n let blackPawns = 0;\n let whitePieces = 0;\n let blackPieces = 0;\n let pawnOnBackRank = false;\n\n for (const [square, piece] of board) {\n if (piece.color === 'w') {\n whitePieces += 1;\n if (piece.type === 'k') {\n whiteKings += 1;\n }\n if (piece.type === 'p') {\n whitePawns += 1;\n if (square.endsWith('1') || square.endsWith('8')) {\n pawnOnBackRank = true;\n }\n }\n } else {\n blackPieces += 1;\n if (piece.type === 'k') {\n blackKings += 1;\n }\n if (piece.type === 'p') {\n blackPawns += 1;\n if (square.endsWith('1') || square.endsWith('8')) {\n pawnOnBackRank = true;\n }\n }\n }\n }\n\n if (whiteKings === 0) {\n options.onWarning(makeWarning('White king is missing'));\n }\n if (blackKings === 0) {\n options.onWarning(makeWarning('Black king is missing'));\n }\n if (pawnOnBackRank) {\n options.onWarning(makeWarning('Pawn on rank 1 or 8'));\n }\n if (whitePawns > 8) {\n options.onWarning(\n makeWarning(`White has ${whitePawns} pawns (maximum is 8)`),\n );\n }\n if (blackPawns > 8) {\n options.onWarning(\n makeWarning(`Black has ${blackPawns} pawns (maximum is 8)`),\n );\n }\n if (whitePieces > 16) {\n options.onWarning(\n makeWarning(`White has ${whitePieces} pieces (maximum is 16)`),\n );\n }\n if (blackPieces > 16) {\n options.onWarning(\n makeWarning(`Black has ${blackPieces} pieces (maximum is 16)`),\n );\n }\n }\n\n return {\n board,\n castlingRights,\n enPassantSquare,\n fullmoveNumber,\n halfmoveClock,\n turn: turnString,\n };\n}\n\nfunction stringify(position: Position): string {\n const placement = stringifyPlacement(position.board);\n const castling = stringifyCastling(position.castlingRights);\n const enPassant = position.enPassantSquare ?? '-';\n\n return [\n placement,\n position.turn,\n castling,\n enPassant,\n String(position.halfmoveClock),\n String(position.fullmoveNumber),\n ].join(' ');\n}\n\nexport type { ParseError, ParseOptions, ParseWarning };\nexport type {\n CastlingRights,\n Color,\n File,\n Piece,\n PieceType,\n Position,\n Rank,\n Square,\n} from './types.js';\nexport { STARTING_FEN, stringify };\nexport default parse;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["import type {\n CastlingRights,\n Color,\n EnPassantSquare,\n File,\n Piece,\n PieceType,\n Position,\n Rank,\n Square,\n} from './types.js';\n\ninterface ParseError {\n column: number;\n line: number;\n message: string;\n offset: number;\n}\n\ninterface ParseWarning {\n column: number;\n line: number;\n message: string;\n offset: number;\n}\n\ninterface ParseOptions {\n onError?: (error: ParseError) => void;\n onWarning?: (warning: ParseWarning) => void;\n}\n\nconst STARTING_FEN = 'rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1';\n\nconst FILES: File[] = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'];\nconst RANKS: Rank[] = ['8', '7', '6', '5', '4', '3', '2', '1'];\n\nconst CHAR_TO_PIECE_TYPE: Record<string, PieceType> = {\n b: 'bishop',\n k: 'king',\n n: 'knight',\n p: 'pawn',\n q: 'queen',\n r: 'rook',\n};\n\nconst PIECE_TYPE_TO_CHAR: Record<PieceType, string> = {\n bishop: 'b',\n king: 'k',\n knight: 'n',\n pawn: 'p',\n queen: 'q',\n rook: 'r',\n};\n\nfunction makeError(message: string, offset = 0): ParseError {\n return { column: offset + 1, line: 1, message, offset };\n}\n\nfunction makeWarning(message: string, offset = 0): ParseWarning {\n return { column: offset + 1, line: 1, message, offset };\n}\n\nfunction parsePlacement(\n placement: string,\n onError?: (error: ParseError) => void,\n): Map<Square, Piece> | null {\n const board = new Map<Square, Piece>();\n const ranks = placement.split('/');\n\n if (ranks.length !== 8) {\n // eslint-disable-next-line unicorn/no-null\n return null;\n }\n\n for (const [rankIndex, rankString] of ranks.entries()) {\n const rank = RANKS[rankIndex];\n if (rank === undefined || rankString === undefined) {\n // eslint-disable-next-line unicorn/no-null\n return null;\n }\n\n let fileIndex = 0;\n for (const char of rankString) {\n const emptyCount = Number.parseInt(char, 10);\n if (Number.isNaN(emptyCount)) {\n const lower = char.toLowerCase();\n const type = CHAR_TO_PIECE_TYPE[lower];\n if (type === undefined) {\n onError?.(makeError(`Invalid piece type: \"${char}\"`));\n // eslint-disable-next-line unicorn/no-null\n return null;\n }\n const color: Color = char === char.toUpperCase() ? 'white' : 'black';\n const file = FILES[fileIndex];\n if (file === undefined) {\n // eslint-disable-next-line unicorn/no-null\n return null;\n }\n board.set(`${file}${rank}` as Square, { color, type });\n fileIndex += 1;\n } else {\n fileIndex += emptyCount;\n }\n }\n\n if (fileIndex !== 8) {\n onError?.(\n makeError(\n `Invalid FEN rank \"${rankString}\": expected 8 files, got ${fileIndex}`,\n ),\n );\n // eslint-disable-next-line unicorn/no-null\n return null;\n }\n }\n\n return board;\n}\n\nconst CASTLING_PATTERN = /^(?:-|K?Q?k?q?)$/;\nconst EN_PASSANT_PATTERN = /^[a-h][36]$/;\n\nfunction parseCastling(castling: string): CastlingRights | null {\n if (!CASTLING_PATTERN.test(castling) || castling.length === 0) {\n // eslint-disable-next-line unicorn/no-null\n return null;\n }\n\n return {\n black: {\n king: castling.includes('k'),\n queen: castling.includes('q'),\n },\n white: {\n king: castling.includes('K'),\n queen: castling.includes('Q'),\n },\n };\n}\n\nfunction stringifyPlacement(board: ReadonlyMap<Square, Piece>): string {\n const rankStrings: string[] = [];\n\n for (const rank of RANKS) {\n let rankString = '';\n let emptyCount = 0;\n\n for (const file of FILES) {\n const p = board.get(`${file}${rank}` as Square);\n if (p === undefined) {\n emptyCount += 1;\n } else {\n if (emptyCount > 0) {\n rankString += String(emptyCount);\n emptyCount = 0;\n }\n const char = PIECE_TYPE_TO_CHAR[p.type];\n rankString += p.color === 'white' ? char.toUpperCase() : char;\n }\n }\n\n if (emptyCount > 0) {\n rankString += String(emptyCount);\n }\n rankStrings.push(rankString);\n }\n\n return rankStrings.join('/');\n}\n\nfunction stringifyCastling(rights: CastlingRights): string {\n let result = '';\n if (rights.white.king) {\n result += 'K';\n }\n if (rights.white.queen) {\n result += 'Q';\n }\n if (rights.black.king) {\n result += 'k';\n }\n if (rights.black.queen) {\n result += 'q';\n }\n return result.length > 0 ? result : '-';\n}\n\nfunction parse(input: string, options?: ParseOptions): Position | null {\n const content = input.replace(/^\\uFEFF/, '').trim();\n\n if (content.length === 0) {\n options?.onError?.(makeError('Input is empty'));\n // eslint-disable-next-line unicorn/no-null\n return null;\n }\n\n const parts = content.split(' ');\n if (parts.length !== 6) {\n options?.onError?.(makeError(`Expected 6 FEN fields, got ${parts.length}`));\n // eslint-disable-next-line unicorn/no-null\n return null;\n }\n\n const [\n placement,\n turnString,\n castlingString,\n epString,\n halfString,\n fullString,\n ] = parts as [string, string, string, string, string, string];\n\n // Compute the start offset of each field within the content string.\n // Fields are separated by single spaces.\n const fieldOffsets: number[] = [0];\n for (let index = 0; index < parts.length - 1; index++) {\n const previous = fieldOffsets[index] ?? 0;\n const field = parts[index] ?? '';\n fieldOffsets.push(previous + field.length + 1);\n }\n\n const board = parsePlacement(placement, options?.onError);\n if (board === null) {\n // eslint-disable-next-line unicorn/no-null\n return null;\n }\n\n if (turnString !== 'w' && turnString !== 'b') {\n options?.onError?.(\n makeError(`Invalid active color: \"${turnString}\"`, fieldOffsets[1]),\n );\n // eslint-disable-next-line unicorn/no-null\n return null;\n }\n\n const turn: Color = turnString === 'w' ? 'white' : 'black';\n\n const castlingRights = parseCastling(castlingString);\n if (castlingRights === null) {\n options?.onError?.(\n makeError(\n `Invalid castling availability: \"${castlingString}\"`,\n fieldOffsets[2],\n ),\n );\n // eslint-disable-next-line unicorn/no-null\n return null;\n }\n\n if (epString !== '-' && !EN_PASSANT_PATTERN.test(epString)) {\n options?.onError?.(\n makeError(`Invalid en passant square: \"${epString}\"`, fieldOffsets[3]),\n );\n // eslint-disable-next-line unicorn/no-null\n return null;\n }\n\n const enPassantSquare: EnPassantSquare | undefined =\n epString === '-' ? undefined : (epString as EnPassantSquare);\n\n const halfmoveClock = Number.parseInt(halfString, 10);\n if (Number.isNaN(halfmoveClock) || halfmoveClock < 0) {\n options?.onError?.(\n makeError(`Invalid halfmove clock: \"${halfString}\"`, fieldOffsets[4]),\n );\n // eslint-disable-next-line unicorn/no-null\n return null;\n }\n\n const fullmoveNumber = Number.parseInt(fullString, 10);\n if (Number.isNaN(fullmoveNumber) || fullmoveNumber < 1) {\n options?.onError?.(\n makeError(`Invalid fullmove number: \"${fullString}\"`, fieldOffsets[5]),\n );\n // eslint-disable-next-line unicorn/no-null\n return null;\n }\n\n // Position warnings — syntactically valid FEN but suspicious position.\n if (options?.onWarning) {\n let whiteKings = 0;\n let blackKings = 0;\n let whitePawns = 0;\n let blackPawns = 0;\n let whitePieces = 0;\n let blackPieces = 0;\n let pawnOnBackRank = false;\n\n for (const [square, piece] of board) {\n if (piece.color === 'white') {\n whitePieces += 1;\n if (piece.type === 'king') {\n whiteKings += 1;\n }\n if (piece.type === 'pawn') {\n whitePawns += 1;\n if (square.endsWith('1') || square.endsWith('8')) {\n pawnOnBackRank = true;\n }\n }\n } else {\n blackPieces += 1;\n if (piece.type === 'king') {\n blackKings += 1;\n }\n if (piece.type === 'pawn') {\n blackPawns += 1;\n if (square.endsWith('1') || square.endsWith('8')) {\n pawnOnBackRank = true;\n }\n }\n }\n }\n\n if (whiteKings === 0) {\n options.onWarning(makeWarning('White king is missing'));\n }\n if (blackKings === 0) {\n options.onWarning(makeWarning('Black king is missing'));\n }\n if (pawnOnBackRank) {\n options.onWarning(makeWarning('Pawn on rank 1 or 8'));\n }\n if (whitePawns > 8) {\n options.onWarning(\n makeWarning(`White has ${whitePawns} pawns (maximum is 8)`),\n );\n }\n if (blackPawns > 8) {\n options.onWarning(\n makeWarning(`Black has ${blackPawns} pawns (maximum is 8)`),\n );\n }\n if (whitePieces > 16) {\n options.onWarning(\n makeWarning(`White has ${whitePieces} pieces (maximum is 16)`),\n );\n }\n if (blackPieces > 16) {\n options.onWarning(\n makeWarning(`Black has ${blackPieces} pieces (maximum is 16)`),\n );\n }\n }\n\n return {\n board,\n castlingRights,\n enPassantSquare,\n fullmoveNumber,\n halfmoveClock,\n turn,\n };\n}\n\nfunction stringify(position: Position): string {\n const placement = stringifyPlacement(position.board);\n const turn = position.turn === 'white' ? 'w' : 'b';\n const castling = stringifyCastling(position.castlingRights);\n const enPassant = position.enPassantSquare ?? '-';\n\n return [\n placement,\n turn,\n castling,\n enPassant,\n String(position.halfmoveClock),\n String(position.fullmoveNumber),\n ].join(' ');\n}\n\nexport type { ParseError, ParseOptions, ParseWarning };\nexport type {\n CastlingRights,\n Color,\n EnPassantSquare,\n File,\n Piece,\n PieceType,\n Position,\n Rank,\n SideCastlingRights,\n Square,\n} from './types.js';\nexport { STARTING_FEN, stringify };\nexport default parse;\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -13,13 +13,13 @@
|
|
|
13
13
|
"eslint-config-prettier": "^10.1.8",
|
|
14
14
|
"eslint-import-resolver-typescript": "^4.4.4",
|
|
15
15
|
"eslint-plugin-import-x": "^4.16.2",
|
|
16
|
-
"eslint-plugin-unicorn": "^
|
|
16
|
+
"eslint-plugin-unicorn": "^64.0.0",
|
|
17
17
|
"husky": "^9.1.7",
|
|
18
18
|
"lint-staged": "^16.4.0",
|
|
19
19
|
"prettier": "^3.8.1",
|
|
20
20
|
"tsdown": "^0.21.4",
|
|
21
21
|
"typedoc": "^0.28.17",
|
|
22
|
-
"typescript": "^
|
|
22
|
+
"typescript": "^6.0.2",
|
|
23
23
|
"typescript-eslint": "^8.57.0",
|
|
24
24
|
"vitest": "^4.1.0"
|
|
25
25
|
},
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
},
|
|
56
56
|
"sideEffects": false,
|
|
57
57
|
"type": "module",
|
|
58
|
-
"version": "
|
|
58
|
+
"version": "2.0.0",
|
|
59
59
|
"scripts": {
|
|
60
60
|
"build": "tsdown",
|
|
61
61
|
"docs": "typedoc",
|