Skip to content

⬅️ Back to Table of Contents

📄 insertRuleOptions.ts

📊 Analysis Summary

Metric Count
🔧 Functions 3
📦 Imports 6
📊 Variables & Constants 6

📚 Table of Contents

🛠️ File Location:

📂 packages/website/plugins/generated-rule-docs/insertions/insertRuleOptions.ts

📦 Imports

Name Source
JSONSchema4 @typescript-eslint/utils/json-schema
Node unist
RuleDocsPage ../RuleDocsPage
nodeIsHeading ../../utils/nodes
nodeIsMdxFlowExpression ../../utils/nodes
findHeadingIndex ../../utils/rules

Variables & Constants

Name Type Kind Value Exported
knownSkippedRules Set<string> const `new Set([
'array-type',
'ban-ts-comment',
'member-ordering',
])`
emptyOptionDefaults Map<unknown, unknown> const `new Map([
['array', []],
['boolean', false],
])`
defaultOptions Record<string, unknown> const `(page.rule.defaultOptions[0] ?? {}) as Record<
string,
unknown
>`
defaultValue unknown const defaultOptions[optionName] ?? emptyOptionDefaults.get(option.type)
OPTION_COMMENT "/* insert option description */" const /* insert option description */
child Node const children[i]

Functions

insertRuleOptions(page: RuleDocsPage): void

Code
export function insertRuleOptions(page: RuleDocsPage): void {
  if (
    knownSkippedRules.has(page.file.stem) ||
    !Array.isArray(page.rule.meta.schema)
  ) {
    return;
  }

  const optionProperties = getOptionProperties(
    (page.rule.meta.schema as JSONSchema4[]).at(0),
  );

  if (!optionProperties) {
    return;
  }

  const defaultOptions = (page.rule.defaultOptions[0] ?? {}) as Record<
    string,
    unknown
  >;

  for (const [optionName, option] of Object.entries(optionProperties)) {
    if (!option.description) {
      if (!page.rule.meta.docs.extendsBaseRule) {
        throw new Error(`Missing description for option ${optionName}.`);
      }
      return;
    }

    const existingHeadingIndex = findHeadingIndex(
      page.children,
      3,
      node => node.type === 'inlineCode' && node.value === optionName,
    );
    if (existingHeadingIndex === -1) {
      if (!page.rule.meta.docs.extendsBaseRule) {
        throw new Error(`Couldn't find h3 for option ${optionName}.`);
      }
      continue;
    }

    const commentInsertionIndex = findCommentIndexForOption(
      page.children,
      existingHeadingIndex,
    );
    if (commentInsertionIndex === -1) {
      throw new Error(
        `[${page.file.stem}] Could not find ${OPTION_COMMENT} under option heading ${optionName}.`,
      );
    }

    const defaultValue =
      defaultOptions[optionName] ?? emptyOptionDefaults.get(option.type);

    page.spliceChildren(
      commentInsertionIndex,
      0,
      // eslint-disable-next-line @typescript-eslint/internal/eqeq-nullish -- I don't know whether this is safe to fix
      defaultValue !== undefined
        ? `${option.description} Default: \`${JSON.stringify(defaultValue)}\`.`
        : option.description,
    );
  }
}
  • Parameters:
  • page: RuleDocsPage
  • Return Type: void
  • Calls:
  • knownSkippedRules.has
  • Array.isArray
  • getOptionProperties
  • (page.rule.meta.schema as JSONSchema4[]).at
  • Object.entries
  • findHeadingIndex (from ../../utils/rules)
  • findCommentIndexForOption
  • emptyOptionDefaults.get
  • page.spliceChildren
  • JSON.stringify
  • Internal Comments:
    // eslint-disable-next-line @typescript-eslint/internal/eqeq-nullish -- I don't know whether this is safe to fix (x3)
    

findCommentIndexForOption(children: readonly Node[], headingIndex: number): number

Code
function findCommentIndexForOption(
  children: readonly Node[],
  headingIndex: number,
): number {
  for (let i = headingIndex + 1; i < children.length; i += 1) {
    const child = children[i];
    if (nodeIsMdxFlowExpression(child) && child.value === OPTION_COMMENT) {
      return i;
    }

    if (nodeIsHeading(child)) {
      break;
    }
  }

  return -1;
}
  • Parameters:
  • children: readonly Node[]
  • headingIndex: number
  • Return Type: number
  • Calls:
  • nodeIsMdxFlowExpression (from ../../utils/nodes)
  • nodeIsHeading (from ../../utils/nodes)

getOptionProperties(options: JSONSchema4 | undefined): Record<string, JSONSchema4> | undefined

Code
function getOptionProperties(
  options: JSONSchema4 | undefined,
): Record<string, JSONSchema4> | undefined {
  if (!options) {
    return undefined;
  }

  if (options.type === 'object') {
    return options.properties;
  }

  if (options.oneOf) {
    return options.oneOf.reduce<Record<string, JSONSchema4>>(
      (previous, next) => ({
        ...previous,
        ...getOptionProperties(next),
      }),
      {},
    );
  }

  return undefined;
}
  • Parameters:
  • options: JSONSchema4 | undefined
  • Return Type: Record<string, JSONSchema4> | undefined
  • Calls:
  • options.oneOf.reduce
  • getOptionProperties