Javascript heredoc


109

JavaScript'te heredoc gibi bir şeye ihtiyacım var. Bunun için herhangi bir fikrin var mı? Tarayıcılar arası işlevselliğe ihtiyacım var.

Bunu buldum:

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

Benim için çalışacağını düşünüyorum. :)


6
Daha ayrıntılı yanıtları olan stackoverflow.com/questions/805107/… dosyasının kopyası.
Chadwick

4
"\" Eklemek zorunda kalmak her seferinde kaşlarımı çatıyor. Imho, çok satırlı dizeler için normal sözdizimine sahip olmamak tamamen gerekçesizdir. Ve bunu herhangi bir sürüme ekleyebilirlerdi, ama eklemediler.
Lex


Günümüzde, bu, olası kopyada gösterildiği gibi şablon değişmez değerleri ile yapılır (burada güncellenmiş bir cevap yoktur).
brasofilo

Yanıtlar:


77

ES6 String Template deneyin, şöyle bir şey yapabilirsiniz:

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


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

=> true

Bu harika özelliği bugün 6to5 veya TypeScript ile kullanabilirsiniz.


2
Bu, yalnızca çok satırlı dizeler istiyorsanız geçerlidir. Bununla birlikte, dizenizi çevreleyen sembolü gerçekten değiştiremeyeceğiniz için, bu gerçekten yorumlama değildir.
Peeyush Kushwaha

3
Bir not olarak, orijinal soru 5 yıl önce ES6 piyasaya çıkmadan önce sorulmuştu. Performans da daha iyi olduğu için ileriye dönük en iyi uygulama budur.
Henry Tseng

2
@HenryTseng, peki bu sorunun yanıtlarının 5 yıl önce var olan eski teknolojilere uyarlanması gerektiğini mi düşünüyorsunuz? Soru hala açıksa, zamanla oluşturuldukları şekliyle yeni teknolojilerden yararlanmayı hak ediyor. Bu şekilde, aynı sorunu yaşayan yeni kullanıcılar burada "arkeolojik olmayan" bilgileri bulabilir.
asiby

1
Hayır, daha önce bu çözümün neden daha belirgin olmadığı konusunda bir yorum yapıyordum. Herhangi bir uyumluluk sorunu yoksa, kesinlikle desteklenen bir yol gibi görünüyor.
Henry Tseng

63

Hayır, ne yazık ki JavaScript heredoc gibi hiçbir şeyi desteklemiyor.


12
Biliyorum ama heredoc hack bulmayı umuyorum :)
VeroLom

