55'use strict' ;
66
77import * as fs from 'fs' ;
8+ import { Minimatch } from 'minimatch' ;
89import * as path from 'path' ;
10+ import { isWindows } from '../constants' ;
911
1012export const cachedEditorConfigSettings : Map < string , any > = new Map < string , any > ( ) ;
1113
@@ -61,13 +63,25 @@ export function mapWrapToEditorConfig(value: string | undefined): string {
6163 return "never" ;
6264}
6365
64- function matchesSection ( filePath : string , section : string ) : boolean {
65- const fileName : string = path . basename ( filePath ) ;
66- // Escape all regex special characters except '*' and '?'.
67- // Convert wildcards '*' to '.*' and '?' to '.'.
68- const sectionPattern = section . replace ( / [ . + ^ $ { } ( ) | [ \] \\ ] / g, '\\$&' ) . replace ( / \* / g, '.*' ) . replace ( / \? / g, '.' ) ;
69- const regex : RegExp = new RegExp ( `^${ sectionPattern } $` ) ;
70- return regex . test ( fileName ) ;
66+ export function matchesSection ( pathPrefix : string , filePath : string , section : string ) : boolean {
67+ // The following code is copied from: https://github.com/editorconfig/editorconfig-core-js
68+ const matchOptions = { matchBase : true , dot : true } ;
69+ pathPrefix = pathPrefix . replace ( / [ ? * + @ ! ( ) | [ \] { } ] / g, '\\$&' ) ;
70+ pathPrefix = pathPrefix . replace ( / ^ # / , '\\#' ) ;
71+ switch ( section . indexOf ( '/' ) ) {
72+ case - 1 :
73+ section = `**/${ section } ` ;
74+ break ;
75+ case 0 :
76+ section = section . substring ( 1 ) ;
77+ break ;
78+ default :
79+ break ;
80+ }
81+ section = section . replace ( / \\ \\ / g, '\\\\\\\\' ) ;
82+ section = section . replace ( / \* \* / g, '{*,**/**/**}' ) ;
83+ const matcher = new Minimatch ( `${ pathPrefix } /${ section } ` , matchOptions ) ;
84+ return matcher . match ( filePath ) ;
7185}
7286
7387function parseEditorConfigContent ( content : string ) : Record < string , any > {
@@ -95,9 +109,9 @@ function parseEditorConfigContent(content: string): Record<string, any> {
95109 let value : any = values . join ( '=' ) . trim ( ) ;
96110
97111 // Convert boolean-like and numeric values.
98- if ( value . toLowerCase ( ) === 'true' ) {
112+ if ( value === 'true' ) {
99113 value = true ;
100- } else if ( value . toLowerCase ( ) === 'false' ) {
114+ } else if ( value === 'false' ) {
101115 value = false ;
102116 } else if ( ! isNaN ( Number ( value ) ) ) {
103117 value = Number ( value ) ;
@@ -123,6 +137,10 @@ function getEditorConfig(filePath: string): any {
123137 let currentDir : string = path . dirname ( filePath ) ;
124138 const rootDir : string = path . parse ( currentDir ) . root ;
125139
140+ if ( isWindows ) {
141+ filePath = filePath . replace ( / \\ / g, '/' ) ;
142+ }
143+
126144 // Traverse from the file's directory to the root directory.
127145 for ( ; ; ) {
128146 const editorConfigPath : string = path . join ( currentDir , '.editorconfig' ) ;
@@ -138,9 +156,14 @@ function getEditorConfig(filePath: string): any {
138156 } ;
139157 }
140158
159+ let currentDirForwardSlashes : string = currentDir ;
160+ if ( isWindows ) {
161+ currentDirForwardSlashes = currentDir . replace ( / \\ / g, '/' ) ;
162+ }
163+
141164 // Match sections and combine configurations.
142165 Object . keys ( configData ) . forEach ( ( section : string ) => {
143- if ( section !== '*' && matchesSection ( filePath , section ) ) {
166+ if ( section !== '*' && matchesSection ( currentDirForwardSlashes , filePath , section ) ) {
144167 combinedConfig = {
145168 ...combinedConfig ,
146169 ...configData [ section ]
0 commit comments