Skip to content

Commit

Permalink
Merge 30fe8ae into 2e87ce4
Browse files Browse the repository at this point in the history
  • Loading branch information
hildjj committed Jul 2, 2023
2 parents 2e87ce4 + 30fe8ae commit 5a37409
Show file tree
Hide file tree
Showing 7 changed files with 121 additions and 23 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/node.js.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name: Tests
on:
push:
branches:
- '*'
- main
pull_request:
branches: ['*']

Expand All @@ -12,7 +12,7 @@ jobs:

strategy:
matrix:
node-version: [14.x, 16.x, 18.x, 19.x]
node-version: [16.x, 18.x, 20.x]
os: [ubuntu-latest, macos-latest, windows-latest]

runs-on: ${{ matrix.os }}
Expand All @@ -29,7 +29,7 @@ jobs:
- name: Install dependencies
run: npm install
- name: Check coding standards
if: matrix.node-version == '18.x' && matrix.os == 'ubuntu-latest'
if: matrix.node-version == '20.x' && matrix.os == 'ubuntu-latest'
run: npm run lint
- name: Test
run: npm run ci
Expand Down
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,16 @@
## 2.0.0

- **Breaking**: Now requires Node v16+
- Enable extended globbing from minimatch. This means that some patterns will
work in this version might not work in other editorconfig implementations.
Fixes #84.
- Add `unset` option to API and CLI. When enabled, properties with the value
"unset" will be removed from the returned object. Defaults to false in all
cases, since according to the core team, this is something that the editor
plugin is supposed to do, and the tests reinforce this. An `unset()`
function is now exported if you'd like to call it explicitly.
Fixes #123.

## 1.0.3

- Updated all dependencies, including security fixes for semver 7.3.8
Expand Down
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,6 @@
"typescript": "^5.1.3"
},
"engines": {
"node": ">=14"
"node": ">=16"
}
}
2 changes: 2 additions & 0 deletions src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ export default async function cli(
.option('-f <path>', 'Specify conf filename other than \'.editorconfig\'')
.option('-b <version>', 'Specify version (used by devs to test compatibility)')
.option('--files', 'Output file names that contributed to the configuration, rather than the configuation itself')
.option('--unset', 'Remove all properties whose final value is \'unset\'')
.parse(args)

const files = program.args
Expand All @@ -73,6 +74,7 @@ export default async function cli(
version: opts.b as string,
files: visited ? visited[i++] : undefined,
cache,
unset: Boolean(opts.unset),
}))
}
return p
Expand Down
35 changes: 34 additions & 1 deletion src/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -178,9 +178,42 @@ describe('parseString', () => {
cfg.should.eql([[null, {}], ['a\\\\b', {}]])
})


it('handles blank comments', () => {
const cfg = editorconfig.parseString('#')
cfg.should.eql([[null, {}]])
})
})

describe('extra behavior', () => {
it('handles extended globs', () => {
// These failed when we had noext: true in matchOptions
const matcher = editorconfig.matcher({
root: __dirname,
}, Buffer.from(`\
[*]
indent_size = 4
[!(package).json]
indent_size = 3`))

matcher(path.join(__dirname, 'package.json')).should.match({ indent_size: 4 })
matcher(path.join(__dirname, 'foo.json')).should.match({ indent_size: 3 })
})
})

describe('unset', () => {
it('pair witht the value `unset`', () => {
const matcher = editorconfig.matcher({
root: __dirname,
unset: true,
}, Buffer.from(`\
[*]
indent_size = 4
[*.json]
indent_size = unset
`))
matcher(path.join(__dirname, 'index.js')).should.match({ indent_size: 4 })
matcher(path.join(__dirname, 'index.json')).should.be.eql({ })
})
})
84 changes: 67 additions & 17 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { parse_to_uint32array, TokenTypes } from '@one-ini/wasm'
import pkg from '../package.json'

const escapedSep = new RegExp(path.sep.replace(/\\/g, '\\\\'), 'g')
const matchOptions = { matchBase: true, dot: true, noext: true }
const matchOptions = { matchBase: true, dot: true }

