UNPKG

read-gedcom

Version:
141 lines 6.1 kB
import { tokenize } from './tokenizer'; import { buildTree } from './structurer'; import { decodeUtfBOM } from './decoding'; /** * Supported Gedcom file encoding schemes. */ export var FileEncoding; (function (FileEncoding) { FileEncoding["Utf8"] = "UTF-8"; FileEncoding["Ansel"] = "ANSEL"; FileEncoding["Cp1252"] = "Cp1252"; FileEncoding["Macintosh"] = "Macintosh"; FileEncoding["Cp850"] = "Cp850"; FileEncoding["Utf16be"] = "UTF-16be"; FileEncoding["Utf16le"] = "UTF-16le"; })(FileEncoding || (FileEncoding = {})); /** * Extracts the file metadata (see {@link FileMetadata}). The metadata can then be used to guess the actual charset of the file. * To circumvent the bootstrapping problem this function restricts its reading to the first lines of the file only, and * decodes them as UTF-8. * @param buffer The content of the file * @param maxPeekBytes Maximum number of bytes to read * @param maxPeekLines Maximum number of lines to read */ export const getFileMetadata = (buffer, maxPeekBytes = 5000, maxPeekLines = 200) => { const { output: inputHead, bomCharset } = decodeUtfBOM(buffer.slice(0, maxPeekBytes)); // Start with UTF-8 since file can contain a BOM const hasBOM = bomCharset !== null; const it = tokenize(inputHead, false); // Non-strict mode: break silently on error let i = 0; const array = []; for (const line of it) { if (i >= maxPeekLines) { break; } array.push(line); i += 1; } const tree = buildTree(array); const header = tree.children.filter(c => c.tag === "HEAD" /* Tag.Header */); const char = header.flatMap(c => c.children.filter(n => n.tag === "CHAR" /* Tag.Character */ || n.tag === "CHARACTER" /* TagNonStandard.CharacterAlt */)); const charOpt = char.length > 0 ? char[0].value : null; const source = header.flatMap(c => c.children.filter(n => n.tag === "SOUR" /* Tag.Source */)); const sourceOpt = source.length > 0 ? source[0].value : null; const version = source.flatMap(c => c.children.filter(n => n.tag === "VERS" /* Tag.Version */)); const versionOpt = version.length > 0 ? version[0].value : null; return { sourceEncoding: charOpt, sourceProvider: sourceOpt, sourceProviderVersion: versionOpt, fileHasBOM: hasBOM }; }; /** * Detects the file charset using a set of heuristics. Has proven to work great in practice. * If you encounter a file for which this procedure doesn't work as intended please do open an issue * at: https://github.com/arbre-app/read-gedcom/issues. * @param buffer The content of the file */ export const detectCharset = (buffer) => { // eslint-disable-next-line const { sourceEncoding, sourceProvider, sourceProviderVersion, fileHasBOM } = getFileMetadata(buffer); // Estimate an encoding without knowing the provider function estimateEncoding() { if (sourceEncoding === "UTF-8" /* ValueCharacterEncoding.Utf8 */) { return "UTF-8" /* FileEncoding.Utf8 */; } else if (sourceEncoding === "ANSEL" /* ValueCharacterEncoding.Ansel */) { return "ANSEL" /* FileEncoding.Ansel */; } else if (sourceEncoding === "ASCII" /* ValueCharacterEncoding.Ascii */) { return "Cp1252" /* FileEncoding.Cp1252 */; } else if (sourceEncoding === "ANSI" /* ValueCharacterEncoding.Ansi */) { return "Cp1252" /* FileEncoding.Cp1252 */; } else if (sourceEncoding === "UNICODE" /* ValueCharacterEncoding.Unicode */) { return "UTF-16be" /* FileEncoding.Utf16be */; // RFC 2781 } else if (sourceEncoding === 'WINDOWS' || sourceEncoding === 'IBM WINDOWS') { return "Cp1252" /* FileEncoding.Cp1252 */; } else if (sourceEncoding === 'MACINTOSH') { return "Macintosh" /* FileEncoding.Macintosh */; } else if (sourceEncoding === 'IBMPC') { return "Cp850" /* FileEncoding.Cp850 */; } else if (sourceEncoding === 'MSDOS') { return "Cp850" /* FileEncoding.Cp850 */; } else if (sourceEncoding === 'UNIX') { return "Cp1252" /* FileEncoding.Cp1252 */; } else if (sourceEncoding === 'UTF8') { // Spelling mistake return "UTF-8" /* FileEncoding.Utf8 */; } else if (sourceEncoding === 'windows-1250') { // Our best guess (Rodokmen Pro) return "Cp1252" /* FileEncoding.Cp1252 */; } else { // Unknown encoding return "UTF-8" /* FileEncoding.Utf8 */; // Defaults to UTF-8 } } if (fileHasBOM) { // Short-circuit: must be one of UTF-{8,16,32} return "UTF-8" /* FileEncoding.Utf8 */; } if (sourceProvider === 'GeneWeb') { // Geneweb if (sourceEncoding === "ASCII" /* ValueCharacterEncoding.Ascii */) { return "Cp1252" /* FileEncoding.Cp1252 */; } else if (sourceEncoding === "UTF-8" /* ValueCharacterEncoding.Utf8 */) { return "UTF-8" /* FileEncoding.Utf8 */; } else { return estimateEncoding(); } } else if (sourceProvider != null && sourceProvider.startsWith('HEREDIS')) { // Heredis if (sourceEncoding === "ANSI" /* ValueCharacterEncoding.Ansi */) { return "Cp1252" /* FileEncoding.Cp1252 */; } else { return estimateEncoding(); } } else if (sourceProvider === 'GENEATIQUE') { // Généatique if (sourceEncoding === "ANSEL" /* ValueCharacterEncoding.Ansel */) { return "ANSEL" /* FileEncoding.Ansel */; } else { return estimateEncoding(); } } else if (sourceProvider === 'Gramps') { // Gramps if (sourceEncoding === "UTF-8" /* ValueCharacterEncoding.Utf8 */) { return "UTF-8" /* FileEncoding.Utf8 */; } else { return estimateEncoding(); } } else { // Unknown provider return estimateEncoding(); } }; //# sourceMappingURL=decoder.js.map