Skip to content

Commit

Permalink
feat: support comments in vscode settings (#5436)
Browse files Browse the repository at this point in the history
* 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 <mail@eduardoboucas.com>

* 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 <mail@eduardoboucas.com>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
  • Loading branch information
3 people committed Feb 9, 2023
1 parent b44eb25 commit 233bb57
Show file tree
Hide file tree
Showing 5 changed files with 117 additions and 7 deletions.
63 changes: 63 additions & 0 deletions npm-shrinkwrap.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@
"ci-info": "^3.0.0",
"clean-deep": "^3.0.2",
"commander": "^9.2.0",
"comment-json": "^4.2.3",
"concordance": "^5.0.0",
"configstore": "^5.0.0",
"content-type": "^1.0.4",
Expand Down
13 changes: 7 additions & 6 deletions src/recipes/vscode/settings.mjs
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
import { mkdir, readFile, stat, writeFile } from 'fs/promises'
import { dirname, relative } from 'path'

// eslint-disable-next-line import/no-namespace
import * as JSONC from 'comment-json'
import unixify from 'unixify'

export const applySettings = (existingSettings, { denoBinary, edgeFunctionsPath, repositoryRoot }) => {
const relativeEdgeFunctionsPath = unixify(relative(repositoryRoot, edgeFunctionsPath))
const settings = {
...existingSettings,
const settings = JSONC.assign(existingSettings, {
'deno.enable': true,
'deno.enablePaths': existingSettings['deno.enablePaths'] || [],
'deno.unstable': true,
'deno.importMap': '.netlify/edge-functions-import-map.json',
}
})

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

const file = await readFile(settingsPath)
const file = await readFile(settingsPath, 'utf8')

return {
fileExists: true,
settings: JSON.parse(file),
settings: JSONC.parse(file),
}
} catch (error) {
if (error.code !== 'ENOENT') {
Expand All @@ -57,7 +58,7 @@ export const getSettings = async (settingsPath) => {
}

export const writeSettings = async ({ settings, settingsPath }) => {
const serializedSettings = JSON.stringify(settings, null, 2)
const serializedSettings = JSONC.stringify(settings, null, 2)

await mkdir(dirname(settingsPath), { recursive: true })
await writeFile(settingsPath, serializedSettings)
Expand Down
45 changes: 44 additions & 1 deletion tests/integration/640.command.recipes.test.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@ const { readFile } = require('fs/promises')
const { resolve } = require('path')

const test = require('ava')
const { parse } = require('comment-json')
const execa = require('execa')

const callCli = require('./utils/call-cli.cjs')
const cliPath = require('./utils/cli-path.cjs')
const { CONFIRM, answerWithValue, handleQuestions } = require('./utils/handle-questions.cjs')
const { CONFIRM, NO, answerWithValue, handleQuestions } = require('./utils/handle-questions.cjs')
const { withSiteBuilder } = require('./utils/site-builder.cjs')
const { normalize } = require('./utils/snapshots.cjs')

Expand Down Expand Up @@ -96,3 +97,45 @@ test('Does not generate a new VS Code settings file if the user does not confirm
t.is(error.code, 'ENOENT')
})
})

test('Handles JSON with comments', async (t) => {
await withSiteBuilder('repo', async (builder) => {
const comment = '// sets value for someSetting'
await builder
.withContentFile({
path: '.vscode/settings.json',
content: `{
"deno.enablePaths":["/some/path"],
"someSetting":"value" ${comment}
}`,
})
.buildAsync()

const childProcess = execa(cliPath, ['recipes', 'vscode'], {
cwd: builder.directory,
})
const settingsPath = resolve(builder.directory, '.vscode', 'settings.json')

handleQuestions(childProcess, [
{
question: `There is a VS Code settings file at ${settingsPath}. Can we update it?`,
answer: answerWithValue(CONFIRM),
},
{
question: 'The Deno VS Code extension is recommended. Would you like to install it now?',
answer: answerWithValue(NO),
},
])

await childProcess

const settingsText = await readFile(`${builder.directory}/.vscode/settings.json`, { encoding: 'utf8' })
t.true(settingsText.includes(comment))

const settings = parse(settingsText, null, true)
t.is(settings.someSetting, 'value')
t.is(settings['deno.enable'], true)
t.is(settings['deno.importMap'], '.netlify/edge-functions-import-map.json')
t.deepEqual([...settings['deno.enablePaths']], ['/some/path', 'netlify/edge-functions'])
})
})
2 changes: 2 additions & 0 deletions tests/integration/utils/handle-questions.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,12 @@ const answerWithValue = (value) => `${value}${CONFIRM}`

const CONFIRM = '\n'
const DOWN = '\u001B[B'
const NO = 'n'

module.exports = {
handleQuestions,
answerWithValue,
CONFIRM,
DOWN,
NO,
}

0 comments on commit 233bb57

Please sign in to comment.