<commit_before>import _ from "lodash"
import { isCI } from "gatsby-core-utils"
import { IFlag } from "./flags"
import chalk from "chalk"
import { commaListsAnd } from "common-tags"
import { distance } from "fastest-levenshtein"

const handleFlags = (
  flags: Array<IFlag>,
  configFlags: Record<string, boolean> = {},
  executingCommand = process.env.gatsby_executing_command
): {
  enabledConfigFlags: Array<IFlag>
  unknownFlagMessage: string
  message: string
} => {
  // Prepare config flags.
  // Filter out any flags that are set to false.
  const availableFlags = new Map<string, IFlag>()
  flags.forEach(flag => {
    availableFlags.set(flag.name, flag)
  })

  // Find unknown flags someone has in their config to warn them about.
  const unknownConfigFlags: Array<{ flag: string; didYouMean: string }> = []
  for (const flagName in configFlags) {
    if (availableFlags.has(flagName)) {
      continue
    }
    let flagWithMinDistance
    let minDistance
    for (const availableFlag of flags) {
      if (availableFlag.name !== flagName) {
        const distanceToFlag = distance(flagName, availableFlag.name)
        if (!flagWithMinDistance || distanceToFlag < minDistance) {
          flagWithMinDistance = availableFlag.name
          minDistance = distanceToFlag
        }
      }
    }

    if (flagName) {
      unknownConfigFlags.push({
        flag: flagName,
        didYouMean:
          flagWithMinDistance && minDistance < 4 ? flagWithMinDistance : ``,
      })
    }
  }

  let unknownFlagMessage = ``
  if (unknownConfigFlags.length > 0) {
    unknownFlagMessage = commaListsAnd`The following flag(s) found in your gatsby-config.js are not known:`
    unknownConfigFlags.forEach(
      flag =>
        (unknownFlagMessage += `\n- ${flag.flag}${
          flag.didYouMean ? ` (did you mean: ${flag.didYouMean})` : ``
        }`)
    )
  }

  let enabledConfigFlags: Array<IFlag> = Object.keys(configFlags)
    .filter(name => configFlags[name] && availableFlags.has(name))
    .map(flagName => availableFlags.get(flagName)!)

  // Test flags to see if it wants opted in.
  const optedInFlags = new Map<string, IFlag>()
  const applicableFlags = new Map<string, IFlag>()
  const lockedInFlags = new Map<string, IFlag>()
  const lockedInFlagsThatAreInConfig = new Map<string, IFlag>()
  availableFlags.forEach(flag => {
    if (flag.command !== `all` && flag.command !== executingCommand) {
      // if flag is not for all commands and current command doesn't match command flag is for - skip
      return
    }

    if (flag.noCI && isCI()) {
      // If we're in CI and flag is not available for CI - skip
      return
    }

    const fitness = flag.testFitness(flag)

    const flagIsSetInConfig = typeof configFlags[flag.name] !== `undefined`

    if (fitness === `LOCKED_IN`) {
      enabledConfigFlags.push(flag)
      lockedInFlags.set(flag.name, flag)
      if (flagIsSetInConfig) {
        lockedInFlagsThatAreInConfig.set(flag.name, flag)
      }
    } else if (!flagIsSetInConfig && fitness === `OPT_IN`) {
      // if user didn't explicitly set a flag (either true or false)
      // and it qualifies for auto opt-in - add it to optedInFlags
      enabledConfigFlags.push(flag)
      optedInFlags.set(flag.name, flag)
    }

    if (fitness === true || fitness === `OPT_IN`) {
      applicableFlags.set(flag.name, flag)
    }
  })

  // Filter enabledConfigFlags against various tests
  enabledConfigFlags = enabledConfigFlags.filter(flag => {
    if (flag.command !== `all` && flag.command !== executingCommand) {
      // if flag is not for all commands and current command doesn't match command flag is for - skip
      return false
    }

    if (flag.noCI && isCI()) {
      // If we're in CI and flag is not available for CI - skip
      return false
    }

    // finally check if flag passes fitness check
    return flag.testFitness(flag)
  })

  const addIncluded = (flag): void => {
    if (flag.includedFlags) {
      flag.includedFlags.forEach(includedName => {
        const incExp = flags.find(e => e.name == includedName)
        if (incExp) {
          const flagIsDisabledByUser =
            typeof configFlags[includedName] !== `undefined` &&
            !configFlags[includedName]

          if (!flagIsDisabledByUser) {
            enabledConfigFlags.push(incExp)
            addIncluded(incExp)
          }
        }
      })
    }
  }
  // Add to enabledConfigFlags any includedFlags
  enabledConfigFlags.forEach(flag => {
    addIncluded(flag)
  })

  enabledConfigFlags = _.uniq(enabledConfigFlags)

  // TODO remove flags that longer exist.
  //  w/ message of thanks

  const generateFlagLine = (flag): string => {
    let message = ``
    message += `\n- ${flag.name}`
    if (flag.experimental) {
      message += ` · ${chalk.white.bgRed.bold(`EXPERIMENTAL`)}`
    }
    if (flag.umbrellaIssue) {
      message += ` · (Umbrella Issue (${flag.umbrellaIssue}))`
    }
    message += ` · ${flag.description}`

    return message
  }

  let message = ``
  //  Create message about what flags are active.<commit_msg>feat(gatsby): change bgcolor of 'EXPERIMENTAL' label so it does look like an error (#31352)<commit_after>import _ from "lodash"
import { isCI } from "gatsby-core-utils"
import { IFlag } from "./flags"
import chalk from "chalk"
import { commaListsAnd } from "common-tags"
import { distance } from "fastest-levenshtein"

const handleFlags = (
  flags: Array<IFlag>,
  configFlags: Record<string, boolean> = {},
  executingCommand = process.env.gatsby_executing_command
): {
  enabledConfigFlags: Array<IFlag>
  unknownFlagMessage: string
  message: string
} => {
  // Prepare config flags.
  // Filter out any flags that are set to false.
  const availableFlags = new Map<string, IFlag>()
  flags.forEach(flag => {
    availableFlags.set(flag.name, flag)
  })

  // Find unknown flags someone has in their config to warn them about.
  const unknownConfigFlags: Array<{ flag: string; didYouMean: string }> = []
  for (const flagName in configFlags) {
    if (availableFlags.has(flagName)) {
      continue
    }
    let flagWithMinDistance
    let minDistance
    for (const availableFlag of flags) {
      if (availableFlag.name !== flagName) {
        const distanceToFlag = distance(flagName, availableFlag.name)
        if (!flagWithMinDistance || distanceToFlag < minDistance) {
          flagWithMinDistance = availableFlag.name
          minDistance = distanceToFlag
        }
      }
    }

    if (flagName) {
      unknownConfigFlags.push({
        flag: flagName,
        didYouMean:
          flagWithMinDistance && minDistance < 4 ? flagWithMinDistance : ``,
      })
    }
  }

  let unknownFlagMessage = ``
  if (unknownConfigFlags.length > 0) {
    unknownFlagMessage = commaListsAnd`The following flag(s) found in your gatsby-config.js are not known:`
    unknownConfigFlags.forEach(
      flag =>
        (unknownFlagMessage += `\n- ${flag.flag}${
          flag.didYouMean ? ` (did you mean: ${flag.didYouMean})` : ``
        }`)
    )
  }

  let enabledConfigFlags: Array<IFlag> = Object.keys(configFlags)
    .filter(name => configFlags[name] && availableFlags.has(name))
    .map(flagName => availableFlags.get(flagName)!)

  // Test flags to see if it wants opted in.
  const optedInFlags = new Map<string, IFlag>()
  const applicableFlags = new Map<string, IFlag>()
  const lockedInFlags = new Map<string, IFlag>()
  const lockedInFlagsThatAreInConfig = new Map<string, IFlag>()
  availableFlags.forEach(flag => {
    if (flag.command !== `all` && flag.command !== executingCommand) {
      // if flag is not for all commands and current command doesn't match command flag is for - skip
      return
    }

    if (flag.noCI && isCI()) {
      // If we're in CI and flag is not available for CI - skip
      return
    }

    const fitness = flag.testFitness(flag)

    const flagIsSetInConfig = typeof configFlags[flag.name] !== `undefined`

    if (fitness === `LOCKED_IN`) {
      enabledConfigFlags.push(flag)
      lockedInFlags.set(flag.name, flag)
      if (flagIsSetInConfig) {
        lockedInFlagsThatAreInConfig.set(flag.name, flag)
      }
    } else if (!flagIsSetInConfig && fitness === `OPT_IN`) {
      // if user didn't explicitly set a flag (either true or false)
      // and it qualifies for auto opt-in - add it to optedInFlags
      enabledConfigFlags.push(flag)
      optedInFlags.set(flag.name, flag)
    }

    if (fitness === true || fitness === `OPT_IN`) {
      applicableFlags.set(flag.name, flag)
    }
  })

  // Filter enabledConfigFlags against various tests
  enabledConfigFlags = enabledConfigFlags.filter(flag => {
    if (flag.command !== `all` && flag.command !== executingCommand) {
      // if flag is not for all commands and current command doesn't match command flag is for - skip
      return false
    }

    if (flag.noCI && isCI()) {
      // If we're in CI and flag is not available for CI - skip
      return false
    }

    // finally check if flag passes fitness check
    return flag.testFitness(flag)
  })

  const addIncluded = (flag): void => {
    if (flag.includedFlags) {
      flag.includedFlags.forEach(includedName => {
        const incExp = flags.find(e => e.name == includedName)
        if (incExp) {
          const flagIsDisabledByUser =
            typeof configFlags[includedName] !== `undefined` &&
            !configFlags[includedName]

          if (!flagIsDisabledByUser) {
            enabledConfigFlags.push(incExp)
            addIncluded(incExp)
          }
        }
      })
    }
  }
  // Add to enabledConfigFlags any includedFlags
  enabledConfigFlags.forEach(flag => {
    addIncluded(flag)
  })

  enabledConfigFlags = _.uniq(enabledConfigFlags)

  // TODO remove flags that longer exist.
  //  w/ message of thanks

  const generateFlagLine = (flag): string => {
    let message = ``
    message += `\n- ${flag.name}`
    if (flag.experimental) {
      message += ` · ${chalk.black.bgYellow.bold(`EXPERIMENTAL`)}`
    }
    if (flag.umbrellaIssue) {
      message += ` · (Umbrella Issue (${flag.umbrellaIssue}))`
    }
    message += ` · ${flag.description}`

    return message
  }

  let message = ``
  //  Create message about what flags are active.
{'fraction_non_alphanumeric': 0.11563629260669987, 'fraction_numerical': 0.0008789920890711983, 'mean_word_length': 2.798219584569733, 'pattern_counts': {'":': 0, '<': 27, '<?xml version=': 0, '>': 49, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6707518', 'n_tokens_mistral': 3119, 'n_tokens_neox': 3004, 'n_words': 836}