UNPKG

@sanity/import

Version:

Import documents to a Sanity dataset

100 lines (99 loc) 3.82 kB
const REPLACEMENT_CHAR = '\uFFFD'; export class ReplacementCharError extends Error { constructor(message){ super(message); this.name = 'ReplacementCharError'; } } /** * Check if a string contains a Unicode replacement character (U+FFFD). * Returns the index of the first occurrence, or null if not found. */ export function checkStringForReplacementChar(str) { const index = str.indexOf(REPLACEMENT_CHAR); return index === -1 ? null : index; } /** * Recursively search an object for strings containing U+FFFD. * Returns the path to the first occurrence, or null if not found. */ export function findReplacementCharInObject(obj, currentPath = '') { if (obj === null || obj === undefined) { return null; } if (typeof obj === 'string') { const index = checkStringForReplacementChar(obj); if (index === null) { return null; } return currentPath; } if (Array.isArray(obj)) { for (const [i, element] of obj.entries()){ const result = findReplacementCharInObject(element, `${currentPath}[${i}]`); if (result !== null) { return result; } } return null; } if (typeof obj === 'object') { for (const key of Object.keys(obj)){ // Check the key itself for replacement characters if (checkStringForReplacementChar(key) !== null) { const keyPath = currentPath ? `${currentPath}["${key}"]` : `["${key}"]`; return keyPath; } // Build the path for this key const needsBracketNotation = !/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(key); let keyPath; if (!currentPath) { keyPath = key; } else if (needsBracketNotation) { keyPath = `${currentPath}["${key}"]`; } else { keyPath = `${currentPath}.${key}`; } const result = findReplacementCharInObject(obj[key], keyPath); if (result !== null) { return result; } } } return null; } /** * Validate that a raw NDJSON line doesn't contain U+FFFD. * Returns an error message if found, or null if clean. */ export function validateLineForReplacementChar(line, lineNumber) { const index = checkStringForReplacementChar(line); if (index !== null) { return `Unicode replacement character (U+FFFD) found on line ${lineNumber}. This usually indicates encoding issues in the source data.`; } return null; } /** * Validate that an assetMap doesn't contain U+FFFD in any string values. * Throws an error if found. */ export function validateAssetMapForReplacementChars(assetMap) { // Check keys first for (const key of Object.keys(assetMap)){ if (checkStringForReplacementChar(key) !== null) { throw new ReplacementCharError(`Unicode replacement character (U+FFFD) found at assetMap["${key}"] (in key). This usually indicates encoding issues in the source data.`); } } // Check values for (const [key, value] of Object.entries(assetMap)){ const path = findReplacementCharInObject(value, ''); if (path !== null) { let fullPath; if (!path) { fullPath = `assetMap["${key}"]`; } else if (path.startsWith('[')) { fullPath = `assetMap["${key}"]${path}`; } else { fullPath = `assetMap["${key}"].${path}`; } throw new ReplacementCharError(`Unicode replacement character (U+FFFD) found at ${fullPath}. This usually indicates encoding issues in the source data.`); } } } //# sourceMappingURL=validateReplacementCharacters.js.map