web-dev-qa-db-ja.com

jadeテンプレートファイルからスクリプトファイルに変数を渡す方法は?

Javascriptファイルに渡されないjadeテンプレートファイル(index.jade)で宣言された変数(config)に問題があるため、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});

Localhost(自分のマシン)で開発モード(NODE_ENV = development)でサイトを実行しています。デバッグにはノードインスペクターを使用していますが、public/javascripts/app.jsで構成変数が未定義であることがわかりました。

何か案は??ありがとう!!

111

little遅いですが...

script.
  loginName="#{login}";

これは私のスクリプトではうまく機能しています。 Expressでは、これを行っています。

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

最新のヒスイは違うと思う?

メルク。

編集:「。」を追加Jadeの警告を防ぐためのスクリプトの後。

158
Merc

- !{}エスケープされていないコード 補間で、オブジェクト

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>

アイデアは、攻撃者が以下を行うのを防ぐことです。

  1. 変数から抜け出す:JSON.stringifyは引用符をエスケープします
  2. スクリプトタグから抜け出す:変数の内容(たとえば、データベースからのものかどうかを制御できない場合があります)が</script>文字列を持っている場合、replaceステートメントが処理します

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


#{}はエスケープされた 文字列補間 で、文字列を使用している場合にのみ適しています。オブジェクトに対しては動作しません

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

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

私の場合、エクスプレスルート(OPのセットアップと同様)を介してテンプレートにオブジェクトを渡そうとしました。次に、そのオブジェクトを、pugテンプレートのscriptタグを介して呼び出していた関数に渡したいと思いました。 lagginreflex's answer が私を近づけましたが、私は次のようになりました:

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

これにより、関数で逆シリアル化する必要がなく、オブジェクトが期待どおりに渡されることが保証されました。また、他の回答はプリミティブではうまく機能するように見えましたが、配列などがオブジェクトとともに渡されると、文字列値として解析されました。

5
Kyle Gillen

あなたが私のようで、変数を渡すこの方法をたくさん使うなら、ここに書き込み不要のコードの解決策があります。

Node.jsルートで、次のようにwindowというオブジェクトに変数を渡します。

router.get('/', function (req, res, next) {
    res.render('index', {
        window: {
            instance: instance
        }
    });
});

次に、pug/jadeレイアウトファイル(block contentの直前)で、次のようにそれらを取得します。

if window
    each object, key in window
        script.
            window.!{key} = !{JSON.stringify(object)};

Layout.pugファイルが各pugファイルとともにロードされるため、変数を何度も「インポート」する必要はありません。

このようにして、window 'magically'に渡されるすべての変数/オブジェクトは、Reactjs、Angular、...またはVanilla javascriptで使用できるブラウザの実際のwindowオブジェクトになります。

4
Sam

私がこれに対処した方法は次のとおりです(MEAN派生物を使用)

私の変数:

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

最初に、必要な構成変数が渡されていることを確認する必要がありました。 MEANはノードnconfパッケージを使用し、デフォルトでは環境から渡される変数を制限するように設定されています。私はそれを改善しなければなりませんでした:

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

注:デフォルトでは「:」であったため、bashから変数を設定するのがより難しくなるため、「heirarchy indicator」を「__」(二重アンダースコア)にリセットしました。このスレッドに関する別の投稿を参照してください。

さて、jadeパート:次に、JavaScriptがクライアント側でそれらを取得できるように、値をレンダリングする必要があります。これらの値をインデックスファイルに書き込む簡単な方法。これは1ページのアプリ(角度付き)であるため、このページは常に最初に読み込まれます。理想的には、これはjavascriptのインクルードファイルである必要があります(物事をきれいに保つためだけです)が、これはデモには適しています。

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:

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

この時点から、angularがコードを利用しやすくなります。

2
Michael

この質問を参照してください: JADE + EXPRESS:インラインJSコード(クライアント側)でオブジェクトを反復処理しますか?

私は同じ問題を抱えています。 Jadeはjavascriptスクリプトにローカル変数を渡さず(またはテンプレート化をまったく行いません)、単にブロック全体をリテラルテキストとして渡します。スクリプトタグの上のJadeファイルでローカル変数「address」と「port」を使用すると、表示されるはずです。

上記の質問に可能な解決策がリストされていますが、次のいずれかを実行できます。-すべての行をエスケープされていないテキストとして渡し(!=を各行の先頭に)、単純に「-」を使用するjavascriptの各行ローカル変数、または:-dom要素を介して変数を渡し、JQueryを介してアクセスします(ugい)

より良い方法はありませんか? GitHubの次のスレッドに示されているように、Jadeの作成者は複数行のJavaScriptサポートを望まないようです。 https://github.com/visionmedia/jade/pull/405

2
Varun Singh