web-dev-qa-db-fra.com

Javascript heredoc

J'ai besoin de quelque chose comme heredoc en JavaScript. Avez-vous des idées pour cela? J'ai besoin de fonctionnalités multi-navigateurs.

J'ai trouvé ça:

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

Je pense que cela fonctionnera pour moi. :)

87
VeroLom

Non, malheureusement, JavaScript ne supporte rien comme heredoc.

62
Andrew Hare

Essayez ES6 String Template, vous pouvez faire quelque chose comme

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


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

=> true

Vous pouvez utiliser cette fonctionnalité intéressante aujourd'hui avec 6to5 ou TypeScript

51
mko

Que dis-tu de ça:

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

Il suffit de remplacer "/ * ICI" et "ICI * /" par le mot de votre choix.

39
Zv_oDD

En me basant sur la réponse de Zv_oDD, j'ai créé une fonction similaire pour une réutilisation plus facile.

Attention: Il s'agit d'une fonctionnalité non standard de nombreux interpréteurs JS. Elle sera probablement supprimée à un moment donné. Toutefois, comme je suis en train de créer un script destiné uniquement à Chrome, je l'utilise! Ne comptez pas sur jamais pour les sites Web destinés aux clients!

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

Utilisation:

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

Résultats:

"A test of horrible
Multi-line strings!"

Remarques:

  1. Le texte est découpé aux deux extrémités, de sorte que tous les espaces supplémentaires sont OK.

Modifications:

02/02/2014 - changé pour ne pas jouer avec le prototype de fonction et utiliser le nom heredoc à la place.

26/05/2017 - espaces mis à jour pour refléter les normes de codage modernes.

30
Nate Ferrero

Selon le type de moteur JS/JS que vous utilisez (SpiderMonkey, AS3), vous pouvez simplement écrire du code XML en ligne dans lequel vous pouvez placer du texte sur plusieurs lignes, comme heredoc:

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

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

ES6 Template Strings a une fonctionnalité heredoc. 

Vous pouvez déclarer des chaînes entourées par back-tick (``) et être étendues sur plusieurs lignes.

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

Vous pouvez également inclure des expressions dans les chaînes de modèles. Celles-ci sont indiquées par le signe dollar et les accolades (${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"

Il contient en fait davantage de fonctionnalités telles que Tagged Temple Strings et Raw Strings. Veuillez trouver la documentation sur 

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

13
Charlie H

Je me sens mal d’écrire une réponse distincte pour une simple extension de @ NateFerrero's , mais je ne pense pas que l’édition de sa réponse soit appropriée non plus, veuillez donc voter @ @ NateFerrero si cette réponse vous était utile.

tl; dr - Pour ceux qui souhaitent utiliser les commentaires de bloc dans leur hérédoc ...

J'avais surtout besoin de Javascript heredocs pour stocker un bloc de CSS, p.

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

Comme vous pouvez le constater, j’aime commenter mes CSS et, malheureusement (comme le suggère la coloration syntaxique en surbrillance), le premier */ termine le commentaire général, cassant ainsi l’hérédoc.


Dans ce but spécifique (CSS), ma solution de contournement consistait à ajouter

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

à la chaîne à l'intérieur de la variable heredoc de @ NateFerrero; sous forme complète:

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

et l'utiliser en ajoutant un espace entre les * et / pour les commentaires de bloc "internes", comme suit:

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

La replace trouve simplement /* ... * / et supprime l'espace pour créer /* ... */, préservant ainsi le heredoc jusqu'à ce qu'il soit appelé.


Vous pouvez bien sûr supprimer complètement les commentaires en utilisant

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

Vous pouvez également prendre en charge les commentaires // si vous les ajoutez à la chaîne:

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

De plus, vous pouvez faire autre chose que l'espace unique entre * et /, comme un -:

    /**
     * Nuke rounded corners.
     *-/

si vous venez de mettre à jour le regex de manière appropriée:

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

Ou peut-être préférez-vous une quantité arbitraire d'espaces blancs au lieu d'un seul espace?

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

Vous pouvez utiliser CoffeeScript , un langage qui compile jusqu'à JavaScript. Le code est compilé un par un dans le JS équivalent et il n'y a pas d'interprétation à l'exécution.

Et bien sûr, il a heredocs :)

7
Jakob

Vous pouvez utiliser les macros Sweet.js pour l’ajouter comme suit, créé par Tim Disney dans cet article

Notez que cette approche utilise des backticks comme délimiteurs de chaîne:

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

ES5 et versions antérieures

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

ES6 et versions ultérieures

`some random
multi line
text here`

résultat

some random
multi line
text here
1
Ga1der

Je poste cette version car elle évite l'utilisation de regex pour quelque chose d'aussi trivial.

IMHO regex est une obfuscation qui a été créée comme une blague entre développeurs. le reste de la communauté les a pris au sérieux et nous en payons maintenant le prix, des décennies plus tard. n'utilisez pas de regex, sauf pour des raisons de compatibilité avec le code hérité. De nos jours, il n'y a aucune excuse pour écrire un code qui ne soit pas immédiatement lisible et compréhensible par l'homme. regex viole ce principe à tous les niveaux.

J'ai également ajouté un moyen d'ajouter le résultat à la page en cours, même si cela n'a pas été demandé.

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

Si vous avez du HTML et de jQuery sous la main et que la chaîne est valide HTML, cela peut être utile:

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

Si le texte contient des commentaires "<! - ->", cela fonctionne aussi, mais une partie du texte peut être visible . Voici le violon: https://jsfiddle.net/hr6ar152/ 1/

0
Max Oriola
// 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
}

exemple 

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

avec cache: - crée une fonction de modèle simple et enregistre la fonction: (la deuxième fois, ça marche vite)

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)
0
Shimon Doodkin

Comme d'autres l'ont dit, les chaînes de modèles ES6 vous donnent la plupart de ce que fournissent les hérédocs traditionnels.

Si vous voulez aller plus loin et utiliser une chaîne de modèle étiquetée, theredoc est une fonction utilitaire de Nice qui vous permet de faire ceci:

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
Neall