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