如何将变量从jade模板文件传递到脚本文件?

时间:2023-01-24 09:50:32

I'm having trouble with a variable (config) declared in a jade template file (index.jade) that isn't passed to a javascript file, which then makes my javascript crash. Here is the file (views/index.jade):

我在一个jade模板文件(index.jade)中声明的变量(config)上遇到了麻烦,该文件没有传递给javascript文件,这导致我的javascript崩溃。这是文件(视图/索引.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')

Here is a part of my app.js (server side):

这里是我的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));

And here is a part of my javascript file that crashes (public/javascripts/app.js):

这里是我的javascript文件崩溃的一部分(公共/javascript /app.js):

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

I'm running the site on development mode (NODE_ENV=development) on localhost (my own machine). I'm using node-inspector for debugging, which told me that the config variable is undefined in public/javascripts/app.js.

我正在localhost(我自己的机器)上运行站点的开发模式(NODE_ENV=development)。我正在使用node-inspector进行调试,它告诉我配置变量在public/javascript /app.js中没有定义。

Any ideas?? Thanks!!

有什么想法?谢谢! !

5 个解决方案

#1


141  

It's a little late but...

有点晚了,但是……

script.
  loginName="#{login}";

This is working fine in my script. In Express, I am doing this:

这在我的脚本中运行得很好。在快递上,我这样做:

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

I guess the latest jade is different?

我猜最新的玉器不同吧?

Merc.

芝加哥商业交易所。

edit: added "." after script to prevent Jade warning.

编辑:添加“。”后,防止玉石警告。

#2


81  

!{} is for unescaped code interpolation, which is more suitable for objects

{}是为未转义的代码插值,更适合对象

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>

The idea is to prevent the attacker to:

目的是防止攻击者:

  1. Break out of the variable: JSON.stringify escapes the quotes
  2. 跳出变量:JSON。stringify转义引号
  3. Break out of the script tag: if the variable contents (which you might not be able to control if comes from the database for ex.) has a </script> string, the replace statement will take care of it
  4. 跳出脚本标记:如果变量内容(如果来自数据库的话,您可能无法控制)有一个字符串,则replace语句将处理它

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

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


#{} is for escaped string interpolation, which is suitable only if you're working with strings. It does not work with objects

#{}用于转义字符串插值,这只适用于处理字符串。它与对象无关。

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

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

#3


2  

See this question: JADE + EXPRESS: Iterating over object in inline JS code (client-side)?

看到这个问题了吗:JADE + EXPRESS:在内联JS代码(客户端)中迭代对象?

I'm having the same problem. Jade does not pass local variables in (or do any templating at all) to javascript scripts, it simply passes the entire block in as literal text. If you use the local variables 'address' and 'port' in your Jade file above the script tag they should show up.

我也有同样的问题。Jade不向javascript脚本传递本地变量(或做任何模板),它只是将整个块作为文本传入。如果您在脚本标签上方的翡翠文件中使用本地变量'address'和'port',那么它们应该会出现。

Possible solutions are listed in the question I linked to above, but you can either: - pass every line in as unescaped text (!= at the beginning of every line), and simply put "-" before every line of javascript that uses a local variable, or: - Pass variables in through a dom element and access through JQuery (ugly)

可能的解决方案在我链接到上面的问题中列出,但是您也可以:-将每一行作为未转义的文本(!=在每一行的开头),并在每一行使用本地变量的javascript之前写上“-”,或者:-通过dom元素传入变量并通过JQuery访问(丑陋)

Is there no better way? It seems the creators of Jade do not want multiline javascript support, as shown by this thread in GitHub: https://github.com/visionmedia/jade/pull/405

难道没有更好的办法吗?看起来Jade的创建者不需要多行javascript支持,如GitHub中的这个线程所示:https://github.com/visionmedia/jade/pull/405

#4


2  

In my case, I was attempting to pass an object into a template via an express route (akin to OPs setup). Then I wanted to pass that object into a function I was calling via a script tag in a pug template. Though lagginreflex's answer got me close, I ended up with the following:

