web-dev-qa-db-fra.com

Comment passer variable d'un fichier de modèle jade à un fichier de script?

J'ai des problèmes avec une variable (config) déclarée dans un fichier modèle jade (index.jade) qui n'est pas transmise à un fichier javascript, ce qui provoque le blocage de javascript. Voici le fichier (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')

Voici une partie de mon app.js (côté serveur):

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

Et voici une partie de mon fichier javascript qui se bloque (public/javascripts/app.js):

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

J'exécute le site en mode de développement (NODE_ENV = développement) sur localhost (ma propre machine). J'utilise node-inspector pour le débogage, qui m'a dit que la variable config n'était pas définie dans public/javascripts/app.js.

Des idées?? Merci!!

111

C'est un pe tard mais ...

script.
  loginName="#{login}";

Cela fonctionne très bien dans mon script. Dans Express, je fais ceci:

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

Je suppose que le dernier jade est différent?

Merc.

edit: ajouté "." après script pour éviter l'avertissement Jade.

158
Merc

!{} est pour l’interpolation code non échappé , qui convient mieux aux objets

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>

L'idée est d'empêcher l'attaquant de:

  1. Sortez de la variable: JSON.stringify échappe aux guillemets
  2. Sort de la balise de script: si le contenu de la variable (que vous ne pourrez peut-être pas contrôler si provient de la base de données, par exemple) a un </script> chaîne, l'instruction de remplacement s'en chargera

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


#{} est utilisé pour un caractère d'échappement interpolation de chaîne , qui ne convient que si vous utilisez des chaînes. Cela ne fonctionne pas avec des objets

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

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

Dans mon cas, j'essayais de passer un objet dans un modèle via un itinéraire express (semblable à la configuration des OP). Ensuite, j'ai voulu transmettre cet objet à une fonction que j'appelais via une balise script dans un modèle pug. Bien que réponse de lagginreflex me rapproche, je me suis retrouvé avec ce qui suit:

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

Cela garantissait que l'objet était passé comme prévu, plutôt que de devoir se désérialiser dans la fonction. En outre, les autres réponses semblaient bien fonctionner avec les primitives, mais lorsque des tableaux, etc., étaient passés avec l'objet, ils étaient analysés en tant que valeurs de chaîne.

5
Kyle Gillen

Si vous êtes comme moi et que vous utilisez beaucoup cette méthode pour passer des variables, voici une solution sans code.

Dans votre route node.js, transmettez les variables dans un objet appelé window, comme ceci:

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

Ensuite, dans votre fichier de formatage carlin/jade (juste avant le block content), vous les sortez comme ceci:

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

Comme mon fichier layout.pug est chargé avec chaque fichier pug, je n'ai pas besoin d '"importer" mes variables à plusieurs reprises.

De cette façon, toutes les variables/objets passés à window '' comme par magie '' se retrouvent dans le véritable objet window de votre navigateur, où vous pouvez les utiliser dans JavaScript, comme Reactjs, Angular, ... ou Vanilla.

4
Sam

Voici comment j'ai traité ceci (en utilisant un dérivé de MEAN)

Mes variables:

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

Tout d'abord, je devais m'assurer que les variables de configuration nécessaires étaient bien transmises. MEAN utilise le package node nconf et est configuré par défaut pour limiter les variables transmises par l'environnement. J'ai dû remédier à cela:

config/config.js:

original:

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

après modifications:

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

Maintenant, je peux définir mes variables comme ceci:

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

Remarque: je réinitialise l'indicateur "heirarchy" sur "__" (double trait de soulignement) car sa valeur par défaut était ":", ce qui rend les variables plus difficiles à définir à partir de bash. Voir un autre post sur ce fil.

Maintenant la partie jade: Ensuite, les valeurs doivent être rendues, pour que javascript puisse les récupérer côté client. Un moyen simple d'écrire ces valeurs dans le fichier d'index. Comme il s'agit d'une application d'une page (angulaire), cette page est toujours chargée en premier. Je pense que, dans l’idéal, il devrait s’agir d’un fichier d’inclusion javascript (juste pour que tout reste clair), mais c’est bien pour une démo.

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

Dans mon rendu HTML, cela me donne un joli petit script:

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

À partir de ce moment, il est facile pour angular d'utiliser le code.

2
Michael

Voir cette question: JADE + EXPRESS: Itérer sur un objet dans un code JS en ligne (côté client)?

J'ai le même problème. Jade ne transmet pas de variables locales (ou ne modifie aucun modèle) aux scripts javascript, il passe simplement le bloc entier sous forme de texte littéral. Si vous utilisez les variables locales 'adresse' et 'port' dans votre fichier Jade, au-dessus de la balise script, elles doivent s'afficher.

Les solutions possibles sont énumérées dans la question ci-dessus, mais vous pouvez soit: - passer chaque ligne sous forme de texte non échappé (! = Au début de chaque ligne), et simplement mettre "-" avant chaque ligne de javascript variable locale, ou: - Passer les variables à travers un élément dom et accéder à JQuery (moche)

N'y a-t-il pas de meilleur moyen? Il semble que les créateurs de Jade ne veulent pas de support javascript multiligne, comme le montre ce fil dans GitHub: https://github.com/visionmedia/jade/pull/405

2
Varun Singh