Repository: tailwindlabs/tailwindcss
File: src/cli/build/plugin.js (JavaScript)

Code before:
    // - Includes `**`
    // - Does not include any of the known large directories (e.g.: node_modules)
    let maybeBroadPattern = this.contentPatterns.all.some(
      (path) => path.includes('**') && !LARGE_DIRECTORIES_REGEX.test(path)
    )

    // All globs that explicitly contain any of the known large directories (e.g.:
    // node_modules)
    let explicitGlobs = this.contentPatterns.all.filter((path) =>
      LARGE_DIRECTORIES_REGEX.test(path)
    )

    for (let file of files) {
      if (
        maybeBroadPattern &&
        // When a broad pattern is used, we have to double check that the file was
        // not explicitly included in the globs.
        !micromatch.isMatch(file, explicitGlobs)
      ) {
        let largeDirectory = LARGE_DIRECTORIES.find((directory) => file.includes(directory))
        if (largeDirectory) {
          log.warn('broad-content-glob-pattern', [
            `You are using a glob pattern that includes \`${largeDirectory}\` without explicitly specifying \`${largeDirectory}\` in the glob.`,
            'This can lead to performance issues and is not recommended.',
            'Please consider using a more specific pattern.',
            'https://tailwindcss.com/docs/content-configuration#pattern-recommendations',
          ])
        }
      }
      content.push({
        content: fs.readFileSync(path.resolve(file), 'utf8'),
        extension: path.extname(file).slice(1),
      })
    }

    // Resolve raw content in the tailwind config
    let rawContent = this.config.content.files.filter((file) => {
      return file !== null && typeof file === 'object'
    })

    for (let { raw: htmlContent, extension = 'html' } of rawContent) {
      content.push({ content: htmlContent, extension })
    }

    return content
  },

  getContext({ createContext, cliConfigPath, root, result, content }) {
    env.DEBUG && console.time('Searching for config')
    let configPath = findAtConfigPath(root, result) ?? cliConfigPath
    env.DEBUG && console.timeEnd('Searching for config')

Review comment (suggestion):
I think the warning could be a bit clearer by:

- Using terminology from our docs: _Your tailwind settings contain a `content` setting that..._ instead of glob pattern (might not be immediately clear what this means). 
- Giving more hints as to what needs to change. We could include the pattern we found to be faulty: _Your content settings contain a pattern that is too broad: `./**/*.js`. This matches files inside ${largeDirectory} which is ... xyz_

I can imagine this warning popping up for all people in teams that have had their setup for a long time, so it might pop up for people that don't immediately know how the project is set up.


Code after:
      return file !== null && typeof file === 'object'
    })

    for (let { raw: htmlContent, extension = 'html' } of rawContent) {
      content.push({ content: htmlContent, extension })
    }

    return content
  },

  getContext({ createContext, cliConfigPath, root, result, content }) {
    env.DEBUG && console.time('Searching for config')
    let configPath = findAtConfigPath(root, result) ?? cliConfigPath
    env.DEBUG && console.timeEnd('Searching for config')

    if (this.context) {
      this.context.changedContent = this.changedContent.splice(0)

      return this.context
    }

    env.DEBUG && console.time('Loading config')
    let config = this.loadConfig(configPath, content)
    env.DEBUG && console.timeEnd('Loading config')

    env.DEBUG && console.time('Creating context')
    this.context = createContext(config, [])
    Object.assign(this.context, {
      userConfigPath: configPath,
    })
    env.DEBUG && console.timeEnd('Creating context')

    env.DEBUG && console.time('Resolving content paths')
    this.refreshContentPaths()
    env.DEBUG && console.timeEnd('Resolving content paths')

    if (this.watcher) {
      env.DEBUG && console.time('Watch new files')
      this.watcher.refreshWatchedFiles()
      env.DEBUG && console.timeEnd('Watch new files')
    }

    for (let file of this.readContentPaths()) {
      this.context.changedContent.push(file)
    }

    return this.context
  },
}

export async function createProcessor(args, cliConfigPath) {