import { isGroupWithOverridesOption } from './is-group-with-overrides-option.js' import { isNewlinesBetweenOption } from './is-newlines-between-option.js' import { computeGroupName } from './compute-group-name.js' /** * Get the `newlinesBetween` option to use between two consecutive nodes. The * result is based on the global `newlinesBetween` option and the custom groups, * which can override the global option. * * - If the two nodes are in the same custom group, the `newlinesInside` option of * the group is used. * * @param props - The function arguments. * @param props.nextNodeGroupIndex - The next node index to sort. * @param props.nodeGroupIndex - The current node index to sort. * @param props.options - Newlines between related options. * @returns - The `newlinesBetween` option to use. */ function getNewlinesBetweenOption({ nextNodeGroupIndex, nodeGroupIndex, options, }) { if (nodeGroupIndex === nextNodeGroupIndex) { return computeNewlinesInsideOption({ groupIndex: nodeGroupIndex, options, }) } if (nextNodeGroupIndex >= nodeGroupIndex + 2) { return computeNewlinesBetweenOptionForDifferentGroups({ nextNodeGroupIndex, nodeGroupIndex, options, }) } return options.newlinesBetween } function computeNewlinesBetweenOptionForDifferentGroups({ nextNodeGroupIndex, nodeGroupIndex, options, }) { if (nextNodeGroupIndex === nodeGroupIndex + 2) { let groupBetween = options.groups[nodeGroupIndex + 1] if (isNewlinesBetweenOption(groupBetween)) { return groupBetween.newlinesBetween } return options.newlinesBetween } let groupsWithAllNewlinesBetween = buildGroupsWithAllNewlinesBetween( options.groups.slice(nodeGroupIndex, nextNodeGroupIndex + 1), options.newlinesBetween, ) let newlinesBetweenOptions = new Set( groupsWithAllNewlinesBetween .filter(isNewlinesBetweenOption) .map(group => group.newlinesBetween), ) let numberNewlinesBetween = [...newlinesBetweenOptions].filter( option => typeof option === 'number', ) let maxNewlinesBetween = numberNewlinesBetween.length > 0 ? Math.max(...numberNewlinesBetween) : null if (maxNewlinesBetween !== null && maxNewlinesBetween >= 1) { return maxNewlinesBetween } if (newlinesBetweenOptions.has('ignore')) { return 'ignore' } return 0 } function computeNewlinesInsideOption({ groupIndex, options }) { let globalNewlinesInsideOption = computeGlobalNewlinesInsideOption() let group = options.groups[groupIndex] if (!group) { return globalNewlinesInsideOption } let groupName = computeGroupName(group) let nodeCustomGroup = options.customGroups.find( customGroup => customGroup.groupName === groupName, ) let groupOverrideNewlinesInside = isGroupWithOverridesOption(group) ? group.newlinesInside : null return ( nodeCustomGroup?.newlinesInside ?? groupOverrideNewlinesInside ?? globalNewlinesInsideOption ) function computeGlobalNewlinesInsideOption() { switch (options.newlinesInside) { case 'newlinesBetween': return options.newlinesBetween === 'ignore' ? 'ignore' : 0 case 'ignore': return 'ignore' default: return options.newlinesInside } } } /** * Inserts newlines settings between groups that don't already have them. * * Fills in missing newlines settings between adjacent groups using the global * newlines option. This ensures every transition between groups has an explicit * newlines setting for consistent calculation. * * @example * * ```ts * buildGroupsWithAllNewlinesBetween( * ['imports', 'types', { newlinesBetween: 2 }, 'functions'], * 1, * ) * // Returns: [ * // 'imports', * // { newlinesBetween: 1 }, // Added * // 'types', * // { newlinesBetween: 2 }, // Already existed * // 'functions' * // ] * ``` * * @param groups - Array of groups with optional inline newlines settings. * @param globalNewlinesBetweenOption - Default newlines to use for missing * settings. * @returns Groups array with newlines settings filled in between all groups. */ function buildGroupsWithAllNewlinesBetween( groups, globalNewlinesBetweenOption, ) { let returnValue = [] for (let i = 0; i < groups.length; i++) { let group = groups[i] if (!isNewlinesBetweenOption(group)) { let previousGroup = groups[i - 1] if (previousGroup && !isNewlinesBetweenOption(previousGroup)) { returnValue.push({ newlinesBetween: globalNewlinesBetweenOption }) } } returnValue.push(group) } return returnValue } export { getNewlinesBetweenOption }