丶 Limeー来夢 丶
丶 Limeー来夢 丶

Reputation: 947

Convert JavaScript string to JavaScript literal

In Chrome, when you right-click a string on the console, you'll see "copy string as javascript literal" option. This is what I want to have now, in JavaScript.

For example, let's say I have the following text content:

console.log('hoge');

My question is, how can I get something below from the above?

"console.log('hoge');"

I want to do this because, I have a mega bytes of webpack-generated long JavaScript content, and for a reason I need to eval() the script on an other environment, so I want to copy-and-paste the JavaScript literal text to inside the "eval()". (you may suggest exchanging the data not with the literal but with json (json.stringify/parse), I know, but I just prefer the literal way for now)

So is it possible? Thanks.

Upvotes: 4

Views: 2269

Answers (4)

slebetman
slebetman

Reputation: 113984

I have an app for this: https://www.npmjs.com/package/make-it-a-string

You can install it by simply using npm install -g. Yes, I'm abusing npm to distribute apps but npm is the best cross-platform app store/repo I know of.

The code to convert anything to a valid javascript string is very simple. My app is just 15 lines long (see https://github.com/slebetman/make-it-a-string/blob/main/make-it-a-string).

I'm basically just doing this:

const valid_string = JSON.stringify(raw_string,null,4)

Yes, that's JSON.stringify(). I'm abusing the fact that a string is valid JSON. Basically the string:

hello world

Has the JSON representation of:

"hello world"

And JSON.stringify() knows how to add the quotes. As an added bonus, JSON.stringify() also knows how to escape all other things that need escaping.

For example, the string:

hello
"world"

Has the JSON representation of:

"hello\n\"world\""

And again, JSON.stringify() knows how to handle this. All the string encoding you need to convert some random string into a valid js string are fully specified by the JSON standard so JSON.stringify() is in my humble opinion the correct and valid way to encode js strings.

My full code simply uses the clipboardy module to read the text from and then write the formatted text to the clipboard. Here's the full code in case you don't feel like installing it from npm:

async function main () {
    const clipboard = (await import('clipboardy')).default;
    
    function result (x) {
        clipboard.writeSync(x);
        console.log(x);
    }

    let raw = clipboard.readSync(); 
    result(JSON.stringify(raw,null,4));
}

main();

Obviously there's a chicken-and-egg problem here. To get the string you first need it in a js variable. And if it's already in a variable there's no reason to need it as a string. That's the whole reason I read it from the clipboard.

If instead of the clipboard you prefer to process the string from a file you can do it like this:

let raw = fs.readFileSync('my-source-text.js', 'utf8'); 
console.log(JSON.stringify(raw,null,4));

Upvotes: 0

moses
moses

Reputation: 17

It feels like you have done it already. You can write that to a file like so

fs.writeFileSync(file, 
    "console.log('hoge');"
 );

or

fs.writeFileSync(file,
        `
       ${ console.log('hoge')}
        ;`
 )

back ticks are usually for multiline spacing

Upvotes: -1

user14967413
user14967413

Reputation: 1416

You can easily enclose Javascript in backticks to get a template literal:

eval(`console.log('hoge')`)

But you should also escape backticks inside the Javascript code to handle situations like this:

eval(`console.log(`hoge`)`)  // SyntaxError

As a solution, you can use this bash one-liner:

 sed 's/`/\\`/g' | xargs -0 printf 'eval(`%s`)'
  1. Invoke the command by pressing Enter.
  2. Paste in the Javascript you want to escape and press Enter again.
  3. Press Ctrl+D to finish input.
  4. You will get valid eval() function call with escaped template literal on the output.

You can assign this one-liner command to an alias for easy use:

 alias js_eval_literal="sed '"'s/`/\\`/g'"' | xargs -0 printf '"'eval(`%s`)'"'"

Upvotes: -1

Dave Pritlove
Dave Pritlove

Reputation: 2687

After noting the advice regarding the security weakness inherent in using eval (see: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval)

You can achieve what you want by enclosing the entire literal code inside back-ticks and using the resulting string as the eval argument. back tick quotted strings can include line breaks so you should be able to pass your entire code block inside a single set.

Working snippet.

console.log('hoge');
console.log('another hoge');


eval(`console.log('hoge');
console.log('another hoge')`);

Upvotes: 2

Related Questions