-
Notifications
You must be signed in to change notification settings - Fork 362
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(js-config): js config files (e.g. .eslintrc.js
)
#2414
base: main
Are you sure you want to change the base?
Conversation
0de600e
to
aec8611
Compare
.eslintrc.js
)
aec8611
to
a5d0441
Compare
Codecov Report
📣 This organization is not using Codecov’s GitHub App Integration. We recommend you install it so Codecov can continue to function properly for your repositories. Learn more @@ Coverage Diff @@
## main #2414 +/- ##
=======================================
Coverage 93.68% 93.68%
=======================================
Files 176 177 +1
Lines 31061 31131 +70
Branches 2424 2430 +6
=======================================
+ Hits 29099 29165 +66
- Misses 1962 1966 +4
Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here. |
a5d0441
to
2c222a0
Compare
import { IResolver } from "./file"; | ||
import { JsonFileOptions } from "./json"; | ||
import { ObjectFile } from "./object-file"; | ||
import { Project } from "./project"; | ||
|
||
/** | ||
* Options for the JsConfigFile class. | ||
*/ | ||
export interface JsConfigFileOptions extends JsonFileOptions {} | ||
|
||
/** | ||
* Represents a JS configuratin file (e.g. .eslintrc.js). | ||
* Suppor | ||
*/ | ||
export class JsConfigFile extends ObjectFile { | ||
static identifier(str: string): string { | ||
return `${JsConfigFile.jsConfigFileIdentifier}${str}`; | ||
} | ||
private static readonly jsConfigFileIdentifier = | ||
"__projenJsConfigFileIdentifier#"; | ||
constructor( | ||
project: Project, | ||
filePath: string, | ||
options: JsConfigFileOptions | ||
) { | ||
super(project, filePath, options); | ||
if (!options.obj) { | ||
throw new Error('"obj" cannot be undefined'); | ||
} | ||
} | ||
|
||
protected synthesizeContent(resolver: IResolver): string | undefined { | ||
const json = super.synthesizeContent(resolver); | ||
if (!json) { | ||
return undefined; | ||
} | ||
|
||
const sanitized = JSON.parse(json); | ||
let content = JSON.stringify(sanitized, undefined, 2); | ||
content = this.replaceIdentifier(content); | ||
content = `module.exports = ${content};`; | ||
content = `// ${this.marker}\n${content}`; | ||
|
||
return content; | ||
} | ||
|
||
private replaceIdentifier(str: string): string { | ||
const regex = new RegExp( | ||
`(\"${JsConfigFile.jsConfigFileIdentifier})([a-zA-Z_$][a-zA-Z_$0-9]+)(\")`, | ||
"gm" | ||
); | ||
return str.replace(regex, "$2"); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This file should probably live inside the javascript submodule.
import { Projenrc } from "../../src/projenrc-json"; | ||
import { synthSnapshot } from "../util"; | ||
|
||
test(".eslintrc.js with identifier values", () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice! Would also need some tests dedicated to JsConfigFile
directly.
*/ | ||
export class JsConfigFile extends ObjectFile { | ||
static identifier(str: string): string { | ||
return `${JsConfigFile.jsConfigFileIdentifier}${str}`; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Out of curiosity what else did you try?
Using a function or an object with a Scrap that. Won't work.toJSON()
comes to mind, but not sure if it's still running through JSON.stringify
adding quotes afterwards.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess we could build our own recursive renderer that prints out Json.stringify
unless the value is a certain instanceof (could use Symbol
or something custom).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here is a gist that does that: https://gist.github.com/mrgrain/a61408a4e8dd2006be5000a6523bf28e
But I wonder if that's enough or if people would want to start using imports as well. 🤔
* Write eslint configuration as JsConfig file instead of JSON | ||
* @default false | ||
*/ | ||
readonly jsConfig?: boolean; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess at this point we should start replacing the boolean flags with a fileformat enum.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
I hope we consider all complex environments before merging this proposal. Legacy ESlint JS-config is not supporting ESM, so, if If the whole proposal is just a workaround for setting |
return undefined; | ||
} | ||
|
||
const sanitized = JSON.parse(json); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NIT: (as I hope this will not be merged) but replaceIdentifier
may be more robustly implemented as JSON reviver.
Drafting this PR as I clearly needs more discussions.
No I don't think it is. That might have been the issue that brought it up, but not being able to produce JS based configurations is certainly a gap in projen.
This is very interesting. I wonder how that fits within our current Eslint component in general. To me this now looks like we have two problems at hand:
|
Introduces
JsConfigFile
which is compatible withJsonFile
interface.The class exposes the static method
JsConfigFile.identifier(str: string)
to allow rendering globals such as__dirname
.Implemented using a magic string, happy to reimplement if someone has a better idea.
Fixes #2405
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.