Repository: style-dictionary/style-dictionary (JavaScript)

Issue:
javascript/es6 format doesn't handle newlines in comments
Comments are inserted as a line comment here: https://github.com/amzn/style-dictionary/blob/737a02b638b9450eb4f989fe9718357f5cba4239/lib/common/formats.js#L643

This has previously been fixed for some formats in #953 

Example of failing token

```json
{
    "token": {
        "value": 0,
        "comment": "This\nis not valid"
    },
    "another": {
        "value": 1,
    }
}
```

This fails to build with
```
SyntaxError: Missing semicolon. (6:3)
  4 |
  5 | export const token = 0; // This
> 6 | is not valid
  7 | export const another = 0;
  8 |
```


Discussion:
I'm a bit conflicted about adding the enhancement flag, it's a missing feature imo but it could also be seen as a bug I suppose.

Anyways, the [`createPropertyFormatter`](https://github.com/amzn/style-dictionary/blob/main/lib/common/formatHelpers/createPropertyFormatter.js) format helper utility has a fix for this I introduced in v3 for the CSS / SCSS / LESS / Stylus formats, see the addComment helper. We can probably make that reusable in some way, and reuse it for our JS formats since they use a similar syntax for comments (`//` and `/* */`). Actually, I'm not sure `//` is valid in CSS, but at least the latter one they do share

PRs welcome
My approach will sanitize the comments by:
1. Escaping any occurrences of `*/` to prevent premature block closure using `.replace(/\*\//g, '*\\/')`.
2. Replacing newline characters (`\n`) with spaces to ensure the comment remains on a single line using `.replace(/\n/g, ' ')`.
Please tell me if there is issue with this approach!




Patch:
diff --git a/.changeset/spotty-clocks-drop.md b/.changeset/spotty-clocks-drop.md
new file mode 100644
index 000000000..a9ec5acc6
--- /dev/null
+++ b/.changeset/spotty-clocks-drop.md
@@ -0,0 +1,5 @@
+---
+'style-dictionary': patch
+---
+
+Account for multiline comments in javascript/es6 format
diff --git a/lib/common/formats.js b/lib/common/formats.js
index e9deb1e83..447ba5d26 100644
--- a/lib/common/formats.js
+++ b/lib/common/formats.js
@@ -58,6 +58,7 @@ import {
   formats as fileFormats,
   propertyFormatNames,
 } from '../enums/index.js';
+import { addComment } from './formatHelpers/createPropertyFormatter.js';
 
 /**
  * @typedef {import('../../types/Format.d.ts').Format} Format
@@ -640,7 +641,13 @@ const formats = {
         const comment = options.usesDtcg ? token.$description : token.comment;
         const to_ret = `export const ${token.name} = ${value};`;
 
-        return comment ? to_ret.concat(`// ${comment}`) : to_ret;
+        const format = {
+          commentStyle: short,
+          indentation: '',
+          ...formatting,
+        };
+
+        return comment ? addComment(to_ret, comment, format) : to_ret;
       }),
     ]
       .flat()


Test patch:
diff --git a/__tests__/formats/__snapshots__/es6Constants.test.snap.js b/__tests__/formats/__snapshots__/es6Constants.test.snap.js
index 7f82dd950..4df8650b5 100644
--- a/__tests__/formats/__snapshots__/es6Constants.test.snap.js
+++ b/__tests__/formats/__snapshots__/es6Constants.test.snap.js
@@ -19,3 +19,15 @@ export const red = "#EF5350"; // comment
 `;
 /* end snapshot formats javascript/es6 should handle DTCG token format, be a valid JS file and matches snapshot */
 
+snapshots["formats javascript/es6 should handle multiline comments"] = 
+`/**
+ * Do not edit directly, this file was auto-generated.
+ */
+
+export const red = "#EF5350"; // comment
+// multiline
+// comment
+export const blue = "#4FEDF0";
+`;
+/* end snapshot formats javascript/es6 should handle multiline comments */
+
diff --git a/__tests__/formats/es6Constants.test.js b/__tests__/formats/es6Constants.test.js
index b3de68342..c1f8af722 100644
--- a/__tests__/formats/es6Constants.test.js
+++ b/__tests__/formats/es6Constants.test.js
@@ -56,6 +56,31 @@ const DTCGTokens = {
   },
 };
 
+const commentTokens = {
+  color: {
+    red: {
+      comment: 'comment',
+      name: 'red',
+      original: {
+        value: '#EF5350',
+      },
+      path: ['color', 'red'],
+      type: 'color',
+      value: '#EF5350',
+    },
+    blue: {
+      comment: 'multiline\ncomment',
+      name: 'blue',
+      original: {
+        value: '#4FEDF0',
+      },
+      path: ['color', 'blue'],
+      type: 'color',
+      value: '#4FEDF0',
+    },
+  },
+};
+
 const format = formats[javascriptEs6];
 
 describe('formats', () => {
@@ -85,5 +110,19 @@ describe('formats', () => {
 
       await expect(output).to.matchSnapshot();
     });
+
+    it('should handle multiline comments', async () => {
+      const output = await format(
+        createFormatArgs({
+          dictionary: {
+            tokens: commentTokens,
+            allTokens: convertTokenData(commentTokens, { output: 'array' }),
+          },
+          file,
+          platform: {},
+        }),
+      );
+      await expect(output).to.matchSnapshot();
+    });
   });
 });