在我的例子中,我试图通过一个快速通道将一个对象传递给一个模板(类似于OPs设置)。然后,我想将该对象传递给我正在通过pug模板中的脚本标记调用的函数。虽然lagginreflex的回答让我很接近,但我最终还是选择了以下几点:

script.
    var data = JSON.parse('!{JSON.stringify(routeObj)}');
    funcName(data)

This ensured the object was passed in as expected, rather than needing to deserialise in the function. Also, the other answers seemed to work fine with primitives, but when arrays etc. were passed along with the object they were parsed as string values.

这确保了对象按预期传入,而不需要在函数中反序列化。另外,对于原语,其他的答案似乎也可以,但是当数组等与对象一起传递时,它们被解析为字符串值。

#5


0  

Here's how I addressed this (using a MEAN derivative)

下面是我如何解决这个问题(使用平均导数)

My variables:

我的变量:

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

First I had to make sure that the necessary config variables were being passed. MEAN uses the node nconf package, and by default is set up to limit which variables get passed from the environment. I had to remedy that:

首先,我必须确保传递了必需的配置变量。MEAN使用节点nconf包,默认设置为限制从环境中传递哪些变量。我必须补救:

config/config.js:

配置/ config.js:

original:

原:

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

after modifications:

修改后:

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

Now I can set my variables like this:

现在我可以这样设置变量:

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

Note: I reset the "heirarchy indicator" to "__" (double underscore) because its default was ":", which makes variables more difficult to set from bash. See another post on this thread.

注意:我将“继承指标”重置为“__”(双下划线),因为它的默认值是“:”,这使得从bash设置变量变得更加困难。请参阅此线程上的另一篇文章。

Now the jade part: Next the values need to be rendered, so that javascript can pick them up on the client side. A straightforward way to write these values to the index file. Because this is a one-page app (angular), this page is always loaded first. I think ideally this should be a javascript include file (just to keep things clean), but this is good for a demo.

现在是jade部分:接下来需要呈现值,以便javascript能够在客户端接收它们。将这些值写入索引文件的简单方法。因为这是一个单页应用程序(角),所以这个页面总是首先被加载。我认为这应该是一个javascript包含文件(只是为了保持整洁),但是这对于演示来说是很好的。

app/controllers/index.js:

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

app/views/index.jade:

app / views / 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};

In my rendered html, this gives me a nice little script:

在我渲染的html中,这给了我一个漂亮的小脚本:

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

From this point it's easy for angular to utilize the code.

从这一点来说,角化代码很容易使用。

#1


141  

It's a little late but...

有点晚了,但是……

script.
  loginName="#{login}";

This is working fine in my script. In Express, I am doing this:

这在我的脚本中运行得很好。在快递上,我这样做:

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

I guess the latest jade is different?

我猜最新的玉器不同吧?

Merc.

芝加哥商业交易所。

edit: added "." after script to prevent Jade warning.

编辑:添加“。”后,防止玉石警告。

#2


81  

!{} is for unescaped code interpolation, which is more suitable for objects

{}是为未转义的代码插值,更适合对象

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>

The idea is to prevent the attacker to:

目的是防止攻击者:

  1. Break out of the variable: JSON.stringify escapes the quotes
  2. 跳出变量:JSON。stringify转义引号
  3. Break out of the script tag: if the variable contents (which you might not be able to control if comes from the database for ex.) has a </script> string, the replace statement will take care of it
  4. 跳出脚本标记:如果变量内容(如果来自数据库的话,您可能无法控制)有一个字符串,则replace语句将处理它

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

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


#{} is for escaped string interpolation, which is suitable only if you're working with strings. It does not work with objects

#{}用于转义字符串插值,这只适用于处理字符串。它与对象无关。

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

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

#3


2  

See this question: JADE + EXPRESS: Iterating over object in inline JS code (client-side)?

看到这个问题了吗:JADE + EXPRESS:在内联JS代码(客户端)中迭代对象?

