UNPKG

llm-md

Version:

Convert JSON to Markdown optimized for LLM consumption

157 lines (156 loc) 5.31 kB
"use strict"; /** * Analyzer for detecting optimal conversion strategy based on JSON structure */ Object.defineProperty(exports, "__esModule", { value: true }); exports.Analyzer = void 0; exports.analyze = analyze; const utils_1 = require("./utils"); class Analyzer { /** * Analyze JSON data and determine the best conversion strategy * @param data Data to analyze * @param options Conversion options * @returns Analysis result with recommended strategy */ analyze(data, options) { // Handle primitives and null/undefined if (data === null || data === undefined) { return { strategy: 'key-value', depth: 0, uniformity: 1, }; } if (typeof data !== 'object') { return { strategy: 'key-value', depth: 0, uniformity: 1, }; } // Check if array if (Array.isArray(data)) { return this.analyzeArray(data, options); } // Must be object return this.analyzeObject(data, options); } /** * Analyze an array to determine conversion strategy * @param arr Array to analyze * @param options Conversion options * @returns Analysis result */ analyzeArray(arr, options) { const maxDepth = options?.maxDepth ?? 10; const tableSimilarityThreshold = options?.tableSimilarityThreshold ?? 0.8; const maxTableColumns = options?.maxTableColumns ?? 15; // Empty array if (arr.length === 0) { return { strategy: 'numbered-list', depth: 0, uniformity: 1, }; } // Check if all items are objects (not arrays) const allObjects = arr.every((item) => item !== null && typeof item === 'object' && !Array.isArray(item)); if (!allObjects) { // Mixed types or arrays - use numbered list return { strategy: 'numbered-list', depth: (0, utils_1.getMaxDepth)(arr, 0, maxDepth), uniformity: 0, }; } // Calculate key similarity const keySimilarity = (0, utils_1.calculateKeySimilarity)(arr); const avgKeys = (0, utils_1.getAverageKeyCount)(arr); // Check if suitable for table if (keySimilarity >= tableSimilarityThreshold && arr.length >= 2 && avgKeys <= maxTableColumns) { return { strategy: 'table', depth: (0, utils_1.getMaxDepth)(arr, 0, maxDepth), uniformity: keySimilarity, arrayInfo: { length: arr.length, keySimilarity, averageKeys: avgKeys, }, }; } // Not uniform enough for table - use numbered list return { strategy: 'numbered-list', depth: (0, utils_1.getMaxDepth)(arr, 0, maxDepth), uniformity: keySimilarity, arrayInfo: { length: arr.length, keySimilarity, averageKeys: avgKeys, }, }; } /** * Analyze an object to determine conversion strategy * Hybrid strategy uses headers + code blocks + YAML for medium-depth objects * @param obj Object to analyze * @param options Conversion options * @returns Analysis result */ analyzeObject(obj, options) { const maxDepthLimit = options?.maxDepth ?? 10; const yamlThreshold = options?.yamlThreshold ?? 15; // Increased to 15 for better hybrid mode usage const depth = (0, utils_1.getMaxDepth)(obj, 0, maxDepthLimit); const keyCount = Object.keys(obj).length; // Simple, shallow object with few keys → Key-value list if (depth <= 1 && keyCount <= 10) { return { strategy: 'key-value', depth, uniformity: 1, }; } // Very deep nesting (>15) → Pure YAML block // Only use pure YAML for extremely complex structures if (depth > yamlThreshold) { return { strategy: 'yaml-block', depth, uniformity: 0.5, }; } // Medium to deep (2-15) or complex structure → Hybrid strategy // HybridConverter uses headers + code blocks + YAML for deeply nested sub-objects // This provides better navigation with headers at top level if (depth >= 2 || keyCount > 10) { return { strategy: 'hybrid', depth, uniformity: 0.7, }; } // Default to key-value for very simple objects return { strategy: 'key-value', depth, uniformity: 1, }; } } exports.Analyzer = Analyzer; /** * Convenience function to analyze data * @param data Data to analyze * @param options Conversion options * @returns Analysis result */ function analyze(data, options) { const analyzer = new Analyzer(); return analyzer.analyze(data, options); }