@@ -1875,14 +1875,54 @@ namespace ts {
1875
1875
const reservedCharacterPattern = / [ ^ \w \s \/ ] / g;
1876
1876
const wildcardCharCodes = [ CharacterCodes . asterisk , CharacterCodes . question ] ;
1877
1877
1878
- /**
1879
- * Matches any single directory segment unless it is the last segment and a .min.js file
1880
- * Breakdown:
1881
- * [^./] # matches everything up to the first . character (excluding directory seperators)
1882
- * (\\.(?!min\\.js$))? # matches . characters but not if they are part of the .min.js file extension
1883
- */
1884
- const singleAsteriskRegexFragmentFiles = "([^./]|(\\.(?!min\\.js$))?)*" ;
1885
- const singleAsteriskRegexFragmentOther = "[^/]*" ;
1878
+ /* @internal */
1879
+ export const commonPackageFolders : ReadonlyArray < string > = [ "node_modules" , "bower_components" , "jspm_packages" ] ;
1880
+
1881
+ const implicitExcludePathRegexPattern = `(?!(${ commonPackageFolders . join ( "|" ) } )(/|$))` ;
1882
+
1883
+ interface WildcardMatcher {
1884
+ singleAsteriskRegexFragment : string ;
1885
+ doubleAsteriskRegexFragment : string ;
1886
+ replaceWildcardCharacter : ( match : string ) => string ;
1887
+ }
1888
+
1889
+ const filesMatcher : WildcardMatcher = {
1890
+ /**
1891
+ * Matches any single directory segment unless it is the last segment and a .min.js file
1892
+ * Breakdown:
1893
+ * [^./] # matches everything up to the first . character (excluding directory seperators)
1894
+ * (\\.(?!min\\.js$))? # matches . characters but not if they are part of the .min.js file extension
1895
+ */
1896
+ singleAsteriskRegexFragment : "([^./]|(\\.(?!min\\.js$))?)*" ,
1897
+ /**
1898
+ * Regex for the ** wildcard. Matches any number of subdirectories. When used for including
1899
+ * files or directories, does not match subdirectories that start with a . character
1900
+ */
1901
+ doubleAsteriskRegexFragment : `(/${ implicitExcludePathRegexPattern } [^/.][^/]*)*?` ,
1902
+ replaceWildcardCharacter : match => replaceWildcardCharacter ( match , filesMatcher . singleAsteriskRegexFragment )
1903
+ } ;
1904
+
1905
+ const directoriesMatcher : WildcardMatcher = {
1906
+ singleAsteriskRegexFragment : "[^/]*" ,
1907
+ /**
1908
+ * Regex for the ** wildcard. Matches any number of subdirectories. When used for including
1909
+ * files or directories, does not match subdirectories that start with a . character
1910
+ */
1911
+ doubleAsteriskRegexFragment : `(/${ implicitExcludePathRegexPattern } [^/.][^/]*)*?` ,
1912
+ replaceWildcardCharacter : match => replaceWildcardCharacter ( match , directoriesMatcher . singleAsteriskRegexFragment )
1913
+ } ;
1914
+
1915
+ const excludeMatcher : WildcardMatcher = {
1916
+ singleAsteriskRegexFragment : "[^/]*" ,
1917
+ doubleAsteriskRegexFragment : "(/.+?)?" ,
1918
+ replaceWildcardCharacter : match => replaceWildcardCharacter ( match , excludeMatcher . singleAsteriskRegexFragment )
1919
+ } ;
1920
+
1921
+ const wildcardMatchers = {
1922
+ files : filesMatcher ,
1923
+ directories : directoriesMatcher ,
1924
+ exclude : excludeMatcher
1925
+ } ;
1886
1926
1887
1927
export function getRegularExpressionForWildcard ( specs : ReadonlyArray < string > , basePath : string , usage : "files" | "directories" | "exclude" ) : string | undefined {
1888
1928
const patterns = getRegularExpressionsForWildcards ( specs , basePath , usage ) ;
@@ -1901,17 +1941,8 @@ namespace ts {
1901
1941
return undefined ;
1902
1942
}
1903
1943
1904
- const replaceWildcardCharacter = usage === "files" ? replaceWildCardCharacterFiles : replaceWildCardCharacterOther ;
1905
- const singleAsteriskRegexFragment = usage === "files" ? singleAsteriskRegexFragmentFiles : singleAsteriskRegexFragmentOther ;
1906
-
1907
- /**
1908
- * Regex for the ** wildcard. Matches any number of subdirectories. When used for including
1909
- * files or directories, does not match subdirectories that start with a . character
1910
- */
1911
- const doubleAsteriskRegexFragment = usage === "exclude" ? "(/.+?)?" : "(/[^/.][^/]*)*?" ;
1912
-
1913
1944
return flatMap ( specs , spec =>
1914
- spec && getSubPatternFromSpec ( spec , basePath , usage , singleAsteriskRegexFragment , doubleAsteriskRegexFragment , replaceWildcardCharacter ) ) ;
1945
+ spec && getSubPatternFromSpec ( spec , basePath , usage , wildcardMatchers [ usage ] ) ) ;
1915
1946
}
1916
1947
1917
1948
/**
@@ -1922,7 +1953,7 @@ namespace ts {
1922
1953
return ! / [ . * ? ] / . test ( lastPathComponent ) ;
1923
1954
}
1924
1955
1925
- function getSubPatternFromSpec ( spec : string , basePath : string , usage : "files" | "directories" | "exclude" , singleAsteriskRegexFragment : string , doubleAsteriskRegexFragment : string , replaceWildcardCharacter : ( match : string ) => string ) : string | undefined {
1956
+ function getSubPatternFromSpec ( spec : string , basePath : string , usage : "files" | "directories" | "exclude" , { singleAsteriskRegexFragment , doubleAsteriskRegexFragment, replaceWildcardCharacter } : WildcardMatcher ) : string | undefined {
1926
1957
let subpattern = "" ;
1927
1958
let hasRecursiveDirectoryWildcard = false ;
1928
1959
let hasWrittenComponent = false ;
@@ -1961,20 +1992,36 @@ namespace ts {
1961
1992
}
1962
1993
1963
1994
if ( usage !== "exclude" ) {
1995
+ let componentPattern = "" ;
1964
1996
// The * and ? wildcards should not match directories or files that start with . if they
1965
1997
// appear first in a component. Dotted directories and files can be included explicitly
1966
1998
// like so: **/.*/.*
1967
1999
if ( component . charCodeAt ( 0 ) === CharacterCodes . asterisk ) {
1968
- subpattern += "([^./]" + singleAsteriskRegexFragment + ")?" ;
2000
+ componentPattern += "([^./]" + singleAsteriskRegexFragment + ")?" ;
1969
2001
component = component . substr ( 1 ) ;
1970
2002
}
1971
2003
else if ( component . charCodeAt ( 0 ) === CharacterCodes . question ) {
1972
- subpattern += "[^./]" ;
2004
+ componentPattern += "[^./]" ;
1973
2005
component = component . substr ( 1 ) ;
1974
2006
}
1975
- }
1976
2007
1977
- subpattern += component . replace ( reservedCharacterPattern , replaceWildcardCharacter ) ;
2008
+ componentPattern += component . replace ( reservedCharacterPattern , replaceWildcardCharacter ) ;
2009
+
2010
+ // Patterns should not include subfolders like node_modules unless they are
2011
+ // explicitly included as part of the path.
2012
+ //
2013
+ // As an optimization, if the component pattern is the same as the component,
2014
+ // then there definitely were no wildcard characters and we do not need to
2015
+ // add the exclusion pattern.
2016
+ if ( componentPattern !== component ) {
2017
+ subpattern += implicitExcludePathRegexPattern ;
2018
+ }
2019
+
2020
+ subpattern += componentPattern ;
2021
+ }
2022
+ else {
2023
+ subpattern += component . replace ( reservedCharacterPattern , replaceWildcardCharacter ) ;
2024
+ }
1978
2025
}
1979
2026
1980
2027
hasWrittenComponent = true ;
@@ -1988,14 +2035,6 @@ namespace ts {
1988
2035
return subpattern ;
1989
2036
}
1990
2037
1991
- function replaceWildCardCharacterFiles ( match : string ) {
1992
- return replaceWildcardCharacter ( match , singleAsteriskRegexFragmentFiles ) ;
1993
- }
1994
-
1995
- function replaceWildCardCharacterOther ( match : string ) {
1996
- return replaceWildcardCharacter ( match , singleAsteriskRegexFragmentOther ) ;
1997
- }
1998
-
1999
2038
function replaceWildcardCharacter ( match : string , singleAsteriskRegexFragment : string ) {
2000
2039
return match === "*" ? singleAsteriskRegexFragment : match === "?" ? "[^/]" : "\\" + match ;
2001
2040
}
0 commit comments