Javascriptヒアドキュメント


109

JavaScriptのヒアドキュメントのようなものが必要です。これについて何かアイデアはありますか?クロスブラウザ機能が必要です。

私はこれを見つけました:

heredoc = '\
<div>\
    <ul>\
        <li><a href="#zzz">zzz</a></li>\
    </ul>\
</div>';

うまくいくと思います。:)


6
stackoverflow.com/questions/805107/…の複製で、より詳細な回答がいくつかあります。
チャドウィック、

4
「\」を追加する必要があるため、毎回不満を感じます。Imho、複数行文字列の通常の構文がないことは完全に正当化されていません。また、どのバージョンでも追加できたはずですが、追加できませんでした。
Lex


現在、これは、可能な複製に示されているように、テンプレートリテラルを使用して行われます(ここでは更新された回答はありません)。
ブラソフィロ2018

回答:


77

ES6文字列テンプレートをお試しください。次のようなことができます

var hereDoc = `
This
is
a
Multiple
Line
String
`.trim()


hereDoc == 'This\nis\na\nMultiple\nLine\nString'

=> true

6to5またはTypeScriptを使用して、この優れた機能を今日使用できます


2
これは、複数行の文字列が必要な場合にのみ当てはまります。ただし、文字列を囲む記号は実際には変更できないため、実際にはヒアドキュメントではありません。
Peeyush Kushwaha 16

3
ちょうどメモとして、元の質問はES6が利用可能になる5年前に尋ねられました。パフォーマンスも向上しているため、これは今後のベストプラクティスです。
Henry Tseng

2
@HenryTseng、あなたはこの質問への答えが5年前に存在していた古代の技術に合わせて調整されるべきだと提案していますか?問題が未解決の場合は、時間の経過とともに作成された新しいテクノロジーを利用する価値があります。このようにして、同じ問題を抱えている新しいユーザーは、「考古学的でない」情報をここで見つけることができます。
asiby 2018年

1
いいえ、その解決策が以前はそれほど目立たなかった理由についてコメントしていました。互換性の問題がない場合は、サポートされている方法で進められることは間違いありません。
Henry Tseng 2018年

63

いいえ、残念ながらJavaScriptはヒアドキュメントのようなものをサポートしていません。


12
私は知っていますが、ヒアドキュメントのハックを見つけたいと思います:)
VeroLom

解析関数のコメントのようなもの(ただし、ie / firefoxでは機能しません)=
VeroLom

37

これはどう:

function MyHereDoc(){
/*HERE
<div>
   <p>
      This is written in the HEREDOC, notice the multilines :D.
   </p>
   <p>
      HERE
   </p>
   <p>
      And Here
   </p>
</div>
HERE*/
    var here = "HERE";
    var reobj = new RegExp("/\\*"+here+"\\n[\\s\\S]*?\\n"+here+"\\*/", "m");
    str = reobj.exec(MyHereDoc).toString();
    str = str.replace(new RegExp("/\\*"+here+"\\n",'m'),'').toString();
    return str.replace(new RegExp("\\n"+here+"\\*/",'m'),'').toString();
}

//Usage 
document.write(MyHereDoc());

"/ * HERE"と "HERE * /"を選択した単語に置き換えるだけです。


4
すべてのブラウザ/エンジンがFunction.toString()でコメントを返しますか?それは非常に賢い
gcb 2013年

Chromeのコンソールで動作
2013

4
*/ヒアドキュメントに終了コメントがある場合は機能しません。
Narigo

2
ネイトフェレーロの回答は、より洗練され最適化された例であるため、使用することをお勧めします。Mineは3つの個別のregEx呼び出しを使用しており、概念実証に適しています。
Zv_oDD 2014年

1
非常に賢いです...しかし、あなたがそれが将来うまくいくことを保証することはできません。これは、実装に依存しすぎているため、良い方法とは言えません。
Pierre-Olivier Vares

33

Zv_oDDの答えに基づいて、再利用を容易にするために同様の関数を作成しました。

警告:これは多くのJSインタープリターの非標準機能であり、おそらくいつかは削除されるでしょうが、私はChromeでのみ使用されるスクリプトを作成しているので、それを使用しています!クライアント向けWebサイトでこれに依存しないください。

