From f2a7c2c4532b76d61351f1ca7e26ec8c93729b5d Mon Sep 17 00:00:00 2001 From: Robin Malfait Date: Fri, 5 Jan 2024 17:23:30 +0100 Subject: [PATCH] Improve glob handling for folders with `(`, `)`, `[` or `]` in the file path (#12715) * sync package-lock.json * modify `normalizePath` to keep `\\[`, `\\]`, `\\(` and `\\)` into account * manually escape () and [] characters in globs * update changelog --- CHANGELOG.md | 1 + src/lib/content.js | 43 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index eb6effe4ee0d..b7bc1961179b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Don't remove keyframe stops when using important utilities ([#12639](https://github.com/tailwindlabs/tailwindcss/pull/12639)) - Don't add spaces to gradients and grid track names when followed by `calc()` ([#12704](https://github.com/tailwindlabs/tailwindcss/pull/12704)) - Restore old behavior for `class` dark mode strategy ([#12717](https://github.com/tailwindlabs/tailwindcss/pull/12717)) +- Improve glob handling for folders with `(`, `)`, `[` or `]` in the file path ([#12715](https://github.com/tailwindlabs/tailwindcss/pull/12715)) ### Added diff --git a/src/lib/content.js b/src/lib/content.js index e814efe4d34e..97bef6afadce 100644 --- a/src/lib/content.js +++ b/src/lib/content.js @@ -4,10 +4,47 @@ import fs from 'fs' import path from 'path' import isGlob from 'is-glob' import fastGlob from 'fast-glob' -import normalizePath from 'normalize-path' import { parseGlob } from '../util/parseGlob' import { env } from './sharedState' +/*! + * Modified version of normalize-path, original license below + * + * normalize-path + * + * Copyright (c) 2014-2018, Jon Schlinkert. + * Released under the MIT License. + */ + +function normalizePath(path) { + if (typeof path !== 'string') { + throw new TypeError('expected path to be a string') + } + + if (path === '\\' || path === '/') return '/' + + var len = path.length + if (len <= 1) return path + + // ensure that win32 namespaces has two leading slashes, so that the path is + // handled properly by the win32 version of path.parse() after being normalized + // https://msdn.microsoft.com/library/windows/desktop/aa365247(v=vs.85).aspx#namespaces + var prefix = '' + if (len > 4 && path[3] === '\\') { + var ch = path[2] + if ((ch === '?' || ch === '.') && path.slice(0, 2) === '\\\\') { + path = path.slice(2) + prefix = '//' + } + } + + // Modified part: instead of purely splitting on `\\` and `/`, we split on + // `/` and `\\` that is _not_ followed by any of the following characters: ()[] + // This is to ensure that we keep the escaping of brackets and parentheses + let segs = path.split(/[/\\]+(?![\(\)\[\]])/) + return prefix + segs.join('/') +} + /** @typedef {import('../../types/config.js').RawFile} RawFile */ /** @typedef {import('../../types/config.js').FilePath} FilePath */ @@ -73,6 +110,10 @@ export function parseCandidateFiles(context, tailwindConfig) { * @returns {ContentPath} */ function parseFilePath(filePath, ignore) { + // Escape special characters in the file path such as: ()[] + // But only if the special character isn't already escaped + filePath = filePath.replace(/(?