diff --git a/src/IGenerationOptions.ts b/src/IGenerationOptions.ts index 7e3ae8f..684494d 100644 --- a/src/IGenerationOptions.ts +++ b/src/IGenerationOptions.ts @@ -1,3 +1,5 @@ +import { EOL } from "os"; + import path = require("path"); // TODO: change name @@ -10,6 +12,7 @@ export default interface IGenerationOptions { convertCaseFile: "pascal" | "param" | "camel" | "none"; convertCaseEntity: "pascal" | "camel" | "none"; convertCaseProperty: "pascal" | "camel" | "none"; + convertEol: "LF" | "CRLF"; propertyVisibility: "public" | "protected" | "private" | "none"; lazy: boolean; activeRecord: boolean; @@ -21,6 +24,12 @@ export default interface IGenerationOptions { indexFile: boolean; exportType: "named" | "default"; } + +export const eolConverter = { + LF: "\n", + CRLF: "\r\n" +}; + export function getDefaultGenerationOptions(): IGenerationOptions { const generationOptions: IGenerationOptions = { resultsPath: path.resolve(process.cwd(), "output"), @@ -29,6 +38,7 @@ export function getDefaultGenerationOptions(): IGenerationOptions { convertCaseFile: "pascal", convertCaseEntity: "pascal", convertCaseProperty: "camel", + convertEol: EOL === "\n" ? "LF" : "CRLF", propertyVisibility: "none", lazy: false, activeRecord: false, diff --git a/src/ModelGeneration.ts b/src/ModelGeneration.ts index c723447..af573e9 100644 --- a/src/ModelGeneration.ts +++ b/src/ModelGeneration.ts @@ -3,8 +3,9 @@ import * as Prettier from "prettier"; import * as changeCase from "change-case"; import * as fs from "fs"; import * as path from "path"; +import { EOL } from "os"; import IConnectionOptions from "./IConnectionOptions"; -import IGenerationOptions from "./IGenerationOptions"; +import IGenerationOptions, { eolConverter } from "./IGenerationOptions"; import { Entity } from "./models/Entity"; import { Relation } from "./models/Relation"; @@ -71,7 +72,14 @@ function generateModels( `${casedFileName}.ts` ); const rendered = entityCompliedTemplate(element); - const withImportStatements = removeUnusedImports(rendered); + const withImportStatements = removeUnusedImports( + EOL !== eolConverter[generationOptions.convertEol] + ? rendered.replace( + /(\r\n|\n|\r)/gm, + eolConverter[generationOptions.convertEol] + ) + : rendered + ); const formatted = Prettier.format(withImportStatements, { parser: "typescript" }); diff --git a/src/index.ts b/src/index.ts index 9f40faf..15e34c8 100644 --- a/src/index.ts +++ b/src/index.ts @@ -11,7 +11,6 @@ import IGenerationOptions, { import fs = require("fs-extra"); import inquirer = require("inquirer"); import path = require("path"); - // eslint-disable-next-line @typescript-eslint/no-floating-promises CliLogic(); @@ -215,6 +214,11 @@ function checkYargsParameters(options: options): options { default: options.generationOptions.convertCaseProperty, describe: "Convert property names to specified case" }, + eol: { + choices: ["LF", "CRLF"], + default: options.generationOptions.convertEol, + describe: "Force EOL to be LF or CRLF" + }, pv: { alias: "property-visibility", choices: ["public", "protected", "private", "none"], @@ -302,6 +306,7 @@ function checkYargsParameters(options: options): options { options.generationOptions.convertCaseEntity = argv.ce as IGenerationOptions["convertCaseEntity"]; options.generationOptions.convertCaseFile = argv.cf as IGenerationOptions["convertCaseFile"]; options.generationOptions.convertCaseProperty = argv.cp as IGenerationOptions["convertCaseProperty"]; + options.generationOptions.convertEol = argv.eol as IGenerationOptions["convertEol"]; options.generationOptions.lazy = argv.lazy; options.generationOptions.customNamingStrategyPath = argv.namingStrategy; options.generationOptions.noConfigs = argv.noConfig; @@ -525,6 +530,11 @@ async function useInquirer(options: options): Promise { options.generationOptions.convertCaseFile !== defaultGenerationOptions.convertCaseFile }, + { + name: "Use specific EOL character", + value: "converteol", + checked: false + }, { name: "Pluralize OneToMany, ManyToMany relation names", @@ -659,6 +669,18 @@ async function useInquirer(options: options): Promise { options.generationOptions.convertCaseEntity = namingConventions.entityCase; } + if (customizations.includes("converteol")) { + const eolChoice = await inquirer.prompt([ + { + choices: ["LF", "CRLF"], + default: options.generationOptions.convertEol, + message: "Force EOL to be:", + name: "eol", + type: "list" + } + ]); + options.generationOptions.convertEol = eolChoice.eol; + } } const { saveConfig } = await inquirer.prompt([ { diff --git a/test/modelCustomization/modelCustomization.test.ts b/test/modelCustomization/modelCustomization.test.ts index 8082c48..8443f1f 100644 --- a/test/modelCustomization/modelCustomization.test.ts +++ b/test/modelCustomization/modelCustomization.test.ts @@ -283,6 +283,53 @@ describe("Model customization phase", async () => { compileGeneratedModel(generationOptions.resultsPath, [""]); }); }); + describe("EOL", async () => { + it("LF", () => { + const data = generateSampleData(); + const generationOptions = generateGenerationOptions(); + clearGenerationDir(); + generationOptions.convertEol = "LF"; + const customizedModel = modelCustomizationPhase( + data, + generationOptions, + {} + ); + modelGenerationPhase( + getDefaultConnectionOptions(), + generationOptions, + customizedModel + ); + const filesGenPath = path.resolve(resultsPath, "entities"); + const postContent = fs + .readFileSync(path.resolve(filesGenPath, "Post.ts")) + .toString(); + expect(postContent).to.not.contain("\r\n"); + expect(postContent).to.contain("\n"); + compileGeneratedModel(generationOptions.resultsPath, [""]); + }); + it("CRLF", () => { + const data = generateSampleData(); + const generationOptions = generateGenerationOptions(); + clearGenerationDir(); + generationOptions.convertEol = "CRLF"; + const customizedModel = modelCustomizationPhase( + data, + generationOptions, + {} + ); + modelGenerationPhase( + getDefaultConnectionOptions(), + generationOptions, + customizedModel + ); + const filesGenPath = path.resolve(resultsPath, "entities"); + const postContent = fs + .readFileSync(path.resolve(filesGenPath, "Post.ts")) + .toString(); + expect(postContent).to.contain("\r\n"); + compileGeneratedModel(generationOptions.resultsPath, [""]); + }); + }); describe("property-visibility", () => { it("public", () => { const data = generateSampleData();