Skip to content

Commit 233bb57

Browse files
tinfoil-knighteduardoboucaskodiakhq[bot]
authored
feat: support comments in vscode settings (#5436)
* feat: support comments in vscode settings * refactor: destructure imports * test: add test to check if JSON with comments is handled * fix: remove unnecessary log statement * test: remove .only modifier Co-authored-by: Eduardo Bouças <[email protected]> * refactor: use utf8 encoding in readFile instead of using toString on contents * refactor: import comment-json using a namespace --------- Co-authored-by: Eduardo Bouças <[email protected]> Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
1 parent b44eb25 commit 233bb57

File tree

5 files changed

+117
-7
lines changed

5 files changed

+117
-7
lines changed

npm-shrinkwrap.json

Lines changed: 63 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@
9595
"ci-info": "^3.0.0",
9696
"clean-deep": "^3.0.2",
9797
"commander": "^9.2.0",
98+
"comment-json": "^4.2.3",
9899
"concordance": "^5.0.0",
99100
"configstore": "^5.0.0",
100101
"content-type": "^1.0.4",

src/recipes/vscode/settings.mjs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,18 @@
11
import { mkdir, readFile, stat, writeFile } from 'fs/promises'
22
import { dirname, relative } from 'path'
33

4+
// eslint-disable-next-line import/no-namespace
5+
import * as JSONC from 'comment-json'
46
import unixify from 'unixify'
57

68
export const applySettings = (existingSettings, { denoBinary, edgeFunctionsPath, repositoryRoot }) => {
79
const relativeEdgeFunctionsPath = unixify(relative(repositoryRoot, edgeFunctionsPath))
8-
const settings = {
9-
...existingSettings,
10+
const settings = JSONC.assign(existingSettings, {
1011
'deno.enable': true,
1112
'deno.enablePaths': existingSettings['deno.enablePaths'] || [],
1213
'deno.unstable': true,
1314
'deno.importMap': '.netlify/edge-functions-import-map.json',
14-
}
15+
})
1516

1617
// If the Edge Functions path isn't already in `deno.enabledPaths`, let's add
1718
// it.
@@ -38,11 +39,11 @@ export const getSettings = async (settingsPath) => {
3839
throw new Error(`${settingsPath} is not a valid file.`)
3940
}
4041

41-
const file = await readFile(settingsPath)
42+
const file = await readFile(settingsPath, 'utf8')
4243

4344
return {
4445
fileExists: true,
45-
settings: JSON.parse(file),
46+
settings: JSONC.parse(file),
4647
}
4748
} catch (error) {
4849
if (error.code !== 'ENOENT') {
@@ -57,7 +58,7 @@ export const getSettings = async (settingsPath) => {
5758
}
5859

5960
export const writeSettings = async ({ settings, settingsPath }) => {
60-
const serializedSettings = JSON.stringify(settings, null, 2)
61+
const serializedSettings = JSONC.stringify(settings, null, 2)
6162

6263
await mkdir(dirname(settingsPath), { recursive: true })
6364
await writeFile(settingsPath, serializedSettings)

tests/integration/640.command.recipes.test.cjs

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,12 @@ const { readFile } = require('fs/promises')
22
const { resolve } = require('path')
33

44
const test = require('ava')
5+
const { parse } = require('comment-json')
56
const execa = require('execa')
67

78
const callCli = require('./utils/call-cli.cjs')
89
const cliPath = require('./utils/cli-path.cjs')
9-
const { CONFIRM, answerWithValue, handleQuestions } = require('./utils/handle-questions.cjs')
10+
const { CONFIRM, NO, answerWithValue, handleQuestions } = require('./utils/handle-questions.cjs')
1011
const { withSiteBuilder } = require('./utils/site-builder.cjs')
1112
const { normalize } = require('./utils/snapshots.cjs')
1213

@@ -96,3 +97,45 @@ test('Does not generate a new VS Code settings file if the user does not confirm
9697
t.is(error.code, 'ENOENT')
9798
})
9899
})
100+
101+
test('Handles JSON with comments', async (t) => {
102+
await withSiteBuilder('repo', async (builder) => {
103+
const comment = '// sets value for someSetting'
104+
await builder
105+
.withContentFile({
106+
path: '.vscode/settings.json',
107+
content: `{
108+
"deno.enablePaths":["/some/path"],
109+
"someSetting":"value" ${comment}
110+
}`,
111+
})
112+
.buildAsync()
113+
114+
const childProcess = execa(cliPath, ['recipes', 'vscode'], {
115+
cwd: builder.directory,
116+
})
117+
const settingsPath = resolve(builder.directory, '.vscode', 'settings.json')
118+
119+
handleQuestions(childProcess, [
120+
{
121+
question: `There is a VS Code settings file at ${settingsPath}. Can we update it?`,
122+
answer: answerWithValue(CONFIRM),
123+
},
124+
{
125+
question: 'The Deno VS Code extension is recommended. Would you like to install it now?',
126+
answer: answerWithValue(NO),
127+
},
128+
])
129+
130+
await childProcess
131+
132+
const settingsText = await readFile(`${builder.directory}/.vscode/settings.json`, { encoding: 'utf8' })
133+
t.true(settingsText.includes(comment))
134+
135+
const settings = parse(settingsText, null, true)
136+
t.is(settings.someSetting, 'value')
137+
t.is(settings['deno.enable'], true)
138+
t.is(settings['deno.importMap'], '.netlify/edge-functions-import-map.json')
139+
t.deepEqual([...settings['deno.enablePaths']], ['/some/path', 'netlify/edge-functions'])
140+
})
141+
})

tests/integration/utils/handle-questions.cjs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,12 @@ const answerWithValue = (value) => `${value}${CONFIRM}`
2727

2828
const CONFIRM = '\n'
2929
const DOWN = '\u001B[B'
30+
const NO = 'n'
3031

3132
module.exports = {
3233
handleQuestions,
3334
answerWithValue,
3435
CONFIRM,
3536
DOWN,
37+
NO,
3638
}

0 commit comments

Comments
 (0)