Ayrıştırma işlevinin yorumları gibi bir şey (ancak ie / firefox'ta çalışmıyor) =
VeroLom

37

Buna ne dersin:

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" ve "HERE * /" kelimelerini tercih ettiğiniz sözcükle değiştirmeniz yeterlidir.


4
tüm tarayıcılar / motorlar Function.toString () içindeki yorumları döndürür mü? bu çok zekice
gcb

Chrome konsolunda çalışır
Omn

4
Yorum */yazınızda bir kapanış yorumunuz varsa çalışmaz.
Narigo

2
Daha rafine ve optimize edilmiş bir örnek olduğu için Nate Ferrero'nun cevabını kullanmanızı tavsiye ederim. Mine, 3 ayrı regEx çağrısı kullanır ve daha çok kavram kanıtıdır.
Zv_oDD

1
Çok zekice ... ama gelecekte işe yarayacağını garanti edemezsiniz. İyi bir uygulama olamayacak kadar uygulamaya bağımlıdır.
Pierre-Olivier Vares

33

Zv_oDD'nin cevabına dayanarak, daha kolay yeniden kullanım için benzer bir işlev oluşturdum.

Uyarı: Bu, birçok JS yorumlayıcısının standart olmayan bir özelliğidir ve muhtemelen bir noktada kaldırılacaktır, ancak yalnızca Chrome'da kullanılmak üzere bir komut dosyası oluştururken, onu kullanıyorum! Müşteriye yönelik web siteleri için buna asla güvenmeyin!

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

kullanın:

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

İadeler:

"A test of horrible
Multi-line strings!"

Notlar:

  1. Metin her iki uçta da kırpılır, bu nedenle her iki uçtaki fazladan boşluklar tamamdır.

Düzenlemeler:

2/2/2014 - İşlev prototipiyle hiç uğraşmayacak şekilde değiştirildi ve onun yerine heredoc adını kullanın.

5/26/2017 - modern kodlama standartlarını yansıtmak için beyaz boşluk güncellendi.


1
İşlev adım olarak hereDoc () 'u kullanırdım, ancak bu kod 40k satır günlük
dökümümü

Neden bir işlev örneğini oluşturup, kullanımdan kaldırılan __ proto __ özelliğine erişirsiniz? Neden sadece Function.prototype.str = function () {...} yapmıyorsunuz?
John Kurlak

@JohnKurlak bu daha da iyi! Cevabı yazdığımda bunun mümkün olduğunun farkında olduğumu sanmıyorum.
Nate Ferrero

2
@NateFerrero - Harika cevap, teşekkürler! Ayrı bir cevap olarak kendime ait bir uzantı ekledim.
Andrew Cheong

5.0.1 çalıştıran Android Nexus 4 cihazımda artık Chrome'da çalışmıyor. Nedense boşlukları ve yorumları siliyor. Bunun bir ayar olup olmadığını anlayamıyorum ama kesinlikle müşteri tarafında. Bir geçici çözüm için herhangi bir fikriniz var mı?
MLU

19

Çalıştırdığınız JS / JS motoruna (SpiderMonkey, AS3) bağlı olarak, heredoc gibi birden çok satıra metin yerleştirebileceğiniz satır içi XML yazabilirsiniz:

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

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

13

ES6 Şablon Dizeleri yorum yazımı özelliğine sahiptir.

Geri tik (``) ile çevrelenmiş dizeleri bildirebilir ve birden çok satırla genişletilebilirsiniz.

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

Şablon Dizelerinin içine de ifadeler dahil edebilirsiniz. Bunlar Dolar işareti ve kaşlı ayraçlar ( ${expression}) ile gösterilir.

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"

Aslında içinde Tagged Temple Strings ve Raw Strings gibi daha fazla özellik var. Lütfen belgeleri şu adreste bulabilirsiniz:

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


8

Yalnızca @ NateFerrero'nun cevabının bir uzantısı için ayrı bir cevap yazmaktan çekiniyorum , ancak cevabını düzenlemenin de uygun olduğunu düşünmüyorum, bu yüzden bu cevap sizin için yararlıysa lütfen @NateFerrero'ya oy verin.

tl; dr-For blok yorumlar kullanmak isteyenler içeride kendi yorumlu metin ...

Ben esas olarak CSS, bloğunu depolamak için JavaScript heredoc gerekli örn

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

Ancak görebileceğiniz gibi */, CSS'mi yorumlamayı seviyorum ve maalesef (sözdizimi vurgulamasının işaret ettiği gibi) ilk yorum genel yorumu sonlandırarak heredocu bozuyor.


Bu özel amaç için (CSS), benim çözümüm eklemek oldu

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

@ NateFerrero'nun içindeki zincire heredoc; eksiksiz biçimde:

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

ve arasına boşluk ekleyerek kullanmak *ve /böylece gibi "iç" blok yorum, için:

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

replaceBasitçe bulur /* ... * /ve marka için boşluk kaldırır /* ... */verilene kadar bu şekilde yorumlu metin koruyarak.


Şunu kullanarak yorumları elbette tamamen kaldırabilirsiniz.

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

Ayrıca //, zincire eklerseniz yorumları da destekleyebilirsiniz :

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

Ayrıca, *ve arasındaki tek boşluk dışında bir şey de yapabilirsiniz /, örneğin -:

    /**
     * Nuke rounded corners.
     *-/

regex'i uygun şekilde güncellerseniz:

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

Ya da belki tek bir boşluk yerine rastgele miktarda beyaz boşluk istersiniz?

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

2
Güzel! Bu yöntemimle ilgili bilinen bir sınırlamaydı, beğendim :)
Nate Ferrero

8

JavaScript'e derleyen bir dil olan CoffeeScript'i kullanabilirsiniz . Kod, eşdeğer JS'de bire bir derler ve çalışma zamanında yorum yapılmaz.

Ve tabii ki yorumlu metinler de var :)


24
Doğru cevap hayır. CoffeeScript ve EJS öneri olarak kullanılabilir.
alvincrespo

4
CoffeeScript, karşılaştığım çoğu JS sorununa doğru yanıttır. Önemsiz miktarda JS yazarsanız (ve zamanınıza ve enerjinize değer verirseniz), onu kullanmayı kendinize borçlusunuz.
Brandon

5
Bence bu iyi bir cevap çünkü javascript'te heredoc'un yokluğunu atlatmanın kolay bir yolunu sağlıyor. Bana çok zaman kazandırdı.
Stofke

3
Sadece bir js yığını istiyorsanız, ancak gerçekten yazmakla uğraşmak istemiyorsanız: coffeescript.org ve "Coffeescript'i Deneyin" düğmesini kullanın.
jcollum

1
Bu, en yüksek oy alan cevaptan daha çok bir cevap, temelde sadece ... "hayır". Bu tür cevaplardan nefret ediyorum.
Matt Fletcher

7

ES5 ve önceki sürümler

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

ES6 ve sonraki sürümler

`some random
multi line
text here`

sonuç

some random
multi line
text here

en iyi basit cevap
Benjamin

1
Eski tarz şey inanılmaz derecede acımasız bir hack: /
Shayne

1

Bu gönderide Tim Disney tarafından yaratıldığı şekliyle eklemek için Sweet.js Makrolarını kullanabilirsiniz.

Bu yaklaşımın, bunun yerine dize sınırlayıcıları olarak ters işaretler kullandığını unutmayın:

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

Başkalarının da söylediği gibi, ES6 şablon dizgeleri size geleneksel yorumlu metinlerin sağladığının çoğunu verir.

Bir adım daha ileri gitmek ve etiketli bir şablon dizisi kullanmak theredocistiyorsanız, bunu yapmanızı sağlayan güzel bir yardımcı program işlevidir:

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

Elinizde biraz html ve jQuery varsa ve dize geçerli HTML ise, bu yararlı olabilir:

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

Metin arasında "<! - ->" yorumları varsa, bu da işe yarar, ancak metnin bir kısmı görülebilir. İşte keman: 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
}

misal

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));

önbellek ile: - basit bir şablon işlevi yapın ve işlevi kaydedin: (ikinci sefer hızlı çalışır)

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 ve Chrome'da oldukça farklı sonuçlar.
Dave Newton

ne farklı Sadece Chrome ve FF'de test edildi ve tamamen aynı sonuçları alıyorum. Bunun dışında Chrome'da Chrome Konsolu'nda yeni satır yoktur. Yalnızca değişken adını yazarsanız. ancak değişken aynıdır.
Console.log

0

Bu sürümü çok önemsiz bir şey için normal ifadenin kullanılmasını engellediği için gönderiyorum.

IMHO regex, perl geliştiricileri arasında pratik bir şaka olarak yaratılmış bir gizlemedir. topluluğun geri kalanı onları ciddiye aldı ve şimdi bedelini onlarca yıl sonra ödüyoruz. eski kodla geriye dönük uyumluluk dışında normal ifadeler kullanmayın. Bu günlerde, hemen okunabilir ve anlaşılabilir olmayan bir kod yazmak için hiçbir mazeret yok. regex bu ilkeyi her düzeyde ihlal eder.

Ayrıca sonucu geçerli sayfaya eklemenin bir yolunu ekledim, bunun istenmediğini değil.

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>

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.