pgn-viewer-parser 1.0.0 → 1.0.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.
@@ -0,0 +1,66 @@
1
+ import { MoveNode } from '../model/move-node.js';
2
+ /**
3
+ * Cursor for navigating through a chess game tree.
4
+ */
5
+ export declare class GameCursor {
6
+ private _current;
7
+ private _root;
8
+ constructor(root: MoveNode);
9
+ /**
10
+ * Gets the current node.
11
+ */
12
+ get current(): MoveNode;
13
+ /**
14
+ * Gets the root node.
15
+ */
16
+ get root(): MoveNode;
17
+ /**
18
+ * Moves to the next node in the current line.
19
+ * Returns the new current node, or null if at the end.
20
+ */
21
+ next(): MoveNode | null;
22
+ /**
23
+ * Moves to the previous node.
24
+ * Returns the new current node, or null if at the start.
25
+ */
26
+ prev(): MoveNode | null;
27
+ /**
28
+ * Jumps to a specific node by ID.
29
+ */
30
+ goTo(nodeId: string): void;
31
+ /**
32
+ * Enters a variation at the given index.
33
+ * Returns the first node of the variation, or null if invalid index.
34
+ */
35
+ enterVariation(index: number): MoveNode | null;
36
+ /**
37
+ * Exits the current variation and returns to the parent line.
38
+ * Returns the parent node, or null if already in the mainline.
39
+ */
40
+ exitVariation(): MoveNode | null;
41
+ /**
42
+ * Goes to the start of the game (root node).
43
+ */
44
+ toStart(): void;
45
+ /**
46
+ * Goes to the end of the current line.
47
+ */
48
+ toEnd(): void;
49
+ /**
50
+ * Checks if the cursor is at the start.
51
+ */
52
+ isAtStart(): boolean;
53
+ /**
54
+ * Checks if the cursor is at the end of the current line.
55
+ */
56
+ isAtEnd(): boolean;
57
+ /**
58
+ * Gets the mainline path from root to current position.
59
+ */
60
+ getMainlinePath(): MoveNode[];
61
+ /**
62
+ * Recursively finds a node by ID.
63
+ */
64
+ private findNodeById;
65
+ }
66
+ //# sourceMappingURL=game-cursor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"game-cursor.d.ts","sourceRoot":"","sources":["../../src/cursor/game-cursor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAEjD;;GAEG;AACH,qBAAa,UAAU;IACnB,OAAO,CAAC,QAAQ,CAAW;IAC3B,OAAO,CAAC,KAAK,CAAW;gBAEZ,IAAI,EAAE,QAAQ;IAK1B;;OAEG;IACH,IAAI,OAAO,IAAI,QAAQ,CAEtB;IAED;;OAEG;IACH,IAAI,IAAI,IAAI,QAAQ,CAEnB;IAED;;;OAGG;IACH,IAAI,IAAI,QAAQ,GAAG,IAAI;IAQvB;;;OAGG;IACH,IAAI,IAAI,QAAQ,GAAG,IAAI;IAQvB;;OAEG;IACH,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAS1B;;;OAGG;IACH,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,QAAQ,GAAG,IAAI;IAQ9C;;;OAGG;IACH,aAAa,IAAI,QAAQ,GAAG,IAAI;IAQhC;;OAEG;IACH,OAAO,IAAI,IAAI;IAIf;;OAEG;IACH,KAAK,IAAI,IAAI;IAMb;;OAEG;IACH,SAAS,IAAI,OAAO;IAIpB;;OAEG;IACH,OAAO,IAAI,OAAO;IAIlB;;OAEG;IACH,eAAe,IAAI,QAAQ,EAAE;IAY7B;;OAEG;IACH,OAAO,CAAC,YAAY;CAmBvB"}
@@ -0,0 +1,12 @@
1
+ export { createMoveNode, createRootNode } from './model/move-node.js';
2
+ export type { MoveNode } from './model/move-node.js';
3
+ export { createPGNGame } from './model/pgn-game.js';
4
+ export type { PGNGame } from './model/pgn-game.js';
5
+ export { parsePGN, PGNParser } from './parser/pgn-parser.js';
6
+ export { PGNTokenizer, TokenType } from './parser/tokenizer.js';
7
+ export type { Token } from './parser/tokenizer.js';
8
+ export { parseHeader, parseHeaders } from './parser/header-parser.js';
9
+ export { GameCursor } from './cursor/game-cursor.js';
10
+ export { nagToSymbol, nagsToSymbols, NAG_SYMBOLS } from './utils/nag-symbols.js';
11
+ export { parseAnnotations, parseTimeAnnotation, parseEvalAnnotation, } from './utils/annotation-parser.js';
12
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtE,YAAY,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,YAAY,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAGnD,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAChE,YAAY,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAGtE,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAGrD,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACjF,OAAO,EACH,gBAAgB,EAChB,mBAAmB,EACnB,mBAAmB,GACtB,MAAM,8BAA8B,CAAC"}
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Represents a single move node in the game tree.
3
+ * Each node can have a mainline continuation (next) and alternative variations.
4
+ */
5
+ export interface MoveNode {
6
+ /** Unique identifier for this node */
7
+ id: string;
8
+ /** Ply number (half-moves from start, 0-indexed) */
9
+ ply: number;
10
+ /** Move number in chess notation (1, 2, 3, etc.) */
11
+ moveNumber: number;
12
+ /** Color to move: 'w' for white, 'b' for black */
13
+ color: 'w' | 'b';
14
+ /** Standard Algebraic Notation of the move (e.g., "e4", "Nf3", "O-O") */
15
+ san: string;
16
+ /** Numeric Annotation Glyphs (e.g., $1 = "!", $2 = "?") */
17
+ nags: number[];
18
+ /** Comment appearing before this move */
19
+ commentBefore?: string;
20
+ /** Comment appearing after this move */
21
+ commentAfter?: string;
22
+ /** Clock time remaining in seconds */
23
+ clock?: number;
24
+ /** Elapsed move time in seconds */
25
+ emt?: number;
26
+ /** Position evaluation in centipawns (positive = white advantage) */
27
+ eval?: number;
28
+ /** Search depth for the evaluation */
29
+ depth?: number;
30
+ /** Parent node (undefined for root) */
31
+ parent?: MoveNode;
32
+ /** Next move in the mainline */
33
+ next?: MoveNode;
34
+ /** Alternative variations from this position */
35
+ variations: MoveNode[];
36
+ }
37
+ /**
38
+ * Creates a new MoveNode with the given properties.
39
+ */
40
+ export declare function createMoveNode(props: {
41
+ id: string;
42
+ ply: number;
43
+ moveNumber: number;
44
+ color: 'w' | 'b';
45
+ san: string;
46
+ nags?: number[];
47
+ commentBefore?: string;
48
+ commentAfter?: string;
49
+ clock?: number;
50
+ emt?: number;
51
+ eval?: number;
52
+ depth?: number;
53
+ parent?: MoveNode;
54
+ }): MoveNode;
55
+ /**
56
+ * Creates a root node (starting position with no move).
57
+ */
58
+ export declare function createRootNode(): MoveNode;
59
+ //# sourceMappingURL=move-node.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"move-node.d.ts","sourceRoot":"","sources":["../../src/model/move-node.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,WAAW,QAAQ;IACrB,sCAAsC;IACtC,EAAE,EAAE,MAAM,CAAC;IAEX,oDAAoD;IACpD,GAAG,EAAE,MAAM,CAAC;IAEZ,oDAAoD;IACpD,UAAU,EAAE,MAAM,CAAC;IAEnB,kDAAkD;IAClD,KAAK,EAAE,GAAG,GAAG,GAAG,CAAC;IAEjB,yEAAyE;IACzE,GAAG,EAAE,MAAM,CAAC;IAEZ,2DAA2D;IAC3D,IAAI,EAAE,MAAM,EAAE,CAAC;IAEf,yCAAyC;IACzC,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB,wCAAwC;IACxC,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB,sCAAsC;IACtC,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf,mCAAmC;IACnC,GAAG,CAAC,EAAE,MAAM,CAAC;IAEb,qEAAqE;IACrE,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd,sCAAsC;IACtC,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf,uCAAuC;IACvC,MAAM,CAAC,EAAE,QAAQ,CAAC;IAElB,gCAAgC;IAChC,IAAI,CAAC,EAAE,QAAQ,CAAC;IAEhB,gDAAgD;IAChD,UAAU,EAAE,QAAQ,EAAE,CAAC;CAC1B;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,GAAG,GAAG,GAAG,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,QAAQ,CAAC;CACrB,GAAG,QAAQ,CAMX;AAED;;GAEG;AACH,wBAAgB,cAAc,IAAI,QAAQ,CAUzC"}
@@ -8,7 +8,7 @@ function e(o) {
8
8
  function n() {
9
9
  return {
10
10
  id: "root",
11
- ply: 0,
11
+ ply: -1,
12
12
  moveNumber: 0,
13
13
  color: "w",
14
14
  san: "",
@@ -1 +1 @@
1
- {"version":3,"file":"move-node.js","sources":["../../src/model/move-node.ts"],"sourcesContent":["/**\n * Represents a single move node in the game tree.\n * Each node can have a mainline continuation (next) and alternative variations.\n */\nexport interface MoveNode {\n /** Unique identifier for this node */\n id: string;\n\n /** Ply number (half-moves from start, 0-indexed) */\n ply: number;\n\n /** Move number in chess notation (1, 2, 3, etc.) */\n moveNumber: number;\n\n /** Color to move: 'w' for white, 'b' for black */\n color: 'w' | 'b';\n\n /** Standard Algebraic Notation of the move (e.g., \"e4\", \"Nf3\", \"O-O\") */\n san: string;\n\n /** Numeric Annotation Glyphs (e.g., $1 = \"!\", $2 = \"?\") */\n nags: number[];\n\n /** Comment appearing before this move */\n commentBefore?: string;\n\n /** Comment appearing after this move */\n commentAfter?: string;\n\n /** Clock time remaining in seconds */\n clock?: number;\n\n /** Elapsed move time in seconds */\n emt?: number;\n\n /** Position evaluation in centipawns (positive = white advantage) */\n eval?: number;\n\n /** Search depth for the evaluation */\n depth?: number;\n\n /** Parent node (undefined for root) */\n parent?: MoveNode;\n\n /** Next move in the mainline */\n next?: MoveNode;\n\n /** Alternative variations from this position */\n variations: MoveNode[];\n}\n\n/**\n * Creates a new MoveNode with the given properties.\n */\nexport function createMoveNode(props: {\n id: string;\n ply: number;\n moveNumber: number;\n color: 'w' | 'b';\n san: string;\n nags?: number[];\n commentBefore?: string;\n commentAfter?: string;\n clock?: number;\n emt?: number;\n eval?: number;\n depth?: number;\n parent?: MoveNode;\n}): MoveNode {\n return {\n ...props,\n nags: props.nags || [],\n variations: [],\n };\n}\n\n/**\n * Creates a root node (starting position with no move).\n */\nexport function createRootNode(): MoveNode {\n return {\n id: 'root',\n ply: 0,\n moveNumber: 0,\n color: 'w',\n san: '',\n nags: [],\n variations: [],\n };\n}\n"],"names":["createMoveNode","props","createRootNode"],"mappings":"AAsDO,SAASA,EAAeC,GAclB;AACT,SAAO;AAAA,IACH,GAAGA;AAAA,IACH,MAAMA,EAAM,QAAQ,CAAA;AAAA,IACpB,YAAY,CAAA;AAAA,EAAC;AAErB;AAKO,SAASC,IAA2B;AACvC,SAAO;AAAA,IACH,IAAI;AAAA,IACJ,KAAK;AAAA,IACL,YAAY;AAAA,IACZ,OAAO;AAAA,IACP,KAAK;AAAA,IACL,MAAM,CAAA;AAAA,IACN,YAAY,CAAA;AAAA,EAAC;AAErB;"}
1
+ {"version":3,"file":"move-node.js","sources":["../../src/model/move-node.ts"],"sourcesContent":["/**\n * Represents a single move node in the game tree.\n * Each node can have a mainline continuation (next) and alternative variations.\n */\nexport interface MoveNode {\n /** Unique identifier for this node */\n id: string;\n\n /** Ply number (half-moves from start, 0-indexed) */\n ply: number;\n\n /** Move number in chess notation (1, 2, 3, etc.) */\n moveNumber: number;\n\n /** Color to move: 'w' for white, 'b' for black */\n color: 'w' | 'b';\n\n /** Standard Algebraic Notation of the move (e.g., \"e4\", \"Nf3\", \"O-O\") */\n san: string;\n\n /** Numeric Annotation Glyphs (e.g., $1 = \"!\", $2 = \"?\") */\n nags: number[];\n\n /** Comment appearing before this move */\n commentBefore?: string;\n\n /** Comment appearing after this move */\n commentAfter?: string;\n\n /** Clock time remaining in seconds */\n clock?: number;\n\n /** Elapsed move time in seconds */\n emt?: number;\n\n /** Position evaluation in centipawns (positive = white advantage) */\n eval?: number;\n\n /** Search depth for the evaluation */\n depth?: number;\n\n /** Parent node (undefined for root) */\n parent?: MoveNode;\n\n /** Next move in the mainline */\n next?: MoveNode;\n\n /** Alternative variations from this position */\n variations: MoveNode[];\n}\n\n/**\n * Creates a new MoveNode with the given properties.\n */\nexport function createMoveNode(props: {\n id: string;\n ply: number;\n moveNumber: number;\n color: 'w' | 'b';\n san: string;\n nags?: number[];\n commentBefore?: string;\n commentAfter?: string;\n clock?: number;\n emt?: number;\n eval?: number;\n depth?: number;\n parent?: MoveNode;\n}): MoveNode {\n return {\n ...props,\n nags: props.nags || [],\n variations: [],\n };\n}\n\n/**\n * Creates a root node (starting position with no move).\n */\nexport function createRootNode(): MoveNode {\n return {\n id: 'root',\n ply: -1,\n moveNumber: 0,\n color: 'w',\n san: '',\n nags: [],\n variations: [],\n };\n}\n"],"names":["createMoveNode","props","createRootNode"],"mappings":"AAsDO,SAASA,EAAeC,GAclB;AACT,SAAO;AAAA,IACH,GAAGA;AAAA,IACH,MAAMA,EAAM,QAAQ,CAAA;AAAA,IACpB,YAAY,CAAA;AAAA,EAAC;AAErB;AAKO,SAASC,IAA2B;AACvC,SAAO;AAAA,IACH,IAAI;AAAA,IACJ,KAAK;AAAA,IACL,YAAY;AAAA,IACZ,OAAO;AAAA,IACP,KAAK;AAAA,IACL,MAAM,CAAA;AAAA,IACN,YAAY,CAAA;AAAA,EAAC;AAErB;"}
@@ -0,0 +1,15 @@
1
+ import { MoveNode } from './move-node.js';
2
+ /**
3
+ * Represents a complete chess game parsed from PGN.
4
+ */
5
+ export interface PGNGame {
6
+ /** PGN headers (Event, Site, Date, White, Black, Result, etc.) */
7
+ headers: Record<string, string>;
8
+ /** Root node of the game tree (starting position) */
9
+ root: MoveNode;
10
+ }
11
+ /**
12
+ * Creates a new PGNGame with the given headers and root node.
13
+ */
14
+ export declare function createPGNGame(headers?: Record<string, string>, root?: MoveNode): PGNGame;
15
+ //# sourceMappingURL=pgn-game.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pgn-game.d.ts","sourceRoot":"","sources":["../../src/model/pgn-game.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE1C;;GAEG;AACH,MAAM,WAAW,OAAO;IACpB,kEAAkE;IAClE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAEhC,qDAAqD;IACrD,IAAI,EAAE,QAAQ,CAAC;CAClB;AAED;;GAEG;AACH,wBAAgB,aAAa,CACzB,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,EACpC,IAAI,CAAC,EAAE,QAAQ,GAChB,OAAO,CAaT"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Parses PGN headers from header tokens.
3
+ * Format: [Key "Value"]
4
+ */
5
+ export declare function parseHeaders(headerTokens: string[]): Record<string, string>;
6
+ /**
7
+ * Parses a single header string.
8
+ */
9
+ export declare function parseHeader(header: string): {
10
+ key: string;
11
+ value: string;
12
+ } | null;
13
+ //# sourceMappingURL=header-parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"header-parser.d.ts","sourceRoot":"","sources":["../../src/parser/header-parser.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,wBAAgB,YAAY,CAAC,YAAY,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAY3E;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAOjF"}
@@ -0,0 +1,32 @@
1
+ import { PGNGame } from '../model/pgn-game.js';
2
+ /**
3
+ * Main PGN parser that converts PGN text into a game tree structure.
4
+ */
5
+ export declare class PGNParser {
6
+ private tokens;
7
+ private position;
8
+ private nodeIdCounter;
9
+ /**
10
+ * Parses PGN text and returns a PGNGame object.
11
+ */
12
+ parse(pgnText: string): PGNGame;
13
+ /**
14
+ * Parses all headers at the beginning of the PGN.
15
+ */
16
+ private parseHeaders;
17
+ /**
18
+ * Parses a sequence of moves and variations, building the tree structure.
19
+ * Returns the FIRST node created in this sequence (for variations).
20
+ */
21
+ private parseMoveSequence;
22
+ private current;
23
+ private advance;
24
+ private consume;
25
+ private isAtEnd;
26
+ private generateNodeId;
27
+ }
28
+ /**
29
+ * Convenience function to parse PGN text.
30
+ */
31
+ export declare function parsePGN(pgnText: string): PGNGame;
32
+ //# sourceMappingURL=pgn-parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pgn-parser.d.ts","sourceRoot":"","sources":["../../src/parser/pgn-parser.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,OAAO,EAAiB,MAAM,sBAAsB,CAAC;AAE9D;;GAEG;AACH,qBAAa,SAAS;IAClB,OAAO,CAAC,MAAM,CAAe;IAC7B,OAAO,CAAC,QAAQ,CAAa;IAC7B,OAAO,CAAC,aAAa,CAAa;IAElC;;OAEG;IACH,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO;IAkB/B;;OAEG;IACH,OAAO,CAAC,YAAY;IAcpB;;;OAGG;IACH,OAAO,CAAC,iBAAiB;IAqIzB,OAAO,CAAC,OAAO;IAIf,OAAO,CAAC,OAAO;IAIf,OAAO,CAAC,OAAO;IAUf,OAAO,CAAC,OAAO;IAIf,OAAO,CAAC,cAAc;CAGzB;AAED;;GAEG;AACH,wBAAgB,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAGjD"}
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Token types for PGN lexical analysis
3
+ */
4
+ export declare enum TokenType {
5
+ HEADER = "HEADER",
6
+ MOVE_NUMBER = "MOVE_NUMBER",
7
+ MOVE = "MOVE",
8
+ NAG = "NAG",
9
+ COMMENT = "COMMENT",
10
+ VARIATION_START = "VARIATION_START",
11
+ VARIATION_END = "VARIATION_END",
12
+ RESULT = "RESULT",
13
+ EOF = "EOF"
14
+ }
15
+ /**
16
+ * Represents a single token from PGN text
17
+ */
18
+ export interface Token {
19
+ type: TokenType;
20
+ value: string;
21
+ line: number;
22
+ column: number;
23
+ }
24
+ /**
25
+ * Tokenizes PGN text into a stream of tokens.
26
+ */
27
+ export declare class PGNTokenizer {
28
+ private input;
29
+ private position;
30
+ private line;
31
+ private column;
32
+ constructor(input: string);
33
+ /**
34
+ * Returns all tokens from the input.
35
+ */
36
+ tokenize(): Token[];
37
+ /**
38
+ * Gets the next token from the input.
39
+ */
40
+ private nextToken;
41
+ private readHeader;
42
+ private readBraceComment;
43
+ private readLineComment;
44
+ private readNAG;
45
+ private readResult;
46
+ private readMoveNumber;
47
+ private readMove;
48
+ private isMoveStart;
49
+ private isMoveChar;
50
+ private isResultStart;
51
+ private isDigit;
52
+ private skipWhitespace;
53
+ private current;
54
+ private advance;
55
+ private createToken;
56
+ }
57
+ //# sourceMappingURL=tokenizer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tokenizer.d.ts","sourceRoot":"","sources":["../../src/parser/tokenizer.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,oBAAY,SAAS;IACjB,MAAM,WAAW;IACjB,WAAW,gBAAgB;IAC3B,IAAI,SAAS;IACb,GAAG,QAAQ;IACX,OAAO,YAAY;IACnB,eAAe,oBAAoB;IACnC,aAAa,kBAAkB;IAC/B,MAAM,WAAW;IACjB,GAAG,QAAQ;CACd;AAED;;GAEG;AACH,MAAM,WAAW,KAAK;IAClB,IAAI,EAAE,SAAS,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,qBAAa,YAAY;IACrB,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,QAAQ,CAAa;IAC7B,OAAO,CAAC,IAAI,CAAa;IACzB,OAAO,CAAC,MAAM,CAAa;gBAEf,KAAK,EAAE,MAAM;IAIzB;;OAEG;IACH,QAAQ,IAAI,KAAK,EAAE;IAYnB;;OAEG;IACH,OAAO,CAAC,SAAS;IAyDjB,OAAO,CAAC,UAAU;IAwBlB,OAAO,CAAC,gBAAgB;IAexB,OAAO,CAAC,eAAe;IAWvB,OAAO,CAAC,OAAO;IAWf,OAAO,CAAC,UAAU;IAkBlB,OAAO,CAAC,cAAc;IAetB,OAAO,CAAC,QAAQ;IAchB,OAAO,CAAC,WAAW;IAInB,OAAO,CAAC,UAAU;IASlB,OAAO,CAAC,aAAa;IAUrB,OAAO,CAAC,OAAO;IAIf,OAAO,CAAC,cAAc;IAStB,OAAO,CAAC,OAAO;IAIf,OAAO,CAAC,OAAO;IAcf,OAAO,CAAC,WAAW;CAQtB"}
package/dist/style.css CHANGED
@@ -1 +1 @@
1
- .pgn-viewer{font-family:Segoe UI,Tahoma,Geneva,Verdana,sans-serif;font-size:14px;line-height:1.8;padding:16px;background-color:#f9f9f9;border:1px solid #ddd;border-radius:4px;max-width:100%;overflow-x:auto}.pgn-move-number{color:#666;margin-right:4px;font-weight:600}.pgn-move{display:inline-block;padding:2px 6px;margin:0 2px;border-radius:3px;transition:background-color .2s}.pgn-move:hover{background-color:#e0e0e0}.pgn-move-current{background-color:#4a90e2;color:#fff;font-weight:600}.pgn-move-current:hover{background-color:#357abd}.pgn-nag{color:#d9534f;margin-left:2px;font-weight:700}.pgn-comment{color:#5a5a5a;font-style:italic;margin:0 4px}.pgn-annotation{color:#888;font-size:12px;margin-left:4px}.pgn-variation{margin-top:4px;margin-bottom:4px;color:#555}.pgn-controls{display:flex;gap:8px;padding:12px;background-color:#f0f0f0;border-radius:4px;justify-content:center}.pgn-control-button{background-color:#4a90e2;color:#fff;border:none;border-radius:4px;padding:8px 16px;font-size:16px;cursor:pointer;transition:background-color .2s;min-width:44px}.pgn-control-button:hover:not(:disabled){background-color:#357abd}.pgn-control-button:disabled{background-color:#ccc;cursor:not-allowed;opacity:.6}.pgn-control-button:active:not(:disabled){transform:scale(.95)}
1
+ .pgn-viewer{font-family:Segoe UI,Tahoma,Geneva,Verdana,sans-serif;font-size:14px;line-height:1.8;padding:16px;background-color:#f9f9f9;border:1px solid #ddd;border-radius:4px;max-width:100%;overflow-x:auto}.pgn-move-number{color:#666;margin-right:4px;font-weight:600}.pgn-row{display:flex;flex-wrap:wrap;align-items:baseline}.pgn-move{display:inline-block;padding:2px 6px;margin:0 2px;border-radius:3px;transition:background-color .2s;cursor:pointer}.pgn-move:hover{background-color:#e0e0e0}.pgn-active{background-color:#4a90e2;color:#fff;font-weight:600}.pgn-active:hover{background-color:#357abd}.pgn-nag{color:#d9534f;margin-left:2px;font-weight:700}.pgn-comment{color:#5a5a5a;font-style:italic;margin:0 4px}.pgn-annotation{color:#888;font-size:12px;margin-left:4px}.pgn-variation{display:block;width:100%;margin-top:4px;margin-bottom:4px;color:#555}.pgn-controls{display:flex;gap:8px;padding:12px;background-color:#f0f0f0;border-radius:4px;justify-content:center}.pgn-control-button{background-color:#4a90e2;color:#fff;border:none;border-radius:4px;padding:8px 16px;font-size:16px;cursor:pointer;transition:background-color .2s;min-width:44px}.pgn-control-button:hover:not(:disabled){background-color:#357abd}.pgn-control-button:disabled{background-color:#ccc;cursor:not-allowed;opacity:.6}.pgn-control-button:active:not(:disabled){transform:scale(.95)}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Parses time annotations from comments.
3
+ * Supports: [%clk 0:04:32], [%emt 0:00:03]
4
+ */
5
+ export declare function parseTimeAnnotation(comment: string): {
6
+ clock?: number;
7
+ emt?: number;
8
+ };
9
+ /**
10
+ * Parses evaluation annotation from comments.
11
+ * Supports: [%eval +0.35], [%eval -1.2], [%eval #3]
12
+ */
13
+ export declare function parseEvalAnnotation(comment: string): {
14
+ eval?: number;
15
+ depth?: number;
16
+ };
17
+ /**
18
+ * Parses all annotations from a comment string.
19
+ */
20
+ export declare function parseAnnotations(comment: string): {
21
+ clock?: number;
22
+ emt?: number;
23
+ eval?: number;
24
+ depth?: number;
25
+ cleanComment: string;
26
+ };
27
+ //# sourceMappingURL=annotation-parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"annotation-parser.d.ts","sourceRoot":"","sources":["../../src/utils/annotation-parser.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG;IAClD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;CAChB,CAoBA;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG;IAClD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;CAClB,CAuBA;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG;IAC/C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;CACxB,CAkBA"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Maps NAG (Numeric Annotation Glyph) codes to their symbolic representations.
3
+ */
4
+ export declare const NAG_SYMBOLS: Record<number, string>;
5
+ /**
6
+ * Converts a NAG code to its symbolic representation.
7
+ */
8
+ export declare function nagToSymbol(nag: number): string;
9
+ /**
10
+ * Converts an array of NAG codes to their symbolic representations.
11
+ */
12
+ export declare function nagsToSymbols(nags: number[]): string[];
13
+ //# sourceMappingURL=nag-symbols.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nag-symbols.d.ts","sourceRoot":"","sources":["../../src/utils/nag-symbols.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,eAAO,MAAM,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAsB9C,CAAC;AAEF;;GAEG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE/C;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAEtD"}
@@ -0,0 +1,17 @@
1
+ import { GameCursor } from '../cursor/game-cursor.js';
2
+ import './styles.css';
3
+ export interface PGNControlsProps {
4
+ /** The game cursor to control */
5
+ cursor: GameCursor;
6
+ /** Callback when position changes */
7
+ onPositionChange?: (cursor: GameCursor) => void;
8
+ /** Enable keyboard controls (default: true) */
9
+ enableKeyboard?: boolean;
10
+ /** Custom class name */
11
+ className?: string;
12
+ }
13
+ /**
14
+ * Navigation controls for a chess game.
15
+ */
16
+ export declare function PGNControls({ cursor, onPositionChange, enableKeyboard, className, }: PGNControlsProps): import("react/jsx-runtime").JSX.Element;
17
+ //# sourceMappingURL=PGNControls.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PGNControls.d.ts","sourceRoot":"","sources":["../../src/viewer/PGNControls.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AACtD,OAAO,cAAc,CAAC;AAEtB,MAAM,WAAW,gBAAgB;IAC7B,iCAAiC;IACjC,MAAM,EAAE,UAAU,CAAC;IACnB,qCAAqC;IACrC,gBAAgB,CAAC,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,IAAI,CAAC;IAChD,+CAA+C;IAC/C,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,wBAAwB;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,EACxB,MAAM,EACN,gBAAgB,EAChB,cAAqB,EACrB,SAAc,GACjB,EAAE,gBAAgB,2CA6FlB"}
@@ -0,0 +1,18 @@
1
+ import { MoveNode } from '../model/move-node.js';
2
+ import { GameCursor } from '../cursor/game-cursor.js';
3
+ import './styles.css';
4
+ export interface PGNViewerProps {
5
+ /** The root node of the game tree */
6
+ root: MoveNode;
7
+ /** Optional cursor for external control */
8
+ cursor?: GameCursor;
9
+ /** Callback when a move is clicked */
10
+ onMoveClick?: (node: MoveNode) => void;
11
+ /** Custom class name */
12
+ className?: string;
13
+ }
14
+ /**
15
+ * Displays a chess game in PGN notation with support for variations.
16
+ */
17
+ export declare function PGNViewer({ root, cursor: externalCursor, onMoveClick, className, }: PGNViewerProps): import("react/jsx-runtime").JSX.Element;
18
+ //# sourceMappingURL=PGNViewer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PGNViewer.d.ts","sourceRoot":"","sources":["../../src/viewer/PGNViewer.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAEtD,OAAO,cAAc,CAAC;AAEtB,MAAM,WAAW,cAAc;IAC3B,qCAAqC;IACrC,IAAI,EAAE,QAAQ,CAAC;IACf,2CAA2C;IAC3C,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,sCAAsC;IACtC,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,QAAQ,KAAK,IAAI,CAAC;IACvC,wBAAwB;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,EACtB,IAAI,EACJ,MAAM,EAAE,cAAc,EACtB,WAAW,EACX,SAAc,GACjB,EAAE,cAAc,2CAwBhB"}
@@ -1,94 +1,107 @@
1
- import { jsx as o, jsxs as l, Fragment as v } from "react/jsx-runtime";
2
- import { useState as f, useEffect as $, useCallback as N } from "react";
3
- import { GameCursor as x } from "../cursor/game-cursor.js";
4
- import { nagToSymbol as b } from "../utils/nag-symbols.js";
1
+ import { jsx as c, jsxs as p, Fragment as w } from "react/jsx-runtime";
2
+ import { useState as d, useEffect as b, useCallback as S } from "react";
3
+ import { GameCursor as E } from "../cursor/game-cursor.js";
4
+ import { nagToSymbol as j } from "../utils/nag-symbols.js";
5
5
  /* empty css */
6
- function k({
7
- root: s,
8
- cursor: a,
9
- onMoveClick: t,
10
- className: i = ""
6
+ function F({
7
+ root: h,
8
+ cursor: l,
9
+ onMoveClick: e,
10
+ className: a = ""
11
11
  }) {
12
- const [e] = f(() => new x(s)), n = a || e, [p, c] = f(n.current.id);
13
- $(() => {
14
- c(n.current.id);
15
- }, [n.current.id]);
16
- const m = N(
17
- (r) => {
18
- n.goTo(r.id), c(r.id), t == null || t(r);
12
+ const [i] = d(() => new E(h)), r = l || i, [f, n] = d(r.current.id);
13
+ b(() => {
14
+ n(r.current.id);
15
+ }, [r.current.id]);
16
+ const t = S(
17
+ (s) => {
18
+ r.goTo(s.id), n(s.id), e == null || e(s);
19
19
  },
20
- [n, t]
20
+ [r, e]
21
21
  );
22
- return /* @__PURE__ */ o("div", { className: `pgn-viewer ${i}`, children: h(s, p, m, 0) });
22
+ return /* @__PURE__ */ c("div", { className: `pgn-viewer ${a}`, children: v(h, f, t, 0) });
23
23
  }
24
- function h(s, a, t, i) {
25
- const e = [];
26
- let n = s.next;
27
- for (; n; ) {
28
- const p = n.id === a, c = n.color === "w";
29
- n.commentBefore && e.push(
30
- /* @__PURE__ */ o("span", { className: "pgn-comment", children: `{${n.commentBefore}}` }, `comment-before-${n.id}`)
31
- ), c && e.push(
32
- /* @__PURE__ */ l("span", { className: "pgn-move-number", children: [
24
+ function v(h, l, e, a) {
25
+ const i = [];
26
+ let r = h.next;
27
+ const f = (n, t, s = !1) => {
28
+ const o = n.id === l, m = n.nags.map(j).join(""), u = [];
29
+ n.commentBefore && u.push(
30
+ /* @__PURE__ */ c("span", { className: "pgn-comment", children: `{${n.commentBefore}}` }, `comment-before-${n.id}`)
31
+ ), t && u.push(
32
+ /* @__PURE__ */ p("span", { className: "pgn-move-number", children: [
33
33
  n.moveNumber,
34
- "."
34
+ s ? "..." : "."
35
35
  ] }, `move-num-${n.id}`)
36
- );
37
- const m = n.nags.map(b).join("");
38
- e.push(
39
- /* @__PURE__ */ l(
36
+ ), u.push(
37
+ /* @__PURE__ */ p(
40
38
  "span",
41
39
  {
42
- className: `pgn-move ${p ? "pgn-move-current" : ""}`,
43
- onClick: () => t(n),
44
- style: { cursor: "pointer" },
40
+ className: `pgn-move ${o ? "pgn-active" : ""}`,
41
+ onClick: ($) => {
42
+ $.stopPropagation(), e(n);
43
+ },
45
44
  children: [
46
45
  n.san,
47
- m && /* @__PURE__ */ o("span", { className: "pgn-nag", children: m })
46
+ m && /* @__PURE__ */ c("span", { className: "pgn-nag", children: m })
48
47
  ]
49
48
  },
50
49
  n.id
51
50
  )
52
- ), n.commentAfter && e.push(
53
- /* @__PURE__ */ o("span", { className: "pgn-comment", children: `{${n.commentAfter}}` }, `comment-after-${n.id}`)
51
+ ), n.commentAfter && u.push(
52
+ /* @__PURE__ */ c("span", { className: "pgn-comment", children: `{${n.commentAfter}}` }, `comment-after-${n.id}`)
54
53
  );
55
- const r = [];
54
+ const g = [];
56
55
  if (n.clock !== void 0) {
57
- const u = Math.floor(n.clock / 3600), d = Math.floor(n.clock % 3600 / 60), g = n.clock % 60;
58
- r.push(`clk ${u}:${d.toString().padStart(2, "0")}:${g.toString().padStart(2, "0")}`);
56
+ const $ = Math.floor(n.clock / 3600), N = Math.floor(n.clock % 3600 / 60), x = n.clock % 60;
57
+ g.push(`clk ${$}:${N.toString().padStart(2, "0")}:${x.toString().padStart(2, "0")}`);
59
58
  }
60
- n.eval !== void 0 && r.push(`eval ${n.eval > 0 ? "+" : ""}${n.eval.toFixed(2)}`), r.length > 0 && e.push(
61
- /* @__PURE__ */ l("span", { className: "pgn-annotation", children: [
59
+ return n.eval !== void 0 && g.push(`eval ${n.eval > 0 ? "+" : ""}${n.eval.toFixed(2)}`), g.length > 0 && u.push(
60
+ /* @__PURE__ */ p("span", { className: "pgn-annotation", children: [
62
61
  "[",
63
- r.join(", "),
62
+ g.join(", "),
64
63
  "]"
65
64
  ] }, `annotations-${n.id}`)
66
- ), n.variations.length > 0 && n.variations.forEach((u, d) => {
67
- e.push(
68
- /* @__PURE__ */ l(
69
- "div",
70
- {
71
- className: "pgn-variation",
72
- style: { marginLeft: `${(i + 1) * 20}px` },
73
- children: [
74
- "(",
75
- h(
76
- { ...n, next: u },
77
- a,
78
- t,
79
- i + 1
80
- ),
81
- ")"
82
- ]
83
- },
84
- `variation-${n.id}-${d}`
85
- )
65
+ ), u;
66
+ };
67
+ for (; r; ) {
68
+ const n = r.color === "w" ? r : null, t = n && n.next && n.next.color === "b" ? n.next : r.color === "b" ? r : null;
69
+ if (n) {
70
+ const s = [];
71
+ s.push(...f(n, !0)), t && t !== r && s.push(...f(t, !1)), i.push(
72
+ /* @__PURE__ */ c("div", { className: "pgn-row", children: s }, `row-${n.id}`)
73
+ ), n.variations.length > 0 && n.variations.forEach((o, m) => {
74
+ i.push(
75
+ /* @__PURE__ */ p("div", { className: "pgn-variation", style: { marginLeft: (a + 1) * 20 }, children: [
76
+ "(",
77
+ v({ ...n, next: o }, l, e, a + 1),
78
+ ")"
79
+ ] }, `var-w-${n.id}-${m}`)
80
+ );
81
+ }), t && t !== r ? (t.variations.length > 0 && t.variations.forEach((o, m) => {
82
+ i.push(
83
+ /* @__PURE__ */ p("div", { className: "pgn-variation", style: { marginLeft: (a + 1) * 20 }, children: [
84
+ "(",
85
+ v({ ...t, next: o }, l, e, a + 1),
86
+ ")"
87
+ ] }, `var-b-${t.id}-${m}`)
88
+ );
89
+ }), r = t.next) : r = n.next;
90
+ } else t && (i.push(
91
+ /* @__PURE__ */ c("div", { className: "pgn-row", children: f(t, !0, !0) }, `row-${t.id}`)
92
+ ), t.variations.length > 0 && t.variations.forEach((s, o) => {
93
+ i.push(
94
+ /* @__PURE__ */ p("div", { className: "pgn-variation", style: { marginLeft: (a + 1) * 20 }, children: [
95
+ "(",
96
+ v({ ...t, next: s }, l, e, a + 1),
97
+ ")"
98
+ ] }, `var-b-${t.id}-${o}`)
86
99
  );
87
- }), n = n.next;
100
+ }), r = t.next);
88
101
  }
89
- return /* @__PURE__ */ o(v, { children: e });
102
+ return /* @__PURE__ */ c(w, { children: i });
90
103
  }
91
104
  export {
92
- k as PGNViewer
105
+ F as PGNViewer
93
106
  };
94
107
  //# sourceMappingURL=PGNViewer.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"PGNViewer.js","sources":["../../src/viewer/PGNViewer.tsx"],"sourcesContent":["'use client';\n\nimport React, { useState, useEffect, useCallback } from 'react';\nimport { MoveNode } from '../model/move-node.js';\nimport { GameCursor } from '../cursor/game-cursor.js';\nimport { nagToSymbol } from '../utils/nag-symbols.js';\nimport './styles.css';\n\nexport interface PGNViewerProps {\n /** The root node of the game tree */\n root: MoveNode;\n /** Optional cursor for external control */\n cursor?: GameCursor;\n /** Callback when a move is clicked */\n onMoveClick?: (node: MoveNode) => void;\n /** Custom class name */\n className?: string;\n}\n\n/**\n * Displays a chess game in PGN notation with support for variations.\n */\nexport function PGNViewer({\n root,\n cursor: externalCursor,\n onMoveClick,\n className = '',\n}: PGNViewerProps) {\n const [internalCursor] = useState(() => new GameCursor(root));\n const cursor = externalCursor || internalCursor;\n const [currentNodeId, setCurrentNodeId] = useState(cursor.current.id);\n\n // Update when cursor changes\n useEffect(() => {\n setCurrentNodeId(cursor.current.id);\n }, [cursor.current.id]);\n\n const handleMoveClick = useCallback(\n (node: MoveNode) => {\n cursor.goTo(node.id);\n setCurrentNodeId(node.id);\n onMoveClick?.(node);\n },\n [cursor, onMoveClick]\n );\n\n return (\n <div className={`pgn-viewer ${className}`}>\n {renderMoveTree(root, currentNodeId, handleMoveClick, 0)}\n </div>\n );\n}\n\n/**\n * Recursively renders the move tree with proper indentation for variations.\n */\nfunction renderMoveTree(\n node: MoveNode,\n currentNodeId: string,\n onMoveClick: (node: MoveNode) => void,\n depth: number\n): React.ReactNode {\n const elements: React.ReactNode[] = [];\n let currentNode: MoveNode | undefined = node.next;\n let moveIndex = 0;\n\n while (currentNode) {\n const isCurrentMove = currentNode.id === currentNodeId;\n const showMoveNumber = currentNode.color === 'w';\n\n // Comment before move\n if (currentNode.commentBefore) {\n elements.push(\n <span key={`comment-before-${currentNode.id}`} className=\"pgn-comment\">\n {`{${currentNode.commentBefore}}`}\n </span>\n );\n }\n\n // Move number for white moves\n if (showMoveNumber) {\n elements.push(\n <span key={`move-num-${currentNode.id}`} className=\"pgn-move-number\">\n {currentNode.moveNumber}.\n </span>\n );\n }\n\n // The move itself\n const nags = currentNode.nags.map(nagToSymbol).join('');\n elements.push(\n <span\n key={currentNode.id}\n className={`pgn-move ${isCurrentMove ? 'pgn-move-current' : ''}`}\n onClick={() => onMoveClick(currentNode!)}\n style={{ cursor: 'pointer' }}\n >\n {currentNode.san}\n {nags && <span className=\"pgn-nag\">{nags}</span>}\n </span>\n );\n\n // Comment after move\n if (currentNode.commentAfter) {\n elements.push(\n <span key={`comment-after-${currentNode.id}`} className=\"pgn-comment\">\n {`{${currentNode.commentAfter}}`}\n </span>\n );\n }\n\n // Annotations (clock, eval)\n const annotations: string[] = [];\n if (currentNode.clock !== undefined) {\n const hours = Math.floor(currentNode.clock / 3600);\n const minutes = Math.floor((currentNode.clock % 3600) / 60);\n const seconds = currentNode.clock % 60;\n annotations.push(`clk ${hours}:${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`);\n }\n if (currentNode.eval !== undefined) {\n annotations.push(`eval ${currentNode.eval > 0 ? '+' : ''}${currentNode.eval.toFixed(2)}`);\n }\n\n if (annotations.length > 0) {\n elements.push(\n <span key={`annotations-${currentNode.id}`} className=\"pgn-annotation\">\n [{annotations.join(', ')}]\n </span>\n );\n }\n\n // Variations\n if (currentNode.variations.length > 0) {\n currentNode.variations.forEach((variation, index) => {\n elements.push(\n <div\n key={`variation-${currentNode!.id}-${index}`}\n className=\"pgn-variation\"\n style={{ marginLeft: `${(depth + 1) * 20}px` }}\n >\n (\n {renderMoveTree(\n { ...currentNode!, next: variation },\n currentNodeId,\n onMoveClick,\n depth + 1\n )}\n )\n </div>\n );\n });\n }\n\n currentNode = currentNode.next;\n moveIndex++;\n }\n\n return <>{elements}</>;\n}\n"],"names":["PGNViewer","root","externalCursor","onMoveClick","className","internalCursor","useState","GameCursor","cursor","currentNodeId","setCurrentNodeId","useEffect","handleMoveClick","useCallback","node","jsx","renderMoveTree","depth","elements","currentNode","isCurrentMove","showMoveNumber","jsxs","nags","nagToSymbol","annotations","hours","minutes","seconds","variation","index"],"mappings":"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"}
1
+ {"version":3,"file":"PGNViewer.js","sources":["../../src/viewer/PGNViewer.tsx"],"sourcesContent":["'use client';\n\nimport React, { useState, useEffect, useCallback } from 'react';\nimport { MoveNode } from '../model/move-node.js';\nimport { GameCursor } from '../cursor/game-cursor.js';\nimport { nagToSymbol } from '../utils/nag-symbols.js';\nimport './styles.css';\n\nexport interface PGNViewerProps {\n /** The root node of the game tree */\n root: MoveNode;\n /** Optional cursor for external control */\n cursor?: GameCursor;\n /** Callback when a move is clicked */\n onMoveClick?: (node: MoveNode) => void;\n /** Custom class name */\n className?: string;\n}\n\n/**\n * Displays a chess game in PGN notation with support for variations.\n */\nexport function PGNViewer({\n root,\n cursor: externalCursor,\n onMoveClick,\n className = '',\n}: PGNViewerProps) {\n const [internalCursor] = useState(() => new GameCursor(root));\n const cursor = externalCursor || internalCursor;\n const [currentNodeId, setCurrentNodeId] = useState(cursor.current.id);\n\n // Update when cursor changes\n useEffect(() => {\n setCurrentNodeId(cursor.current.id);\n }, [cursor.current.id]);\n\n const handleMoveClick = useCallback(\n (node: MoveNode) => {\n cursor.goTo(node.id);\n setCurrentNodeId(node.id);\n onMoveClick?.(node);\n },\n [cursor, onMoveClick]\n );\n\n return (\n <div className={`pgn-viewer ${className}`}>\n {renderMoveTree(root, currentNodeId, handleMoveClick, 0)}\n </div>\n );\n}\n\n/**\n * Recursively renders the move tree.\n * Groups Mainline moves into rows (White + Black).\n * Variations are rendered in nested blocks.\n */\nfunction renderMoveTree(\n parentNode: MoveNode,\n currentNodeId: string,\n onMoveClick: (node: MoveNode) => void,\n depth: number\n): React.ReactNode {\n const elements: React.ReactNode[] = [];\n let currentNode: MoveNode | undefined = parentNode.next;\n\n // Helper to render a single move node\n const renderMoveNode = (node: MoveNode, showMoveNumber: boolean, isBlackStub: boolean = false) => {\n const isCurrentMove = node.id === currentNodeId;\n const nags = node.nags.map(nagToSymbol).join('');\n\n const nodeElements: React.ReactNode[] = [];\n\n // Comment before\n if (node.commentBefore) {\n nodeElements.push(\n <span key={`comment-before-${node.id}`} className=\"pgn-comment\">\n {`{${node.commentBefore}}`}\n </span>\n );\n }\n\n // Move Number\n if (showMoveNumber) {\n nodeElements.push(\n <span key={`move-num-${node.id}`} className=\"pgn-move-number\">\n {node.moveNumber}{isBlackStub ? '...' : '.'}\n </span>\n );\n }\n\n // The Move\n nodeElements.push(\n <span\n key={node.id}\n className={`pgn-move ${isCurrentMove ? 'pgn-active' : ''}`}\n onClick={(e) => {\n e.stopPropagation();\n onMoveClick(node);\n }}\n >\n {node.san}\n {nags && <span className=\"pgn-nag\">{nags}</span>}\n </span>\n );\n\n // Comment after\n if (node.commentAfter) {\n nodeElements.push(\n <span key={`comment-after-${node.id}`} className=\"pgn-comment\">\n {`{${node.commentAfter}}`}\n </span>\n );\n }\n\n // Annotations (clock, eval)\n const annotations: string[] = [];\n if (node.clock !== undefined) {\n const hours = Math.floor(node.clock / 3600);\n const minutes = Math.floor((node.clock % 3600) / 60);\n const seconds = node.clock % 60;\n annotations.push(`clk ${hours}:${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`);\n }\n if (node.eval !== undefined) {\n annotations.push(`eval ${node.eval > 0 ? '+' : ''}${node.eval.toFixed(2)}`);\n }\n\n if (annotations.length > 0) {\n nodeElements.push(\n <span key={`annotations-${node.id}`} className=\"pgn-annotation\">\n [{annotations.join(', ')}]\n </span>\n );\n }\n\n return nodeElements;\n };\n\n while (currentNode) {\n const whiteMove = currentNode.color === 'w' ? currentNode : null;\n const blackMove = whiteMove && whiteMove.next && whiteMove.next.color === 'b' ? whiteMove.next : (currentNode.color === 'b' ? currentNode : null);\n\n // If we have a white move (standard start of row)\n if (whiteMove) {\n const rowContent: React.ReactNode[] = [];\n\n // Render White\n rowContent.push(...renderMoveNode(whiteMove, true));\n\n // Render Black (if part of this pair)\n if (blackMove && blackMove !== currentNode) { // blackMove exists and follows white\n rowContent.push(...renderMoveNode(blackMove, false));\n }\n\n elements.push(\n <div key={`row-${whiteMove.id}`} className=\"pgn-row\">\n {rowContent}\n </div>\n );\n\n // Handle Variations & Logic for Next Loop\n\n // Check for variations on White\n if (whiteMove.variations.length > 0) {\n whiteMove.variations.forEach((v, i) => {\n elements.push(\n <div key={`var-w-${whiteMove.id}-${i}`} className=\"pgn-variation\" style={{ marginLeft: (depth + 1) * 20 }}>\n ({renderMoveTree({ ...whiteMove, next: v }, currentNodeId, onMoveClick, depth + 1)})\n </div>\n );\n });\n }\n\n // Check for variations on Black (if we processed it)\n if (blackMove && blackMove !== currentNode) {\n if (blackMove.variations.length > 0) {\n blackMove.variations.forEach((v, i) => {\n elements.push(\n <div key={`var-b-${blackMove.id}-${i}`} className=\"pgn-variation\" style={{ marginLeft: (depth + 1) * 20 }}>\n ({renderMoveTree({ ...blackMove, next: v }, currentNodeId, onMoveClick, depth + 1)})\n </div>\n );\n });\n }\n currentNode = blackMove.next;\n } else {\n // No black move followed, or we are at end of this line\n currentNode = whiteMove.next;\n }\n\n } else if (blackMove) {\n // We started with Black (e.g. 1... d5 variation or start from position)\n // Render just the black move in a row\n elements.push(\n <div key={`row-${blackMove.id}`} className=\"pgn-row\">\n {renderMoveNode(blackMove, true, true)}\n </div>\n );\n\n if (blackMove.variations.length > 0) {\n blackMove.variations.forEach((v, i) => {\n elements.push(\n <div key={`var-b-${blackMove.id}-${i}`} className=\"pgn-variation\" style={{ marginLeft: (depth + 1) * 20 }}>\n ({renderMoveTree({ ...blackMove, next: v }, currentNodeId, onMoveClick, depth + 1)})\n </div>\n );\n });\n }\n\n currentNode = blackMove.next;\n }\n }\n\n return <>{elements}</>;\n}\n\n"],"names":["PGNViewer","root","externalCursor","onMoveClick","className","internalCursor","useState","GameCursor","cursor","currentNodeId","setCurrentNodeId","useEffect","handleMoveClick","useCallback","node","jsx","renderMoveTree","parentNode","depth","elements","currentNode","renderMoveNode","showMoveNumber","isBlackStub","isCurrentMove","nags","nagToSymbol","nodeElements","jsxs","e","annotations","hours","minutes","seconds","whiteMove","blackMove","rowContent","v","i"],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ export { PGNViewer } from './PGNViewer.js';
2
+ export { PGNControls } from './PGNControls.js';
3
+ export type { PGNViewerProps } from './PGNViewer.js';
4
+ export type { PGNControlsProps } from './PGNControls.js';
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/viewer/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE/C,YAAY,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AACrD,YAAY,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pgn-viewer-parser",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "A production-ready PGN parser and viewer library for chess, with full support for variations, comments, NAGs, and annotations",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.js",
@@ -21,7 +21,7 @@
21
21
  "README.md"
22
22
  ],
23
23
  "scripts": {
24
- "build": "tsc && vite build",
24
+ "build": "vite build && tsc --emitDeclarationOnly",
25
25
  "test": "vitest run",
26
26
  "test:watch": "vitest",
27
27
  "type-check": "tsc --noEmit",
@@ -41,8 +41,8 @@
41
41
  "author": "",
42
42
  "license": "MIT",
43
43
  "peerDependencies": {
44
- "react": "^18.0.0",
45
- "react-dom": "^18.0.0"
44
+ "react": ">=18",
45
+ "react-dom": ">=18"
46
46
  },
47
47
  "peerDependenciesMeta": {
48
48
  "react": {
@@ -66,4 +66,4 @@
66
66
  "type": "git",
67
67
  "url": "https://github.com/yourusername/pgn-viewer-parser.git"
68
68
  }
69
- }
69
+ }