diff --git a/packages/bruno-lang/v2/src/bruToJson.js b/packages/bruno-lang/v2/src/bruToJson.js index c84d36d07..ad39185a7 100644 --- a/packages/bruno-lang/v2/src/bruToJson.js +++ b/packages/bruno-lang/v2/src/bruToJson.js @@ -43,8 +43,14 @@ const grammar = ohm.grammar(`Bru { // Dictionary Blocks dictionary = st* "{" pairlist? tagend pairlist = optionalnl* pair (~tagend stnl* pair)* (~tagend space)* - pair = st* key st* ":" st* value st* - key = keychar* + pair = st* (quoted_key | key) st* ":" st* value st* + disable_char = "~" + quote_char = "\\"" + esc_char = "\\\\" + esc_quote_char = esc_char quote_char + quoted_key_char = ~(quote_char | esc_quote_char | nl) any + quoted_key = disable_char? quote_char (esc_quote_char | quoted_key_char)* quote_char + key = keychar+ value = multilinetextblock | valuechar* // Dictionary for Assert Block @@ -213,6 +219,14 @@ const sem = grammar.createSemantics().addAttribute('ast', { res[key.ast] = value.ast ? value.ast.trim() : ''; return res; }, + esc_quote_char(_1, quote) { + // unescape + return quote.sourceString; + }, + quoted_key(disabled, _1, chars, _2) { + // unquote + return (disabled? disabled.sourceString : "") + chars.ast.join(""); + }, key(chars) { return chars.sourceString ? chars.sourceString.trim() : ''; }, @@ -264,6 +278,9 @@ const sem = grammar.createSemantics().addAttribute('ast', { tagend(_1, _2) { return ''; }, + _terminal(){ + return this.sourceString; + }, _iter(...elements) { return elements.map((e) => e.ast); }, diff --git a/packages/bruno-lang/v2/src/jsonToBru.js b/packages/bruno-lang/v2/src/jsonToBru.js index 8d3a5fdee..a8e2f1cd6 100644 --- a/packages/bruno-lang/v2/src/jsonToBru.js +++ b/packages/bruno-lang/v2/src/jsonToBru.js @@ -4,6 +4,10 @@ const { indentString } = require('../../v1/src/utils'); const enabled = (items = []) => items.filter((item) => item.enabled); const disabled = (items = []) => items.filter((item) => !item.enabled); +const quoteKey = (key) => { + const quotableChars = [':', '"', '{', '}', ' ']; + return quotableChars.some(char => key.includes(char)) ? ('"' + key.replaceAll('"', '\\"') + '"') : key; +} // remove the last line if two new lines are found const stripLastLine = (text) => { @@ -71,7 +75,7 @@ const jsonToBru = (json) => { if (enabled(queryParams).length) { bru += `\n${indentString( enabled(queryParams) - .map((item) => `${item.name}: ${item.value}`) + .map((item) => `${quoteKey(item.name)}: ${item.value}`) .join('\n') )}`; } @@ -79,7 +83,7 @@ const jsonToBru = (json) => { if (disabled(queryParams).length) { bru += `\n${indentString( disabled(queryParams) - .map((item) => `~${item.name}: ${item.value}`) + .map((item) => `~${quoteKey(item.name)}: ${item.value}`) .join('\n') )}`; } diff --git a/packages/bruno-lang/v2/tests/fixtures/request.bru b/packages/bruno-lang/v2/tests/fixtures/request.bru index 1a3efeab7..058297c36 100644 --- a/packages/bruno-lang/v2/tests/fixtures/request.bru +++ b/packages/bruno-lang/v2/tests/fixtures/request.bru @@ -13,6 +13,9 @@ get { params:query { apiKey: secret numbers: 998877665 + "colon:parameter": is allowed + "nested escaped \"quote\"": is allowed + ~"disabled:colon:parameter": is allowed ~message: hello } diff --git a/packages/bruno-lang/v2/tests/fixtures/request.json b/packages/bruno-lang/v2/tests/fixtures/request.json index 24997a90c..9c6ea5bcf 100644 --- a/packages/bruno-lang/v2/tests/fixtures/request.json +++ b/packages/bruno-lang/v2/tests/fixtures/request.json @@ -23,6 +23,24 @@ "type": "query", "enabled": true }, + { + "name" : "colon:parameter", + "value" : "is allowed", + "type": "query", + "enabled": true + }, + { + "name" : "nested escaped \"quote\"", + "value" : "is allowed", + "type": "query", + "enabled": true + }, + { + "name" : "disabled:colon:parameter", + "value" : "is allowed", + "type": "query", + "enabled": false + }, { "name": "message", "value": "hello",