// Multiline Function String - Nate Ferrero - Public Domain
function heredoc(fn) {
  return fn.toString().match(/\/\*\s*([\s\S]*?)\s*\*\//m)[1];
};

使用する:

var txt = heredoc(function () {/*
A test of horrible
Multi-line strings!
*/});

戻り値:

"A test of horrible
Multi-line strings!"

ノート:

  1. テキストは両端でトリミングされるため、両端の余分な空白は問題ありません。

編集:

2014年2月2日-Functionプロトタイプをまったく使用しないように変更され、代わりにheredocという名前を使用。

2017年5月26日-最新のコーディング標準を反映するように空白を更新


1
私はhereDoc()を関数名として使用しましたが、このコードは私の40k行の
ログダンプを

なぜ関数のインスタンスを作成し、非推奨のプロパティ__ proto __にアクセスするのですか?なぜFunction.prototype.str = function(){...}をしないのですか?
John

@JohnKurlakはもっと良いです!答えを書いたときにそれが可能だったとは思いませんでした。
ネイトフェレーロ2014

2
@NateFerrero-素晴らしい答え、ありがとう!独自の拡張機能を別の回答として追加しました。
Andrew Cheong

私のAndroid、5.0.1を実行しているNexus 4では、Chromeでは動作しません。何らかの理由で、空白とコメントを削除しています。これが設定かどうかはわかりませんが、クライアント側のものです。回避策のアイデアはありますか?
MLU、2014

19

実行しているJS / JSエンジンの種類(SpiderMonkey、AS3)に応じて、ヒアドキュメントのように、テキストを複数行に配置できるインラインXMLを簡単に記述できます。

var xml = <xml>
    Here 
    is 
    some 
    multiline 
    text!
</xml>

console.log(xml.toXMLString())
console.log(xml.toString()) // just gets the content

13

ES6 テンプレート文字列には、ヒアドキュメント機能があります。

バックティック( ``)で囲まれた文字列を宣言し、複数行で展開できます。

var str = `This is my template string...
and is working across lines`;

テンプレート文字列内に式を含めることもできます。これらは、ドル記号と中括弧(${expression})で示されます。

var js = "Java Script";
var des = `Template strings can now be used in ${js} with lot of additional features`;

console.log(des); //"Template strings can now be used in Java Script with lot of additional features"

実際には、タグ付きのテンプル文字列や生の文字列など、より多くの機能があります。ドキュメントは次の場所にあります

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/template_strings


8

@NateFerreroの回答を単に拡張しただけで別の回答を書くのは気分が悪いですが、彼の回答を編集するのも適切だとは思いません。

tl; dr-ヒアドキュメント内でブロックコメントを使用する場合...

私は主にCSSのブロックを保存するためにJavaScriptのヒアドキュメントを必要としました、例えば

var css = heredoc(function() {/*
    /**
     * Nuke rounded corners.
     */
    body div {
        border-top-left-radius: 0 !important;
        border-top-right-radius: 0 !important;
        border-bottom-right-radius: 0 !important;
        border-bottom-left-radius: 0 !important;
    }
*/});

ただし、ご覧のとおり、私はCSSにコメントを付けたいのですが、残念ながら(構文の強調表示が示唆するように)最初の*/コメントはコメント全体を終了させて​​、ヒアドキュメントを壊します。


この特定の目的(CSS)の場合、私の回避策は

.replace(/(\/\*[\s\S]*?\*) \//g, '$1/')

@NateFerrero内のチェーンにheredoc; 完全な形で:

function heredoc (f) {
    return f.toString().match(/\/\*\s*([\s\S]*?)\s*\*\//m)[1].replace(/(\/\*[\s\S]*?\*) \//g, '$1/');
};

そして、の間のスペース追加することによって、それを使用*し、/そのような「インナー」ブロックコメント、のために:

var css = heredoc(function() {/*
    /**
     * Nuke rounded corners.
     * /
    body div {
        border-top-left-radius: 0 !important;
        border-top-right-radius: 0 !important;
        border-bottom-right-radius: 0 !important;
        border-bottom-left-radius: 0 !important;
    }
*/});

はmakeするスペースをreplace見つけ/* ... * /て削除するだけで/* ... */、呼び出されるまでヘレドックを保持します。


もちろん、コメントを完全に削除することができます

.replace(/\/\*[\s\S]*?\* \//g, '')

//チェーンにコメントを追加すると、コメントをサポートすることもできます。

.replace(/^\s*\/\/.*$/mg, '')

また、次のように、*との間の単一のスペース以外のものを実行できます。/-

    /**
     * Nuke rounded corners.
     *-/

正規表現を適切に更新するだけの場合:

.replace(/(\/\*[\s\S]*?\*)-\//g, '$1/')
                          ^

それとも、単一のスペースではなく、任意の量の空白が必要ですか?

.replace(/(\/\*[\s\S]*?\*)\s+\//g, '$1/')
                          ^^^

2
涼しい!それは私の方法の既知の制限でした、私はそれが好きです:)
Nate Ferrero

8

JavaScriptにコンパイルされる言語であるCoffeeScriptを使用できます。コードは1対1で同等のJSにコンパイルされ、実行時には解釈されません。

そしてもちろん、それはヒアドキュメントを持っています:)


24
正解は「いいえ」です。CoffeeScriptとEJSを提案として使用できます。
alvincrespo 2011

4
CoffeeScriptは、私が遭遇したほとんどのJS問題に対する正解です。ほんのわずかな量のJSを書く(そしてあなたが時間とエネルギーを大切にする)場合、それを使用するのは自分自身の責任です。
ブランドン、

5
これは、javascriptでheredocがないことを回避する簡単な方法を提供するので、良い答えだと思います。多くの時間を節約できました。
Stofke

3
jsのチャンクが必要なだけで、実際の書き込みに対応したくない場合は、coffeescript.orgで、[Try Coffeescript]ボタンを使用してください。
jcollum 2013年

1
これは、基本的には「いいえ」である最高評価の回答よりも多くの回答です。そういう答えは嫌いです。
Matt Fletcher

7

ES5以前のバージョン

(function(){/**
some random
multi line
text here
**/}).toString().slice(15,-5);

ES6以降のバージョン

`some random
multi line
text here`

結果

some random
multi line
text here

ベストシンプルな回答
ベンジャミン

1
古いスタイルのものは信じられないほど残忍なハックです:/
Shayne

1

この投稿でTim Disneyが作成したように、Sweet.jsマクロを使用して追加できます。

このアプローチでは、代わりに文字列区切り文字としてバックティックを使用しています。

let str = macro {
    case {_ $template } => {
        var temp = #{$template}[0];
        var tempString = temp.token.value.raw;
        letstx $newTemp = [makeValue(tempString, #{here})];
        return #{$newTemp}
    }
}

str `foo bar baz`

1

他の人が言ったように、ES6テンプレート文字列は、従来のヒアドキュメントが提供するもののほとんどを提供します。

さらに一歩進んでタグ付きテンプレート文字列theredocを使用したい場合は、これを実行できる便利なユーティリティ関数です。

if (yourCodeIsIndented) {
  console.log(theredoc`
    Theredoc will strip the
    same amount of indentation
    from each line.

      You can still indent
      further if you want.

    It will also chop off the
    whitespace-only first and
    last lines.
  `)
}

0

手元にhtmlとjQueryがあり、文字列が有効なHTMLである場合、これは便利です。

<div id="heredoc"><!--heredoc content
with multiple lines, even 'quotes' or "double quotes",
beware not to leave any tag open--></div>
<script>
var str = (function() {
   var div = jQuery('#heredoc');
   var str = div.html();
   str = str.replace(/^<\!--/, "").toString();
   str = str.replace(/-->$/, "").toString();
   return str;
})();
</script>

テキストの間にコメント「<!-->」が含まれている場合も同様に機能しますが、テキストの一部が表示される場合があります。これがフィドルです:https : //jsfiddle.net/hr6ar152/1/


0
// js heredoc - http://stackoverflow.com/a/32915549/466363
// a function with comment with eval-able string, use it just like regular string

function extractFuncCommentString(func,comments) {
  var matches = func.toString().match(/function\s*\(\)\s*\{\s*\/\*\!?\s*([\s\S]+?)\s*\*\/\s*\}/);
  if (!matches) return undefined;
  var str=matches[1];

   // i have made few flavors of comment removal add yours if you need something special, copy replacement lines from examples below, mix them
  if(comments===1 )
  {
   // keep comments, in order to keep comments  you need to convert /**/ to / * * / to be able to put them inside /**/ like /*    / * * /    */
   return (
    str
   .replace(/\/\s\*([\s\S]*?)\*\s\//g,"/*$1*/") //       change   / * text * /  to   /* text */ 
   )
  }
  else if(comments===2)
  {
   // keep comments and replace singleline comment to multiline comment
   return (
    str
   .replace(/\/\s\*([\s\S]*?)\*\s\//g,"/*$1*/") //       change   / * text * /  to   /* text */ 
   .replace(/\/\/(.*)/g,"/*$1*/")          //           change   //abc to  /*abc*/
   )
  }
  else if(comments===3)
  {
   // remove comments
   return (
      str
      .replace(/\/\s\*([\s\S]*?)\*\s\//g,"") //       match / * abc * /
      .replace(/\/\/(.*)/g,"")             // match //abc
     )
  }
  else if(comments===4)
  {
   // remove comments and trim and replace new lines with escape codes
   return (
      str
      .replace(/\/\s\*([\s\S]*?)\*\s\//g,"") //       match / * abc * /
      .replace(/\/\/(.*)/g,"")             // match //abc
      .trim() // after removing comments trim and:
      .replace(/\n/g,'\\n').replace(/\r/g,'\\r') // replace new lines with escape codes. allows further eval() of the string, you put in the comment function: a quoted text but with new lines
     )
  }
  else if(comments===5)
  {
   // keep comments comments and replace strings, might not suit when there are spaces or comments before and after quotes 
   // no comments allowed before quotes of the string
   return (
      str
      .replace(/\/\s\*([\s\S]*?)\*\s\//g,"/*$1*/") //       change   / * text * /  to   /* text */
      .replace(/\/\/(.*)/g,"/*$1*/")          //           change   //abc to  /*abc*/
      .trim() // trim space around quotes to not escape it and:
      .replace(/\n/g,'\\n').replace(/\r/g,'\\r') // replace new lines with escape codes. allows further eval() of the string, you put in the comment function: a quoted text but with new lines
     )
  }
  else 
  return str
}

var week=true,b=123;
var q = eval(extractFuncCommentString(function(){/*!

// this is a comment     


'select 

/ * this
is a multiline 
comment * /

 a
,b  // this is a comment  
,c
from `table`
where b='+b+' and monthweek="'+(week?'w':'m')+'" 
//+' where  a=124
order by a asc
'
*/},4));

キャッシュ付き:-単純なテンプレート関数を作成し、関数を保存します(2回目は高速に動作します)。

var myfunction_sql1;
function myfunction(week,a){


    if(!myfunction_sql1) eval('myfunction_sql1=function(week,a){return ('+extractFuncCommentString(function(){/*!
'select 

/ * this
is a multiline 
comment * /

 a
,b  // this is a comment  
,c
from `table`
where b='+b+' and monthweek="'+(week?'w':'m')+'" 
//+' where  a=124
order by a asc

'*/},4)+')}');
    q=myfunction_sql1(week,a);
    console.log(q)
}
myfunction(true,1234)

1
FFとChromeではまったく異なる結果が得られます。
Dave Newton

何が違うの?ChromeとFFでテストしたところ、まったく同じ結果が得られました。ただし、Chromeでは、var名を入力するだけでChromeのコンソールに改行はありません。しかし、変数は同じです。console.log()で改行して印刷することが可能です
Shimon Doodkin

0

私はこのバージョンを投稿しています。これは、非常に些細なことに対する正規表現の使用を回避するためです。

IMHO regexは、perl開発者の間の実用的な冗談として作成された難読化です。コミュニティの残りの人々はそれらを真剣に受け止め、数十年後、私たちは現在代価を払っています。レガシーコードとの後方互換性を除いて、正規表現を使用しないでください。最近では、すぐには人間が読めない、理解できないコードを書く言い訳はありません。正規表現は、すべてのレベルでこの原則に違反しています。

結果を現在のページに追加する方法も追加しました。これは要求されたものではありません。

function pretty_css () {
/*
    pre { color: blue; }

*/
}
function css_src (css_fn) {
   var css = css_fn.toString();
   css = css.substr(css.indexOf("/*")+2);
   return css.substr(0,css.lastIndexOf("*/")).trim();
}

function addCss(rule) {
  let css = document.createElement('style');
  css.type = 'text/css';
  if (css.styleSheet) css.styleSheet.cssText = rule; // Support for IE
  else css.appendChild(document.createTextNode(rule)); // Support for the rest
  document.getElementsByTagName("head")[0].appendChild(css);
}

addCss(css_src(pretty_css));

document.querySelector("pre").innerHTML=css_src(pretty_css);
<pre></pre>

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.