Как передать переменную из файла шаблона jade в файл script?

У меня возникают проблемы с переменной (config), объявленной в файле jade-шаблона (index.jade), который не передается в файл javascript, что затем приводит к сбою в работе javascript. Вот файл (views/index.jade):

h1 #{title}

script(src='./socket.io/socket.io.js')
script(type='text/javascript')
  var config = {};
  config.address = '#{address}';
  config.port = '#{port}';
script(src='./javascripts/app.js')

Вот часть моего app.js(серверная сторона):

  app.use(express.bodyParser());
  app.use(express.methodOverride());
  app.use(app.router);
  app.use(express.static(__dirname + '/public'));
});

app.configure('development', function(){
  app.set('address', 'localhost');
  app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
});

app.configure('production', function(){
  app.use(express.errorHandler());
});

// Routes

app.get('/', function(req, res){
  res.render('index', {
    address: app.settings.address,
    port: app.settings.port
});
});

if (!module.parent) {
  app.listen(app.settings.port);
  console.log("Server listening on port %d",
app.settings.port);
}

// Start my Socket.io app and pass in the socket
require('./socketapp').start(io.listen(app));

И вот часть моего javascript файла, который сбой (public/javascripts/app.js):

(function() {
        var socket = new io.Socket(config.address, {port: config.port, rememberTransport: false});

Я запускаю сайт в режиме разработки (NODE_ENV = разработка) на localhost (моя собственная машина). Я использую node -инспектор для отладки, который сказал мне, что переменная конфигурации undefined в public/javascripts/app.js.

Любые идеи? Спасибо!!

Ответ 1

Немного поздно, но...

script.
  loginName="#{login}";

Это отлично работает в моем script. В Express я делаю это:

exports.index = function(req, res){
  res.render( 'index',  { layout:false, login: req.session.login } );
};

Я думаю, что последний нефрит отличается?

Merc.

edit: добавлено "." после script, чтобы предотвратить предупреждение Jade.

Ответ 2

!{} для unescaped код, который более подходит для объектов

script var data = !{JSON.stringify(data).replace(/<\//g, '<\\/')}

{ foo: 'bar' }
// becomes:
<script>var data = {"foo":"bar"}</script>

{ foo: 'bar</script><script>alert("xss")//' }
// becomes:
<script>var data = {"foo":"bar<\/script><script>alert(\"xss\")//"}</script>

Идея состоит в том, чтобы предотвратить атакующий:

  • Вырыв из переменной: JSON.stringify выполняет кавычки
  • Разрыв тэга script: если содержимое переменной (которое вы, возможно, не сможете контролировать, если происходит из базы данных для ex.), имеет строку </script>, оператор replace позаботится об этом

https://github.com/pugjs/pug/blob/355d3dae/examples/dynamicscript.pug


#{} для экранированного string интерполяция, которая подходит только в том случае, если вы работаете со строками. Он не работает с объектами

script var data = #{JSON.stringify(data)}

//=> <script>var data = {&quot;foo&quot;:&quot;bar&quot;}</script>

Ответ 3

Смотрите этот вопрос: JADE + EXPRESS: Итерирование объекта в встроенном JS-коде (на стороне клиента)?

У меня такая же проблема. Jade не пропускает локальные переменные (или вообще не делает шаблонов) скриптам javascript, он просто передает весь блок в виде буквального текста. Если вы используете локальные переменные "адрес" и "порт" в вашем файле Jade над тегом script, они должны появиться.

Возможные решения перечислены в вопросе, который я связал выше, но вы можете: - передать каждую строку в виде неэксклюзивного текста (!= в начале каждой строки) и просто поместить "-" перед каждой строкой javascript, которая использует локальную переменную, или: - Передать переменные через элемент dom и получить доступ через JQuery (уродливый)

Нет ли лучшего способа? Кажется, создатели Jade не хотят поддержки многострочной javascript, как показано в этом потоке в GitHub: https://github.com/visionmedia/jade/pull/405

Ответ 4

Вот как я обратился к этому (используя производную MEAN)

Мои переменные:

{
  NODE_ENV : development,
  ...
  ui_varables {
     var1: one,
     var2: two
  }
}

Сначала мне нужно было убедиться, что необходимые переменные конфигурации передаются. MEAN использует пакет node nconf и по умолчанию настроен для ограничения того, какие переменные передаются из среды. Я должен был исправить это:

конфиг /config.js:

оригинал:

nconf.argv()
  .env(['PORT', 'NODE_ENV', 'FORCE_DB_SYNC'] ) // Load only these environment variables
  .defaults({
  store: {
    NODE_ENV: 'development'
  }
});

после изменений:

nconf.argv()
  .env('__') // Load ALL environment variables
  // double-underscore replaces : as a way to denote hierarchy
  .defaults({
  store: {
    NODE_ENV: 'development'
  }
});

Теперь я могу установить такие переменные следующим образом:

export ui_varables__var1=first-value
export ui_varables__var2=second-value

Примечание: я reset индикатор "иерархии" до "__" (двойной знак подчеркивания), поскольку его значение по умолчанию ":", что затрудняет настройку переменных из bash. См. Другое сообщение в этой теме.

Теперь нефритовая часть: Затем значения должны быть отображены, чтобы javascript мог забрать их на стороне клиента. Прямой способ записать эти значения в индексный файл. Поскольку это одностраничное приложение (angular), эта страница всегда загружается первым. Я думаю, что в идеале это должен быть файл с поддержкой javascript (просто чтобы все было в порядке), но это хорошо для демонстрации.

приложение/контроллеры/index.js:

'use strict';
var config = require('../../config/config');

exports.render = function(req, res) {
  res.render('index', {
    user: req.user ? JSON.stringify(req.user) : "null",
    //new lines follow:
    config_defaults : {
       ui_defaults: JSON.stringify(config.configwriter_ui).replace(/<\//g, '<\\/')  //NOTE: the replace is xss prevention
    }
  });
};

приложение/просмотров/index.jade:

extends layouts/default

block content
  section(ui-view)
    script(type="text/javascript").
    window.user = !{user};
    //new line here
    defaults = !{config_defaults.ui_defaults};

В моем рендерированном html это дает мне небольшой script:

<script type="text/javascript">
 window.user = null;         
 defaults = {"var1":"first-value","var2:"second-value"};
</script>        

С этой точки легко использовать angular код.