In my Node.js project, I've defined a script:
{
"scripts": {
"fix:formatting-translation": "ts-node -O '{\"module\": \"commonjs\"}' tools/sortTranslation.ts"
}
}
This will work under Linux, but Windows (where the command shell is used), I'll receive the following error:
undefined:1
'{module:
^
SyntaxError: Unexpected token ''', "'{module:" is not valid JSON
So, the '
causes an error. Additionally, the error messages suggests that module
isn't quoted anymore. Replacing them with \"
(as remotely suggested here) won't work either:
undefined:1
{module: commonjs}
^
SyntaxError: Expected property name or '}' in JSON at position 1
But it might be a step in the correct direction, since - for all I can tell - now it's complaining about the unquoted module
.
How can I pass this JSON object to ts-node
properly? Is there a way with an ASCII sequence instead of a "
? Ideally, the solution would work with the bash
as well.
There can be used on Windows:
{
"scripts": {
"fix:formatting-translation": "ts-node -O {\\\"module\\\":\\\"commonjs\\\"} tools/sortTranslation.ts"
}
}
The character "
must be escaped in a JSON string which is the reason why "module"
must be written as \"module\"
and "commonjs"
as \"commonjs\"
.
The shell interpreters on Linux/Mac like bash
support multiple types of quoting a string to pass as argument to an executable. An argument string in '
is interpreted literally without expanding variable references, doing a shell parameter expansion, or interpreting a backlash as escape character. A string enclosed in '
cannot contain for that reason the character '
, not even with a preceding backslash, because of the backslash is interpreted literally and the following '
is interpreted as end of the argument string enclosed in '
.
The Windows Command Procssor cmd.exe
supports only one type of quoting an argument string. An argument string enclosed in "
is interpreted literally with two exceptions:
%
inside the double quoted argument string is interpreted as beginning/end of an environment/dynamic variable reference, or as loop variable reference inside a FOR loop, or as batch file argument reference on processing a batch file.!
inside the double quoted argument string is interpreted as beginning/end of an environment/dynamic variable reference on enabled delayed variable expansion.It is not possible to define an argument string enclosed in "
for interpreting literally a space and other ASCII characters which special meaning for cmd
like &(){}^=;!'+,`~<>|
depending on context which contains itself "
. There is no possibility to escape the double quote inside a double quoted argument string.
The character '
cannot be used to quote the string as argument string as cmd
interprets them in this context as literal character and pass both '
further to the executable.
These are the main problems on JSON data should be passed as one argument string to an executable because of strings in JSON formatted data must be enclosed in "
, but there is no '
quoting possible with cmd.exe
.
The solution is escaping each double quote character of the JSON data with a backslash. It is necessary in this case to escape each escaping backlash with one more backslash because of the string to pass finally to ts-node
is itself defined in JSON format on which parsing a backslash character is interpreted as escape character, except after an escaping backlash.
The solution is therefore the definition of the JSON data to pass to ts-node
within a JSON formatted data block with \\\"
for each double quote in the JSON data string.
But there is one more problem to solve. ts-node
splits up a command line string passed to it with interpreting a space as argument string separator on not being enclosed in quotes. It is not possible for that reason to use:
"fix:formatting-translation": "ts-node -O {\\\"module\\\": \\\"commonjs\\\"} tools/sortTranslation.ts"
The space character after the colon lets ts-node
interpret the command line finally as series of following arguments:
-O
{"module":
"commonjs"}
tools/sortTranslation.ts
That is of course incorrect because of the second argument string is not anymore a valid json compilerOption.
But the space after the colon is just for better readability. The JSON format itself does not require a space character after the colon which must be between the name and the value. It can be omitted here which solves the problem.
The solution is:
"fix:formatting-translation": "ts-node -O {\\\"module\\\":\\\"commonjs\\\"} tools/sortTranslation.ts"
ts-node
interprets the command line string now finally as series of following argument strings:
-O
{"module":"commonjs"}
tools/sortTranslation.ts