Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Is it possible to insert a comment after a value? #38

Open
blhoward2 opened this issue Oct 8, 2022 · 3 comments
Open

Is it possible to insert a comment after a value? #38

blhoward2 opened this issue Oct 8, 2022 · 3 comments

Comments

@blhoward2
Copy link

After a json has been parsed, is it possible to insert a new comment that will then be retained? If so, how? I'm pulling my hair out...

@psulek
Copy link

psulek commented Apr 6, 2023

I am also curious about this. Also i want to know how to add comments when building json object at runtime (not loading/parsing).

So for example i have this code:

const {stringify} = require('comment-json');
let obj = { name: "peter"; age: 20; };
// TODO: how to add comment before property "name" here before calling stringify ?
const str = stringify(obj);

@psulek
Copy link

psulek commented Apr 6, 2023

@blhoward2 @kaelzhang I found a wacky way to do this (ugly but working):

obj[Symbol.for('before:name')] = [{type: 'LineComment', inline: false, value: 'my custom comment'}];

will stringify to:

{ 
  // my custom comment
  name: "peter"; 
  age: 20; 
};

@HanYangZhao
Copy link

I have a similar use case but the comment i wanted for entries in a list

I have this

{
    "members": [
        "user1", // comment
        "user2"  // comment2
    ]
}

And I want to have this

{
    "members": [
        "user1",   // comment
        "user2",  // comment2
        "user3"  // comment3
    ]
}

I wrote the following code

const {
  parse,
  stringify
} = require('comment-json')
const fs = require('fs')
const { inspect } = require('util')

const findMembersLineNumber = (filePath, groupName) => {
  const fileContent = fs.readFileSync(filePath, { encoding: 'utf-8' })
  const lines = fileContent.split(/\r?\n/)
  let isWithinTargetBlock = false

  for (let i = 0; i < lines.length; i++) {
    const line = lines[i]
    if (line.includes(`"${groupName}"`)) {
      isWithinTargetBlock = true
    }
    if (isWithinTargetBlock && line.includes('"members"')) {
      const leadingWhitespace = line.match(/^\s*/)[0]
      const whitespaceCount = leadingWhitespace.length
      // console.log(`Number of leading whitespace characters: ${whitespaceCount}`)
      // console.log(`Line number of "members" under "${groupName}": ${i + 1}`)
      return { lineNumber: i + 1, whitespaceCount }
    }
  }
}
const appendMember = (obj, valueToAdd = null, comment = null, lineNumberObj) => {
  if (valueToAdd) {
    const members = obj.members
    const memberKey = 'after:' + (members.length)
    const newSymbol = Symbol(memberKey)
    members.push(valueToAdd)
    members[newSymbol] = [
      {
        type: 'LineComment',
        value: comment,
        loc: {
          start: { line: lineNumberObj.lineNumber + members.length, column: lineNumberObj.whitespaceCount + 3 + valueToAdd.length + 5 },
          end: { line: lineNumberObj.lineNumber + members.length, column: lineNumberObj.whitespaceCount + 3 + valueToAdd.length + 5 + comment.length + 2 }
        },
        inline: true
      }
    ]
  }
  return obj
}

parse(fs.readFileSync('test.jsonc').toString(), null, true)
const obj = parse(fs.readFileSync('test.jsonc').toString())
const startingLineNumber = findMembersLineNumber('test.jsonc', 'members')
const modifiedObj = appendMember(obj, 'user3', ' comment3', startingLineNumber)

const hidden = (
  inspect(modifiedObj, {
    showHidden: true,
    depth: 10
  })
)
console.log(hidden)
const output = stringify(modifiedObj, null, 2)
console.log(output)

I used util.inspect to looks at the object, which looked correct to me.

{
  members: CommentArray(3) [
    'user1',
    'user2',
    'user3',
    [length]: 3,
    [Symbol(after:0)]: [
      {
        type: 'LineComment',
        value: ' comment',
        loc: {
          start: { line: 3, column: 17 },
          end: { line: 3, column: 27 }
        },
        inline: true
      },
      [length]: 1
    ],
    [Symbol(after:1)]: [
      {
        type: 'LineComment',
        value: ' comment2',
        loc: {
          start: { line: 4, column: 17 },
          end: { line: 4, column: 28 }
        },
        inline: true
      },
      [length]: 1
    ],
    [Symbol(after:2)]: [
      {
        type: 'LineComment',
        value: ' comment3',
        loc: {
          start: { line: 5, column: 17 },
          end: { line: 5, column: 28 }
        },
        inline: true
      },
      [length]: 1
    ]
  ]
}

But the output from stringify didn't have the new comment.

{
  "members": [
    "user1", // comment
    "user2", // comment2
    "user3"
  ]
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants