Repository: jhipster/generator-jhipster
Pull request #7454 (2018-04-09 21:33:29)

Add table/column description into liquibase remarks tag
If description is defined for Entity and/or Field(s), it will be added to Table and/or Column(s) description in liquibase remarks tag in entity changelog.

- Please make sure the below checklist is followed for Pull Requests.

- [X] [Travis tests](https://travis-ci.org/jhipster/generator-jhipster/pull_requests) are green
- [X] Tests are added where necessary
- [X] Documentation is added/updated where necessary
- [X] Coding Rules & Commit Guidelines as per our [CONTRIBUTING.md document](https://github.com/jhipster/generator-jhipster/blob/master/CONTRIBUTING.md) are followed



Patch:
diff --git a/generators/entity-server/templates/src/main/resources/config/liquibase/changelog/added_entity.xml.ejs b/generators/entity-server/templates/src/main/resources/config/liquibase/changelog/added_entity.xml.ejs
index f6e6900f1c..77ed7d17b6 100644
--- a/generators/entity-server/templates/src/main/resources/config/liquibase/changelog/added_entity.xml.ejs
+++ b/generators/entity-server/templates/src/main/resources/config/liquibase/changelog/added_entity.xml.ejs
@@ -47,7 +47,11 @@
         Added the entity <%= entityClass %>.
     -->
     <changeSet id="<%= changelogDate %>-1" author="jhipster">
+        <%_ if (typeof javadoc == 'undefined') { _%>
         <createTable tableName="<%= entityTableName %>">
+        <%_ } else { _%>
+        <createTable tableName="<%= entityTableName %>" remarks="<%- formatAsLiquibaseRemarks(javadoc) %>">
+        <%_ } _%>
             <column name="id" type="bigint" autoIncrement="${autoIncrement}">
                 <constraints primaryKey="true" nullable="false"/>
             </column><% for (idx in fields) {
@@ -101,7 +105,11 @@
                 }
             }
             %>
+            <%_ if (typeof fields[idx].javadoc == 'undefined') { _%>
             <column name="<%=columnName %>" type="<%=columnType %>">
+            <%_ } else { _%>
+            <column name="<%=columnName %>" type="<%=columnType %>" remarks="<%- formatAsLiquibaseRemarks(fields[idx].javadoc) %>">
+            <%_ } _%>
                 <%_ if (unique) { _%>
                 <constraints nullable="<%= nullable %>" unique="true" />
                 <%_ } else { _%>
diff --git a/generators/generator-base-private.js b/generators/generator-base-private.js
index d187bdb2aa..e07c04fef6 100644
--- a/generators/generator-base-private.js
+++ b/generators/generator-base-private.js
@@ -341,7 +341,7 @@ module.exports = class extends Generator {
             return text;
         }
         const rows = text.split('\n');
-        let description = rows[0];
+        let description = this.formatLineForJavaStringUse(rows[0]);
         for (let i = 1; i < rows.length; i++) {
             // discard empty rows
             if (rows[i].trim() !== '') {
@@ -362,6 +362,41 @@ module.exports = class extends Generator {
         return text.replace(/"/g, '\\"');
     }
 
+    /**
+     * Format As Liquibase Remarks
+     *
+     * @param {string} text - text to format
+     * @returns formatted liquibase remarks
+     */
+    formatAsLiquibaseRemarks(text) {
+        if (!text) {
+            return text;
+        }
+        const rows = text.split('\n');
+        let description = rows[0];
+        for (let i = 1; i < rows.length; i++) {
+            // discard empty rows
+            if (rows[i].trim() !== '') {
+                // if simple text then put space between row strings
+                if (!description.endsWith('>') && !rows[i].startsWith('<')) {
+                    description += ' ';
+                }
+                description += rows[i];
+            }
+        }
+        // escape & to &amp;
+        description = description.replace(/&/g, '&amp;');
+        // escape " to &quot;
+        description = description.replace(/"/g, '&quot;');
+        // escape ' to &apos;
+        description = description.replace(/'/g, '&apos;');
+        // escape < to &lt;
+        description = description.replace(/</g, '&lt;');
+        // escape > to &gt;
+        description = description.replace(/>/g, '&gt;');
+        return description;
+    }
+
     /**
      * @param {any} input input
      * @returns {boolean} true if input is number; false otherwise


Test patch:
diff --git a/test/generator-base-private.spec.js b/test/generator-base-private.spec.js
index 700d5081d9..48302fe6ef 100644
--- a/test/generator-base-private.spec.js
+++ b/test/generator-base-private.spec.js
@@ -181,7 +181,54 @@ export * from './entityFolderName/entityFileName.state';`;
             describe('when having quotes', () => {
                 it('formats the text to make the string valid', () => {
                     // eslint-disable-next-line quotes
-                    expect(BaseGenerator.formatAsApiDescription("JHipster is \"the\" best")).to.equal("JHipster is \"the\" best");
+                    expect(BaseGenerator.formatAsApiDescription('JHipster is "the" best')).to.equal('JHipster is \\"the\\" best');
+                });
+            });
+        });
+    });
+
+    describe('formatAsLiquibaseRemarks', () => {
+        describe('when formatting a nil text', () => {
+            it('returns it', () => {
+                expect(BaseGenerator.formatAsLiquibaseRemarks()).to.equal(undefined);
+            });
+        });
+        describe('when formatting an empty text', () => {
+            it('returns it', () => {
+                expect(BaseGenerator.formatAsLiquibaseRemarks('')).to.equal('');
+            });
+        });
+        describe('when formatting normal texts', () => {
+            describe('when having empty lines', () => {
+                it('discards them', () => {
+                    expect(BaseGenerator.formatAsLiquibaseRemarks('First line\n \nSecond line\n\nThird line')).to.equal('First line Second line Third line');
+                });
+            });
+            describe('when having a plain text', () => {
+                it('puts a space before each line', () => {
+                    expect(BaseGenerator.formatAsLiquibaseRemarks('JHipster is\na great generator')).to.equal('JHipster is a great generator');
+                });
+            });
+            describe('when having ampersand', () => {
+                it('formats the text to escape it', () => {
+                    expect(BaseGenerator.formatAsLiquibaseRemarks('JHipster uses Spring & Hibernate')).to.equal('JHipster uses Spring &amp; Hibernate');
+                });
+            });
+            describe('when having quotes', () => {
+                it('formats the text to escape it', () => {
+                    // eslint-disable-next-line quotes
+                    expect(BaseGenerator.formatAsLiquibaseRemarks('JHipster is "the" best')).to.equal('JHipster is &quot;the&quot; best');
+                });
+            });
+            describe('when having apostrophe', () => {
+                it('formats the text to escape it', () => {
+                    // eslint-disable-next-line quotes
+                    expect(BaseGenerator.formatAsLiquibaseRemarks("JHipster is 'the' best")).to.equal("JHipster is &apos;the&apos; best");
+                });
+            });
+            describe('when having HTML tags < and >', () => {
+                it('formats the text to escape it', () => {
+                    expect(BaseGenerator.formatAsLiquibaseRemarks('Not boldy\n<b>boldy</b>')).to.equal('Not boldy&lt;b&gt;boldy&lt;/b&gt;');
                 });
             });
         });