UNPKG

llm-md

Version:

Convert JSON to Markdown optimized for LLM consumption

198 lines (197 loc) 5.61 kB
"use strict"; /** * Utility functions for JSON to Markdown conversion */ Object.defineProperty(exports, "__esModule", { value: true }); exports.getMaxDepth = getMaxDepth; exports.escapePipes = escapePipes; exports.escapeMarkdown = escapeMarkdown; exports.formatValue = formatValue; exports.formatCellValue = formatCellValue; exports.estimateTokens = estimateTokens; exports.calculateKeySimilarity = calculateKeySimilarity; exports.getAverageKeyCount = getAverageKeyCount; exports.getAllKeys = getAllKeys; /** * Calculate the maximum depth of a data structure * @param data The data to analyze * @param current Current depth level * @param maxDepth Maximum depth to prevent infinite recursion * @param visited Set to track circular references * @returns Maximum depth found */ function getMaxDepth(data, current = 0, maxDepth = 10, visited = new WeakSet()) { // Prevent infinite recursion if (current >= maxDepth) { return maxDepth; } // Primitive values have no additional depth if (data === null || typeof data !== 'object') { return current; } // Check for circular references if (visited.has(data)) { return current; } visited.add(data); // Arrays if (Array.isArray(data)) { if (data.length === 0) { return current; } return Math.max(current, ...data.map((item) => getMaxDepth(item, current + 1, maxDepth, visited))); } // Objects const values = Object.values(data); if (values.length === 0) { return current; } return Math.max(current, ...values.map((val) => getMaxDepth(val, current + 1, maxDepth, visited))); } /** * Escape pipe characters in strings for Markdown tables * @param str String to escape * @returns Escaped string */ function escapePipes(str) { return str.replace(/\|/g, '\\|'); } /** * Escape special Markdown characters * @param str String to escape * @returns Escaped string */ function escapeMarkdown(str) { return str .replace(/\\/g, '\\\\') .replace(/\*/g, '\\*') .replace(/_/g, '\\_') .replace(/\[/g, '\\[') .replace(/\]/g, '\\]') .replace(/`/g, '\\`'); } /** * Format a value for display in Markdown * @param value Value to format * @returns Formatted string */ function formatValue(value) { if (value === null) { return '`null`'; } if (value === undefined) { return '`undefined`'; } if (typeof value === 'boolean') { return value.toString(); } if (typeof value === 'number') { return String(value); } if (typeof value === 'string') { return value; } if (typeof value === 'object') { return '`' + JSON.stringify(value) + '`'; } return String(value); } /** * Format a value for table cells * @param value Value to format * @returns Formatted string safe for table cells */ function formatCellValue(value) { if (value === null) { return '`null`'; } if (value === undefined) { return ''; } if (typeof value === 'boolean') { return value ? '✓' : '✗'; } if (typeof value === 'number') { return String(value); } if (typeof value === 'string') { // Escape pipes and remove newlines return escapePipes(value.replace(/\n/g, ' ')); } if (typeof value === 'object') { return '`' + JSON.stringify(value) + '`'; } return String(value); } /** * Estimate token count for a string (rough approximation) * Uses a simple heuristic: ~4 characters per token * @param str String to estimate * @returns Estimated token count */ function estimateTokens(str) { return Math.ceil(str.length / 4); } /** * Check if all objects in an array have similar keys * @param arr Array of objects to check * @returns Similarity score (0-1) */ function calculateKeySimilarity(arr) { if (!Array.isArray(arr) || arr.length === 0) { return 0; } // Filter to only objects const objects = arr.filter((item) => item !== null && typeof item === 'object' && !Array.isArray(item)); if (objects.length === 0) { return 0; } // Get key sets for each object const keySets = objects.map((obj) => Object.keys(obj) .sort() .join(',')); // Calculate uniqueness const uniqueKeySets = new Set(keySets); return 1 / uniqueKeySets.size; } /** * Get average number of keys in array of objects * @param arr Array to analyze * @returns Average key count */ function getAverageKeyCount(arr) { if (!Array.isArray(arr) || arr.length === 0) { return 0; } const objects = arr.filter((item) => item !== null && typeof item === 'object' && !Array.isArray(item)); if (objects.length === 0) { return 0; } const totalKeys = objects.reduce((sum, obj) => { return sum + Object.keys(obj).length; }, 0); return totalKeys / objects.length; } /** * Get all unique keys from an array of objects * @param arr Array of objects * @returns Array of unique keys in order of first appearance */ function getAllKeys(arr) { if (!Array.isArray(arr)) { return []; } const keySet = new Set(); const keyOrder = []; arr.forEach((item) => { if (item !== null && typeof item === 'object' && !Array.isArray(item)) { Object.keys(item).forEach((key) => { if (!keySet.has(key)) { keySet.add(key); keyOrder.push(key); } }); } }); return keyOrder; }