146 lines
4.5 KiB
JavaScript
146 lines
4.5 KiB
JavaScript
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 }
|