Skip to content

Commit

Permalink
Support json(5) files
Browse files Browse the repository at this point in the history
  • Loading branch information
vweevers committed Dec 10, 2020
1 parent 8682d96 commit 4db88fe
Show file tree
Hide file tree
Showing 5 changed files with 87 additions and 5 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@ Files can be glob patterns or paths to a:

- Visual Studio Solution (`*.sln`) (parsed to find projects)
- Project (`*.csproj` or `*.fsproj`) (parsed to find a `Version` element or `AssemblyInfo` file)
- C# or F# source code file;
- C# or F# source code file
- JSON or JSON5 file;
- Directory containing any of the above.

Default is the current working directory. Files must reside in a git working tree (or multiple working trees).
Expand Down
25 changes: 22 additions & 3 deletions lib/finder.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ const Emitter = require('events').EventEmitter
const detectLanguage = require('language-detect')
const AssemblyFile = require('./assembly-file')
const ProjectFile = require('./project-file')
const JsonFile = require('./json-file')

const SOURCE_EXT_LANGUAGES = {
'.cs': 'C#',
Expand All @@ -28,7 +29,7 @@ const PROJECT_EXT_LANGUAGES = {

const GLOB_IGNORE = [
'**/{packages,bin,obj,OpenCover,TestResults,node_modules,.git}/**',
'**/*.{json,md,tar,gz,zip,7z,vs,xml,txt,yml,js,dll,exe,pdb,node,lib,pb,html,config,user,config,manifest}'
'**/*.{md,tar,gz,zip,7z,vs,xml,txt,yml,js,dll,exe,pdb,node,lib,pb,html,config,user,config,manifest,rc}'
]

module.exports = class Finder extends Emitter {
Expand Down Expand Up @@ -93,6 +94,8 @@ module.exports = class Finder extends Emitter {

if (ext === '.sln') {
this.readSolution(file, done)
} else if (ext === '.json' || ext === '.json5') {
this.readJson(file, done)
} else if (PROJECT_EXT_LANGUAGES[ext]) {
this.readProject(file, PROJECT_EXT_LANGUAGES[ext], done)
} else if (SOURCE_EXT_LANGUAGES[ext]) {
Expand All @@ -108,6 +111,19 @@ module.exports = class Finder extends Emitter {
})
}

readJson (jsonFile, done) {
if (this.skip('json', jsonFile)) return done()

fs.readFile(jsonFile, 'utf8', (err, source) => {
if (err) return done(err)

const result = JsonFile.maybe(jsonFile, source)
if (result) this.found(result)

done()
})
}

readProject (projectFile, language, done) {
if (this.skip('project', projectFile)) return done()

Expand Down Expand Up @@ -147,16 +163,19 @@ module.exports = class Finder extends Emitter {
scanDirectory (dir, done) {
if (this.skip('directory', dir)) return done()

glob('*.{sln,csproj,fsproj}', { cwd: dir, nodir: true, absolute: true }, (err, files) => {
glob('{*,config/*}.{sln,csproj,fsproj,json,json5}', { cwd: dir, nodir: true, absolute: true }, (err, files) => {
if (err) return done(err)

const next = after(files.length, done)

for (const file of files) {
for (const unixy of files) {
const file = path.normalize(unixy)
const ext = path.extname(file)

if (ext === '.sln') {
this.readSolution(file, next)
} else if (ext === '.json' || ext === '.json5') {
this.readJson(file, next)
} else if (PROJECT_EXT_LANGUAGES[ext]) {
this.readProject(file, PROJECT_EXT_LANGUAGES[ext], next)
} else {
Expand Down
60 changes: 60 additions & 0 deletions lib/json-file.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
'use strict'

const JSON5 = require('json5')
const fs = require('fs')
const AbstractFile = require('./abstract-file')

const kSource = Symbol('kSource')
const kKey = Symbol('kKey')
const kVersion = Symbol('kVersion')

class JsonFile extends AbstractFile {
constructor (path, source, key, version) {
super(path)

this[kSource] = source
this[kKey] = key
this[kVersion] = version
}

[AbstractFile.read] (callback) {
process.nextTick(callback)
}

[AbstractFile.write] (callback) {
fs.writeFile(this.path, this[kSource], callback)
}

[AbstractFile.getVersion] () {
return this[kVersion]
}

[AbstractFile.setVersion] (version) {
// Search and replace JSON in order to preserve comments
const key = this[kKey]
const re = new RegExp(`"${key}"\\s*:\\s*"[^"]+"`)
const source = this[kSource].replace(re, `"${key}": "${version}"`)

// Check that the JSON is valid
if (JSON5.parse(source)[key] !== version) {
throw new Error('Failed to set ' + key)
}

this[kSource] = source
this[kVersion] = version
}
}

JsonFile.maybe = function (fp, source) {
const data = JSON5.parse(source)

for (const key of ['version', 'ProductVersion']) {
const version = data[key]

if (typeof version === 'string' && version.trim() !== '') {
return new JsonFile(fp, source, key, version)
}
}
}

module.exports = JsonFile
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
"glob": "^7.1.2",
"is-dirty": "0.2.1",
"is-glob": "^4.0.1",
"json5": "^2.1.3",
"language-detect": "^1.1.0",
"minimist": "^1.2.0",
"once": "^1.4.0",
Expand Down
3 changes: 2 additions & 1 deletion usage.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ Files can be glob patterns or paths to a:

- Visual Studio Solution (*.sln) (parsed to find projects)
- Project (*.csproj or *.fsproj) (parsed to find AssemblyInfo)
- C# or F# source code file;
- C# or F# source code file
- JSON or JSON5 file;
- Directory containing any of the above.

Default is the current working directory. Files must reside
Expand Down

0 comments on commit 4db88fe

Please sign in to comment.