// These are specified by the editorconfig script
/* eslint-disable @typescript-eslint/naming-convention */
Expand Down Expand Up @@ -61,19 +61,18 @@ export interface ParseOptions {
root?: string
files?: Visited[]
cache?: Cache
unset?: boolean
}

// These are specified by the editorconfig script
/* eslint-disable @typescript-eslint/naming-convention */
const knownProps = {
end_of_line: true,
indent_style: true,
indent_size: true,
insert_final_newline: true,
trim_trailing_whitespace: true,
charset: true,
}
/* eslint-enable @typescript-eslint/naming-convention */
const knownPropNames: (keyof KnownProps)[] = [
'end_of_line',
'indent_style',
'indent_size',
'insert_final_newline',
'trim_trailing_whitespace',
'charset',
]
const knownProps = new Set<string>(knownPropNames)

export type SectionName = string | null
export interface SectionBody { [key: string]: string }
Expand Down Expand Up @@ -190,7 +189,7 @@ function processMatches(matches: Props, version: string): Props {
function buildFullGlob(pathPrefix: string, glob: string): Minimatch {
switch (glob.indexOf('/')) {
case -1:
glob = '**/' + glob
glob = `**/${glob}`
break
case 0:
glob = glob.substring(1)
Expand All @@ -217,14 +216,13 @@ function buildFullGlob(pathPrefix: string, glob: string): Minimatch {
* @returns
*/
function normalizeProps(options: SectionBody): Props {
const props = {}
const props: Props = {}
for (const key in options) {
if (options.hasOwnProperty(key)) {
const value = options[key]
const key2 = key.toLowerCase()
let value2: unknown = value
// @ts-ignore -- Fix types here
if (knownProps[key2]) {
if (knownProps.has(key2)) {
// All of the values for the known props are lowercase.
value2 = String(value).toLowerCase()
}
Expand All @@ -236,7 +234,6 @@ function normalizeProps(options: SectionBody): Props {
// in editorconfig) & should just be returned as regular strings.
value2 = String(value)
}
// @ts-ignore -- Fix types here
props[key2] = value2
}
}
Expand Down Expand Up @@ -430,6 +427,7 @@ function opts(filepath: string, options: ParseOptions = {}): [
root: path.resolve(options.root || path.parse(resolvedFilePath).root),
files: options.files,
cache: options.cache,
unset: options.unset,
},
]
}
Expand Down Expand Up @@ -511,11 +509,33 @@ function combine(
}
}
}

return props
}, {})

if (options.unset) {
unset(ret)
}

return processMatches(ret, options.version as string)
}

/**
* For any pair, a value of `unset` removes the effect of that pair, even if
* it has been set before. This method modifies the properties object in
* place to remove any property that has a value of `unset`.
*
* @param props Properties object to modify.
*/
export function unset(props: Props): void {
const keys = Object.keys(props)
for (const k of keys) {
if (props[k] === 'unset') {
delete props[k]
}
}
}

/**
* Find all of the properties from matching sections in config files in the
* same directory or toward the root of the filesystem.
Expand Down Expand Up @@ -551,3 +571,33 @@ export function parseSync(
const configs = getAllConfigsSync(filepaths, processedOptions)
return combine(resolvedFilePath, configs, processedOptions)
}

/**
* I think this may be of limited utility at the moment, but I need something
* like this for testing. As such, the interface of this may change without
* warning.
*
* Something this direction may be better for editors than the caching bits
* we've got today, but that will need some thought.
*
* @param options All options. root will be process.cwd if not specified.
* @param buffers 1 or more Buffers that have .editorconfig contents.
* @returns Function that can be called multiple times for different paths.
* @private
*/
export function matcher(
options: ParseOptions,
...buffers: Buffer[]
): (filepath: string) => Props {
const processedOptions = opts('', options)[1]
const configs = buffers.map(
(buf, i) => processFileContents(
path.join(processedOptions.root as string, `buffer-${i}`),
buf,
processedOptions
))
return (filepath: string) => {
const resolvedFilePath = path.resolve(filepath)
return combine(resolvedFilePath, configs, processedOptions)
}
}

0 comments on commit 5a37409

Please sign in to comment.