chessops
    Preparing search index...

    Module pgn

    Parse, transform and write PGN.

    The parser will interpret any input as a PGN, creating a tree of syntactically valid (but not necessarily legal) moves, skipping any invalid tokens.

    import { parsePgn, startingPosition } from 'chessops/pgn';
    import { parseSan } from 'chessops/san';

    const pgn = '1. d4 d5 *';
    const games = parsePgn(pgn);
    for (const game of games) {
    const pos = startingPosition(game.headers).unwrap();
    for (const node of game.moves.mainline()) {
    const move = parseSan(pos, node.san);
    if (!move) break; // Illegal move
    pos.play(move);
    }
    }

    The module also provides a denial-of-service resistant streaming parser. It can be configured with a budget for reasonable complexity of a single game, fed with chunks of text, and will yield parsed games as they are completed.


    import { createReadStream } from 'fs';
    import { PgnParser } from 'chessops/pgn';

    const stream = createReadStream('games.pgn', { encoding: 'utf-8' });

    const parser = new PgnParser((game, err) => {
    if (err) {
    // Budget exceeded.
    stream.destroy(err);
    }

    // Use game ...
    });

    await new Promise<void>(resolve =>
    stream
    .on('data', (chunk: string) => parser.parse(chunk, { stream: true }))
    .on('close', () => {
    parser.parse('');
    resolve();
    })
    );

    You can use walk to visit all nodes in the game tree, or transform to augment it with user data.

    Both allow you to provide context. You update the context inside the callback, and it is automatically clone()-ed at each fork. In the example below, the current position pos is provided as context.

    import { transform } from 'chessops/pgn';
    import { makeFen } from 'chessops/fen';
    import { parseSan, makeSanAndPlay } from 'chessops/san';

    const pos = startingPosition(game.headers).unwrap();
    game.moves = transform(game.moves, pos, (pos, node) => {
    const move = parseSan(pos, node.san);
    if (!move) {
    // Illegal move. Returning undefined cuts off the tree here.
    return;
    }

    const san = makeSanAndPlay(pos, move); // Mutating pos!

    return {
    ...node, // Keep comments and annotation glyphs
    san, // Normalized SAN
    fen: makeFen(pos.toSetup()), // Add arbitrary user data to node
    };
    });

    Requires each node to at least have a san property.

    import { makePgn } from 'chessops/pgn';

    const rewrittenPgn = makePgn(game);

    Classes

    Box
    ChildNode
    Node
    PgnError
    PgnParser

    Interfaces

    Comment
    CommentShape
    Game
    ParseOptions
    PgnNodeData

    Type Aliases

    CommentShapeColor
    Evaluation
    EvaluationMate
    EvaluationPawns

    Functions

    defaultGame
    defaultHeaders
    emptyHeaders
    extend
    isChildNode
    isMate
    isPawns
    makeComment
    makeOutcome
    makePgn
    makeVariant
    parseComment
    parseOutcome
    parsePgn
    parseVariant
    setStartingPosition
    startingPosition
    transform
    walk