자바 스크립트 heredoc


109

JavaScript에서 heredoc과 같은 것이 필요합니다. 이것에 대한 아이디어가 있습니까? 브라우저 간 기능이 필요합니다.

나는 이것을 찾았다:

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

나는 그것이 나를 위해 일할 것이라고 생각합니다. :)


6
좀 더 자세한 답변이있는 stackoverflow.com/questions/805107/…의 중복 .
Chadwick

4
"\"를 추가하면 매번 눈살을 찌푸리게됩니다. Imho, 여러 줄 문자열에 대한 일반 구문이없는 것은 완전히 정당화되지 않습니다. 그리고 그들은 주어진 버전에서 그것을 추가 할 수 있었지만 그렇지 않았습니다.
렉스


요즘에는 중복 가능성이있는 템플릿 리터럴로 수행됩니다 (여기에는 업데이트 된 답변이 없습니다).
brasofilo

답변:


77

시도 ES6 문자열 템플릿 , 당신은 뭔가를 할 수 있습니다

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


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

=> true

당신과 함께 오늘이 위대한 기능을 사용할 수 있습니다 6to5 또는 타이프 라이터


2
이것은 여러 줄 문자열을 원하는 경우에 적용 할 수 있습니다. 그러나 문자열을 둘러싸는 기호를 실제로 변경할 수 없기 때문에 실제로 heredoc이 아닙니다.
Peeyush Kushwaha

3
참고로 원래 질문은 ES6가 출시되기 5 년 전에 질문되었습니다. 이것은 성능도 더 좋기 때문에 앞으로 나아가는 모범 사례입니다.
Henry Tseng

2
@HenryTseng,이 질문에 대한 답변이 5 년 전에 존재했던 고대 기술에 맞게 조정되어야한다고 제안하고 있습니까? 질문이 여전히 열려 있다면 시간이 지남에 따라 생성 된 새로운 기술을 활용할 자격이 있습니다. 이렇게하면 동일한 문제가있는 신규 사용자가 여기에서 "비고 고 학적"정보를 찾을 수 있습니다.
asiby

1
아니요, 이전에 그 솔루션이 더 눈에 띄지 않는 이유에 대해 언급했습니다. 호환성 문제가없는 경우 지원되는 방식으로 진행되는 것 같습니다.
Henry Tseng

63

아니요, 안타깝게도 JavaScript는 heredoc과 같은 것을 지원하지 않습니다.


12
:) 나도 알아하지만 난 히어 닥 해킹을 찾을 수 있도록 노력하겠습니다
VeroLom

구문 분석 함수의 의견처럼 뭔가 (하지만 즉 / 파이어 폭스에서 작업이 아니다) =
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

Chrome 콘솔에서 작동
Omn

4
*/heredoc에 닫는 주석이 있으면 작동하지 않습니다 .
Narigo 2010

2
Nate Ferrero의 대답은 더 세련되고 최적화 된 예이므로 사용하는 것이 좋습니다. Mine은 3 개의 별도 regEx 호출을 사용하며 개념 증명에 더 가깝습니다.
Zv_oDD

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라는 이름을 대신 사용하도록 변경되었습니다.

2017 년 5 월 26 일-최신 코딩 표준을 반영하기 위해 공백이 업데이트되었습니다.


1
hereDoc ()을 함수 이름으로 사용하지만이 코드는 40k 줄의 로그 덤프를 Chrome 콘솔의 변수에로드하는 데 문제가 없습니다.
Omn

함수의 인스턴스를 만들고 사용되지 않는 __ proto __ 속성에 액세스하는 이유는 무엇입니까? 그냥 Function.prototype.str = function () {...}하지 않는 이유는 무엇입니까?
John Kurlak 2014 년

@JohnKurlak 더 좋습니다! 내가 답을 썼을 때 가능하다는 것을 알지 못했다고 생각합니다.
Nate Ferrero 2014

2
@NateFerrero-멋진 대답, 감사합니다! 별도의 답변으로 내 확장을 추가했습니다.
Andrew Cheong