I'm having the same problem. Jade does not pass local variables in (or do any templating at all) to javascript scripts, it simply passes the entire block in as literal text. If you use the local variables 'address' and 'port' in your Jade file above the script tag they should show up.

我也有同样的问题。Jade不向javascript脚本传递本地变量(或做任何模板),它只是将整个块作为文本传入。如果您在脚本标签上方的翡翠文件中使用本地变量'address'和'port',那么它们应该会出现。

Possible solutions are listed in the question I linked to above, but you can either: - pass every line in as unescaped text (!= at the beginning of every line), and simply put "-" before every line of javascript that uses a local variable, or: - Pass variables in through a dom element and access through JQuery (ugly)

可能的解决方案在我链接到上面的问题中列出,但是您也可以:-将每一行作为未转义的文本(!=在每一行的开头),并在每一行使用本地变量的javascript之前写上“-”,或者:-通过dom元素传入变量并通过JQuery访问(丑陋)

Is there no better way? It seems the creators of Jade do not want multiline javascript support, as shown by this thread in GitHub: https://github.com/visionmedia/jade/pull/405

难道没有更好的办法吗?看起来Jade的创建者不需要多行javascript支持,如GitHub中的这个线程所示:https://github.com/visionmedia/jade/pull/405

#4


2  

In my case, I was attempting to pass an object into a template via an express route (akin to OPs setup). Then I wanted to pass that object into a function I was calling via a script tag in a pug template. Though lagginreflex's answer got me close, I ended up with the following:

在我的例子中,我试图通过一个快速通道将一个对象传递给一个模板(类似于OPs设置)。然后,我想将该对象传递给我正在通过pug模板中的脚本标记调用的函数。虽然lagginreflex的回答让我很接近,但我最终还是选择了以下几点:

script.
    var data = JSON.parse('!{JSON.stringify(routeObj)}');
    funcName(data)

This ensured the object was passed in as expected, rather than needing to deserialise in the function. Also, the other answers seemed to work fine with primitives, but when arrays etc. were passed along with the object they were parsed as string values.

这确保了对象按预期传入,而不需要在函数中反序列化。另外,对于原语,其他的答案似乎也可以,但是当数组等与对象一起传递时,它们被解析为字符串值。

#5


0  

Here's how I addressed this (using a MEAN derivative)

下面是我如何解决这个问题(使用平均导数)

My variables:

我的变量:

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

First I had to make sure that the necessary config variables were being passed. MEAN uses the node nconf package, and by default is set up to limit which variables get passed from the environment. I had to remedy that:

首先,我必须确保传递了必需的配置变量。MEAN使用节点nconf包,默认设置为限制从环境中传递哪些变量。我必须补救:

config/config.js:

配置/ config.js:

original:

原:

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

after modifications:

修改后:

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

Now I can set my variables like this:

现在我可以这样设置变量:

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

Note: I reset the "heirarchy indicator" to "__" (double underscore) because its default was ":", which makes variables more difficult to set from bash. See another post on this thread.

注意:我将“继承指标”重置为“__”(双下划线),因为它的默认值是“:”,这使得从bash设置变量变得更加困难。请参阅此线程上的另一篇文章。

Now the jade part: Next the values need to be rendered, so that javascript can pick them up on the client side. A straightforward way to write these values to the index file. Because this is a one-page app (angular), this page is always loaded first. I think ideally this should be a javascript include file (just to keep things clean), but this is good for a demo.

现在是jade部分:接下来需要呈现值,以便javascript能够在客户端接收它们。将这些值写入索引文件的简单方法。因为这是一个单页应用程序(角),所以这个页面总是首先被加载。我认为这应该是一个javascript包含文件(只是为了保持整洁),但是这对于演示来说是很好的。

app/controllers/index.js:

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

app/views/index.jade:

app / views / 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};

In my rendered html, this gives me a nice little script:

在我渲染的html中,这给了我一个漂亮的小脚本:

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

From this point it's easy for angular to utilize the code.

从这一点来说,角化代码很容易使用。