JavaScript HERE-doc или другой механизм больших цитат? - PullRequest
21 голосов
/ 02 июня 2010

Есть ли удобный способ заключить в кавычки большой блок HTML с одинарными и двойными кавычками в JavaScript?

Есть ли что-нибудь вроде HERE-doc <<EOF, символа мульти-кавычки """ или пользовательских разделителей q{}?

Какие-нибудь творческие или изобретательные решения этой проблемы?

Ответы [ 11 ]

19 голосов
/ 02 июня 2010

Некоторым людям это не нравится, так что будьте готовы к презрению и насмешкам, но одна хитрость заключается в том, чтобы выбросить ваш «большой кусок материала» в блок <script language="text">:

<script id='blockOfStuff' language="text">
  Hi this is random stuff
  <h1>Including HTML markup</h1>
  And quotes too, or as one man said, "These are quotes, but
  'these' are quotes too."
</script>

Джон Резиг использовал эту технику (или эту мерзость, если хотите) в качестве примера своего шаблонного механизма.

Вы можете получить содержимое с помощью «innerText» или «innerHTML», в зависимости от ситуации, или через службы вашей любимой платформы.

edit & mdash; обратите внимание, что через jQuery (вопреки тому, что я сказал в комментарии ниже) .text() работает , а не работает, хотя я думаю, что должно. Вместо этого используйте .html().

9 голосов
/ 31 марта 2011

Не поддерживается изначально.

Но поскольку мы говорим о том, как заставить это работать, вот что (по моему опыту) делает:

<script type="text/javascript">  

    var name = "Mud";

    var str = "\
        My name is " + name + "\
        not to be confused with Bill\
        or Jack or Pete or Dennis\
        my name is " + name + " and it's always been\
    ";

    alert("Les'n one: " + str);

</script>

Эти обратные слэши сделают свое дело. Просто убедитесь, что в вашей строке нет двойных кавычек, поскольку весь блок заключен в них.

Обратите внимание, что при этом не сохраняются новые строки, их необходимо вставлять вручную как "\ n" перед косой чертой в каждой строке. С другой стороны, любые отступы в начале каждой строки будут включены в выходные данные.

Действительно, это работает лучше всего, когда вам нужно объявить длинную многострочную строку в скрипте (например, XML), не так хорошо, когда вам нужно сохранить форматирование строки точно так, как вы ее определили.

Приветствия

4 голосов
/ 02 июня 2010

JavaScript не может этого сделать, но CoffeeScript , который представляет собой тонкий слой поверх JavaScript, может.

Перейдите по ссылке и прокрутите вниз до «Многострочные строки и Heredocs». ​​

3 голосов
/ 02 июня 2010

Я помню, как недавно видел умное решение, которое использовало многострочные комментарии в функции:

(function () {
   /*
      "This is an example of a multi-line string.  It's really just a mult-line
      comment, and it's wrapped in quote marks.  You might also notice the 
      apostrophe's ;-)"; 
   */
});

Примечание: последний апостроф намеренно неверен; -P

Хитрость заключается в том, чтобы вызвать метод toString() функции и проанализировать многострочный комментарий с помощью регулярного выражения. Умный, но очень похожий на предложение Пойнти, немного мерзкий.

На самом деле я не думал, что вопрос состоит в том, чтобы искать серьезно жизнеспособный метод для производственного использования - я сам виноват в том, что сделал поспешные выводы - я не совсем уверен, почему бы вам просто не избежать соответствующего строкового литерала разделители. Как отметил Тим Даун в комментариях ниже, третье издание ECMAScript определяет функции toString () как зависящие от реализации.

Для забавы я решил проверить совместимость браузера, и этот метод возможен в IE, Opera, Safari и Chrome, но не в Firefox, который не включает комментарии в возвращаемой строке. http://jsfiddle.net/2yvXG/

1 голос
/ 03 февраля 2016

ECMAscript 6, теперь стандарт, позволяет использовать обратные тики (ударение) для цитирования многострочных буквенных строк.К сожалению, это не поддерживается в IE 11, поэтому его не следует использовать на большинстве веб-сайтов.(Фото: Адам Кац, выше)

Пример:

var str=
`Line 1
Line 2`;
1 голос
/ 11 октября 2012

HereDoc для JavaScript

FuncToHereDoc ("deletemiter", не вызываемая функция с закомментированным HEREDOC)

function FuncToHereDoc(here,str) {
    var reobj = new RegExp("/\\*"+here+"\\n[\\s\\S]*?\\n"+here+"\\*/", "m");
    str = reobj.exec(str).toString();
    str = str.replace(new RegExp("/\\*"+here+"\\n",'m'),'').toString();
    return str.replace(new RegExp("\\n"+here+"\\*/",'m'),'').toString();
}

Использование:

FuncToHereDoc("HERE", MyHereDoc);

function MyHereDoc(){
/*HERE
<p>
This is written ing the HEREDOC, notice the multilines :D.
</p>
<p>
HERE
</p>
<p>
And Here
</p>
HERE*/
}
0 голосов
/ 02 октября 2015
// 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
   // url html links
   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 if(comments===6)
  { // good for html with links
   // remove comments and trim and replace new lines with escape codes
   return (
      str
      .replace(/\/\s\*([\s\S]*?)\*\s\//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 
  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 cache={};
function myfunction(week,a){


    if(!cache.myfunction_sql1) eval('cache.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=cache.myfunction_sql1(week,a);
    console.log(q)
}
myfunction(true,1234)

простой текст (не eval'd):

//var cache={};
function myfunction2(week,a){


    if(!cahce.myfunction_sql2) cahce.myfunction_sql2=extractFuncCommentString(function(){/*!

some multiline text
with <html>
and a link://to.url
and a / * comment * / 
*/},6);
    q=cahce.myfunction_sql2;
    console.log(q)
}
0 голосов
/ 21 августа 2014

Меня заинтересовал этот вопрос, потому что я хочу использовать javascript для добавления новой строки на экран редактирования (например, для нескольких телефонных номеров). (Я мог бы использовать ajax для этого, но хотел избежать дополнительного запроса к серверу.)

Мне нравится ответ Пойнти об использовании тега для включения блоков HTML, которые вы хотите использовать:

<script id='blockOfStuff'>
  Hi this is random stuff
  <h1>Including HTML markup</h1>
</script>

Но Firefox и Chrome жаловались на синтаксические ошибки, когда я пытался это сделать. Мое решение состояло в том, чтобы изменить тег «script» на «div», скрыть его отображение от пользователей через css и переместить его в теле. e.g.:

<div style="display: none;" id="new_row_innerhtml">
  <td><a href="#" onclick="removeCurrentRow(this); return false;">Remove</a></td>
  <input type="hidden" name="id[]" value="new" />
  <td><input name="name[]" type="text" /></td>
</div>

That removed the syntax errors.

Here's how I used that block:

I had an "Add" link that called the appendRow function:
<a href="#" onclick="appendRow(this); return false;">Add</a>

here's the appendRow function:

function appendRow() {
  var tbl = document.getElementById('my_table');
  var row = tbl.insertRow(-1); // add to end of table
}
0 голосов
/ 28 июня 2013

На основании предыдущих ответов и различных вариантов использования приведен небольшой пример:

https://gist.github.com/lavoiesl/5880516

/*!
 * Extract a function's comment, useful to have multiline string
 * @link https://gist.github.com/lavoiesl/5880516
 *
 * Don't forget to use /*! to avoid the comment being removed in minification 
 */

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

  return matches[1];
}

var myString = extractFuncCommentString(function(){/*!
  <p>
    foo bar
  </p>
*/});
0 голосов
/ 10 февраля 2012

Я на самом деле разработал хитрый вариант, похожий на user742675, где вы помещаете текст в div, затем устанавливаете его видимость в none и извлекаете содержимое. Но простого цитирования большого количества HTML было недостаточно, поэтому я добавил функциональность, которая подобрала все переменные, которые вы объявили в своем скрипте, поэтому, если бы у вас было var a = 'Steve', любой экземпляр $ a в вашем тексте heredoc был бы отображается как «Стив».

<script type="text/javascript">
// set variables named andy and handy, which we can use as $andy and $handy in our text

var andy = "Fred Flintstone";
var handy = "Steve Austin";

function hereDoc(divid){
var obj = window; // gets an object containing all the variables
var str = document.getElementById(divid).innerHTML; // gets the HTML block
for(var i in obj){

/* the for loop recurses through all the objects in the page - remember strings are objects in Javascript */

if((typeof(obj[i])=="string")||(typeof(obj[i])=="number")){

/* Type of makes sure it only executes replacement for strings and numbers. The function worked without this test in Firefox and Safari, but threw errors on Opera until it was added. */

myregex = new RegExp('\\$'+i,"g");

/* To replace globally, you need to use a regular expression and use the "g" option, but within the string.replace() method, the regular expression is unquoted, so you can't use a variable in it directly. So we create it and assign it to a RegExp object that works in the string.replace() method. */

str = str.replace(myregex, obj[i]);

/* we replace instances of the variable name with a dollar sign before it with the variable's value */
}
}
return str;

/* and when the loop is done, we return the processed text to be used however needed */

}

function gotoit(){

/* fill the "steve" div with the processed contents of the "randy" div. */

document.getElementById("steve").innerHTML = hereDoc("randy");
}

</script>

<a href="javascript:gotoit();">Run the script</a>
<div id="randy" style="display:none;">
The interesting thing about $andy is that he's not nearly as popular with young kids as $handy.<br><br>

What I really find 'interesting' is that this "multiline" thing works as well as $handy's bionic arm. <br><br>
</div>
<div id="steve"></div>
...