내 Android, nexus 4에서 5.0.1을 실행하면 더 이상 Chrome에서 작동하지 않습니다. 어떤 이유로 공백과 주석을 삭제합니다. 이것이 설정인지 알 수 없지만 확실히 클라이언트 측에 있습니다. 해결 방법에 대한 아이디어가 있습니까?
MLU

19

실행중인 JS / JS 엔진 (SpiderMonkey, AS3)의 종류에 따라 heredoc과 같이 여러 줄에 텍스트를 배치 할 수있는 인라인 XML을 간단히 작성할 수 있습니다.

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"

실제로 Tagged Temple Strings 및 Raw Strings와 같은 더 많은 기능이 있습니다. 설명서를 찾으십시오.

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


8

@NateFerrero의 답변에 대한 확장에 대한 별도의 답변을 작성하는 것이 좋지 않습니다. 않지만 그의 답변을 편집하는 것도 적절하다고 생각하지 않으므로이 답변이 유용하다면 @NateFerrero를 찬성하십시오.

tl; dr- heredoc 내에서 블록 주석을 사용하려는 사람들을 위해 ...

나는 주로 CSS의 블록 저장하기 위해 자바 스크립트 heredocs 필요 예를

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을 깨뜨립니다.


이 특정 목적 (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;
    }
*/});

replace단순히 /* ... * /만들 공간을 찾아서 제거하여 /* ... */호출 될 때까지 heredoc을 보존합니다.


물론 다음을 사용하여 주석을 모두 제거 할 수 있습니다.

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

//주석을 체인에 추가하는 경우 에도 지원할 수 있습니다 .

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

또한 다음 */같이 와 사이의 단일 공백 ​​이외의 다른 작업을 수행 할 수 있습니다 -.

    /**
     * Nuke rounded corners.
     *-/

정규식을 적절하게 업데이트하는 경우 :

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

아니면 단일 공백 ​​대신 임의의 양의 공백을 원하십니까?

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

2
멋있는! 즉 나는 :) 그것을처럼, 내 방법 알려진 제한했다
네이트 페레로

8

JavaScript로 컴파일되는 언어 인 CoffeeScript를 사용할 수 있습니다 . 코드는 일대일로 동등한 JS로 컴파일되며 런타임에는 해석이 없습니다.

그리고 물론 heredocs있습니다. :)


24
정답은 아니오입니다. CoffeeScript 및 EJS를 제안으로 사용할 수 있습니다.
alvincrespo

4
CoffeeScript는 내가 만난 대부분의 JS 문제에 대한 정답입니다. 사소한 양의 JS를 작성하고 (시간과 에너지를 소중하게 생각하는 경우) 사용하는 것은 자신에게 빚진 것입니다.
Brandon

5
나는 이것이 자바 스크립트에서 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 템플릿 문자열은 전통적인 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에서는 단지 var 이름을 입력하면 Chrome 콘솔에 개행 문자가 없다는 점을 제외하고는. 그러나 변수는 동일합니다. 그것은 () CONSOLE.LOG으로 줄 바꿈로 인쇄하는 것이 가능
시몬 Doodkin

0

이 버전은 너무 사소한 것에 정규식을 사용하지 않기 때문에 게시하고 있습니다.

IMHO 정규식은 펄 개발자들 사이에서 실용적인 농담으로 만들어진 난독 화입니다. 나머지 커뮤니티는 그들을 진지하게 받아 들였고 우리는 이제 수십 년 후에 그 대가를 지불합니다. 레거시 코드와의 하위 호환성을 제외하고 정규식을 사용하지 마십시오. 요즘에는 사람이 즉시 읽을 수없고 이해할 수없는 코드를 작성할 변명의 여지가 없습니다. 정규식은 모든 수준에서이 원칙을 위반합니다.

나는 또한 이것이 요청 된 것이 아니라 현재 페이지에 결과를 추가하는 방법을 추가했습니다.

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.