UNPKG

nice-ui

Version:

React design system, components, and utilities

200 lines (199 loc) 6.58 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.parseExtended = exports.parse = void 0; const letterToNumber = { a: 0, b: 1, c: 2, d: 3, e: 4, f: 5, g: 6, h: 7, }; const pieceName2Letter = { k: 'bk', q: 'bq', b: 'bb', n: 'bn', r: 'br', p: 'bp', K: 'wk', Q: 'wq', B: 'wb', N: 'wn', R: 'wr', P: 'wp', }; const twoLetterToCased = { bk: 'k', bq: 'q', bb: 'b', bn: 'n', br: 'r', bp: 'p', wk: 'K', wq: 'Q', wb: 'B', wn: 'N', wr: 'R', wp: 'P', }; const validFen = (fen) => { if (typeof fen !== 'string') return false; // cut off any move, castling, etc info from the end // we're only interested in position information fen = fen.replace(/ .+$/, ''); // FEN should be 8 sections separated by slashes const chunks = fen.split('/'); if (chunks.length > 8) return false; // check the piece sections for (let i = 0; i < 8 && i < chunks.length; i++) { if (chunks[i].length > 8 || chunks[i].search(/[^kqrbnpKQRNBP1-8]/) !== -1) { return false; } } return true; }; const parse = (fen) => { if (!validFen(fen)) return []; // cut off any move, castling, etc info from the end // we're only interested in position information fen = fen.replace(/ .+$/, ''); const rows = fen.split('/'); const pieces = []; for (let i = 0; i < 8 && i < rows.length; i++) { const row = rows[i].split(''); let colIndex = 0; // loop through each character in the FEN section for (let j = 0; j < row.length; j++) { if (row[j].search(/[1-8]/) !== -1) { const emptySquares = parseInt(row[j], 10); colIndex += emptySquares; } else { let piece = row[j]; if (piece.toLowerCase() === piece) piece = 'b' + piece.toLowerCase(); else piece = 'w' + piece.toLowerCase(); pieces.push([i, colIndex, piece]); colIndex++; } } } return pieces; }; exports.parse = parse; const parseExtended = (fen, noFen = false) => { const layout = { borders: [], lines: [], squares: [], }; const parts = fen.split(/\n|;/g); if (!noFen) { const pieces = (0, exports.parse)(parts[0]); if (pieces) { for (const [x, y, piece] of pieces) { layout.squares.push({ xy: [y, (7 - x)], piece: twoLetterToCased[piece], }); } } } for (let i = 0; i < parts.length; i++) { const part = parts[i]; // Lines like: `e1->e4` let match = part.match(/^\s*([a-hA-H])([0-8])\s*(<{0,50}|[oO]{0,1})\s*([\-=]{0,50})\s*(>{0,50}|[oO]{0,1})\s*([a-hA-H])([0-8])\s*:?\s*([a-zA-Z#0-9]+)?\s*,?\s*([0-9\.]+)?\s*/); if (match) { const line = { from: [letterToNumber[match[1].toLowerCase()], (Number(match[2]) - 1)], tipFrom: match[3], body: match[4], tipTo: match[5], to: [letterToNumber[match[6].toLowerCase()], (Number(match[7]) - 1)], }; if (match[8]) line.color = match[8]; if (match[9]) line.opacity = Number(match[9]); layout.lines.push(line); continue; } // Squares like: `e4:red` match = part.match(/^\s*([a-hA-H])([0-8])\s*(:(\s*([prnbkqPRNBKQ](\s|\n|$))\s*(\s*([0-9\.]+)\s*)?\s*)?\s*([\\\/\-_]{0,4})?\s*(\s*([a-zA-Z#0-9]+)?(\s*\s*([0-9\.]+)?)?)?\s*)?/); if (match) { const square = { xy: [ (Number(match[2]) - 1), (7 - letterToNumber[match[1].toLowerCase()]), ], }; if (match[5]) square.piece = pieceName2Letter[match[5].trim()]; if (match[8]) square.pieceOpacity = Number(match[8]); // Borders if (match[9]) { if (match[9].indexOf('-') > -1) square.borderTop = true; if (match[9].indexOf('\\') > -1) square.borderRight = true; if (match[9].indexOf('_') > -1) square.borderBottom = true; if (match[9].indexOf('/') > -1) square.borderLeft = true; } if (match[11]) square.color = match[11]; if (match[13]) square.opacity = Number(match[13]); const existingSquare = layout.squares.find((a) => a.xy[0] === square.xy[0] && a.xy[1] === square.xy[1]); if (existingSquare) { Object.assign(existingSquare, square); } else { layout.squares.push(square); } continue; } // Borders like: `~a1 1 2 3 ddwwaasssd: red .7 red .2` match = part.match(/^\s*~\s*([a-hA-H])([0-8])(\s+([\-0-9\.]+))?(\s+([\-0-9\.]+))?(\s+([0-9\.]+))?(\s+([asdw]+))\s*(:\s*([a-zA-Z#0-9]+)?(\s+([0-9\.]+))?(\s+([0-9\.]+))?)?(\s+([a-zA-Z#0-9]+))?(\s+([0-9\.]+))?\s*/); if (match) { const border = { xy: [letterToNumber[match[1].toLowerCase()], (Number(match[2]) - 1)], segments: match[10], }; if (match[4]) border.offset = [Number(match[4]), Number(match[6] || 0)]; if (match[8]) border.segmentSize = Number(match[8]); if (match[12]) border.color = match[12]; if (match[14]) border.opacity = Number(match[14]); if (match[16]) border.width = Number(match[16]); if (match[18]) border.fillColor = match[18]; if (match[20]) border.fillOpacity = Number(match[20]); layout.borders.push(border); continue; } // Size like: `size: xl` // match = part.match(/^\s*size\s*:\s*(xxs|xs|s|m|l|xl|xxl)(\s|\n|$)\s*/i); // if(match) { // layout.size = match[1]; // } } if (!layout.borders.length && !layout.lines.length && !layout.squares.length) return {}; return layout; }; exports.parseExtended = parseExtended;