Javascript Heredoc


109

我需要JavaScript中的Heredoc之类的东西。您对此有什么想法吗?我需要跨浏览器功能。

我找到了这个:

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

我认为它将为我工作。:)


6
stackoverflow.com/questions/805107/…重复,其中包含一些更详细的答案。
查德威克

4
必须加上“ \”使我每次皱眉。恕我直言,没有多行字符串的常规语法是完全没有道理的。他们可以在任何给定版本中添加它,但没有添加。
Lex 2014年


如今,这是通过模板文字完成的,如可能的重复所示(此处没有更新的答案)。
brasofilo

Answers:


77

尝试使用ES6字符串模板,您可以执行以下操作

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


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

=> true

您现在可以通过6to5TypeScript使用此强大功能


2
如果您只需要多行字符串,则此方法适用。但是,由于您不能真正更改包围字符串的符号,因此并不是真正的heredoc。
Peeyush Kushwaha

3
仅作说明,最初的问题是在5年前ES6推出之前提出的。这是前进的最佳实践,因为性能也更好。
曾亨利

2
@HenryTseng,您是否建议对这个问题的答案应适合5年前存在的古老技术?如果问题仍然悬而未决,那么当新技术随着时间的推移而产生时,就应该利用这些新技术。这样,具有相同问题的新用户可以在此处找到“非考古”信息。
asiby

1
不,我是在评论为什么该解决方案没有在以前更加突出。如果没有任何兼容性问题,肯定看起来像是受支持的方法。
曾亨利


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

可在Chrome浏览器的控制台中运行
Omn 2013年

4
如果您*/的Heredoc中有结束语,将无法使用。
Narigo 2014年

2
我建议使用内特·费雷罗(Nate Ferrero)的答案,因为他是一个更完善和优化的示例。我的使用3个单独的regEx调用,并且更多是概念证明。
2014年

1
非常聪明...但是您不能保证它会在将来使用。它太依赖于实现而不是一个好的实践。
Pierre-Olivier Vares

33

基于Zv_oDD的答案,我创建了一个类似的函数来简化重用。

警告:这是许多JS解释器的非标准功能,可能会在某些时候被删除,但是由于我正在构建仅在Chrome中使用的脚本,因此我正在使用它!永远不要依赖于面向客户的网站!

// 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这个名称。

5/26/2017-更新了空白以反映现代编码标准。


1
我将hereDoc()用作函数名称,但是此代码可以很好地将我的40k行日志转储加载到Chrome控制台的一个变量中
Omn

为什么要创建一个函数实例并访问不推荐使用的属性__ proto __?为什么不只是Function.prototype.str = function(){...}?
John Kurlak 2014年

@JohnKurlak更好!我认为我写答案时并没有意识到这是可能的。
内特·费雷罗

2
@NateFerrero-很棒的答案,谢谢!添加了我自己的扩展作为单独的答案。
Andrew Cheong

在运行5.0.1的Android nexus 4上,该功能不再适用于Chrome。由于某种原因,它正在删除空格和注释。我不知道这是否是设置,但肯定是在客户端。有任何解决方法的想法吗?
MLU 2014年

19

根据您所运行的JS / JS引擎的风格(SpiderMonkey,AS3),您可以简单地编写内联XML,并可以将文本放在多行中,例如heredoc:

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

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

13

ES6 模板字符串具有heredoc功能。

您可以声明反引号(`)括起来的字符串,并且可以通过多行扩展。

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/zh-CN/docs/Web/JavaScript/Reference/template_strings


8

对于仅扩展@NateFerrero的答案,我写一个单独的答案感到很遗憾,但是我也不认为编辑他的答案也很合适,所以如果此答案对您有用,请投票@NateFerrero。

tl; dr-对于那些希望其Heredoc中使用块注释的人...

我主要需要Javascript heredocs来存储CSS块,例如

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进行注释,但不幸的是(如语法突出显示所示),第一个*/注释结束了整个注释,破坏了Heredoc。


为此,我的解决方法是添加

.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;
    }
*/});

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 2014年

8

您可以使用CoffeeScript,这是一种可编译为JavaScript的语言。该代码一对一地编译成等效的JS,并且在运行时没有解释。

当然,它具有heredocs :)


24
正确答案为否。CoffeeScript和EJS可以用作建议。
alvincrespo 2011年

4
CoffeeScript是我遇到的大多数JS问题的正确答案。如果您编写的JS数量不多(并且您珍惜时间和精力),则应归功于自己的使用。
布兰登

5
我认为这是一个很好的答案,因为它提供了一种简单的方法来避免在JavaScript中缺少Heredoc。节省了我很多时间。
Stofke

3
如果您只想要一堆 js,但不想处理实际编写的js,请使用:coffeescript.org并使用“尝试Coffeescript”按钮。
jcollum 2013年

1
这比最高评分的答案更重要,后者基本上只是...“否”。我讨厌那种答案。
马特·弗莱彻

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

您可以使用Sweet.js Macros来添加它,就像蒂姆·迪斯尼在本文中创建的那样

请注意,此方法改用反引号作为字符串定界符:

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模板字符串为您提供了传统的Heredocs提供的大多数功能。

如果您想更进一步并使用带标签的模板字符串,那么它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));

带缓存:-制作一个简单的模板函数,然后保存该函数:(第二次工作很快)

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,在Chrome的控制台中没有换行符(如果您输入var名称)。但变量是相同的。它可以打印与换行符与CONSOLE.LOG()
西蒙Doodkin

0

我发布此版本是因为它避免了将正则表达式用于如此琐碎的事情。

恕我直言,正则表达式是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>

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.