jade 템플릿 파일에서 스크립트 파일로 변수를 전달하는 방법은 무엇입니까?


119

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

다음은 충돌하는 내 자바 스크립트 파일의 일부입니다 (public / javascripts / app.js).

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

나는 localhost (내 자신의 컴퓨터)에서 개발 모드 (NODE_ENV = development)에서 사이트를 실행하고 있습니다. 디버깅을 위해 node-inspector를 사용하고 있는데, config 변수가 public / javascripts / app.js에 정의되어 있지 않다고 말했습니다.

어떤 아이디어 ?? 감사!!


답변:


174

그것은이다 조금 늦었지만 ...

script.
  loginName="#{login}";

이것은 내 스크립트에서 잘 작동합니다. Express에서는 다음을 수행합니다.

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

최신 비취가 다른 것 같아요?

Merc.

편집 : "."추가 Jade 경고를 방지하기 위해 스크립트 후.


1
답변을 받아 주셔서 감사합니다! 그렇다면 코드 의 실제 문제 는 무엇 입니까?
Merc 2015 년

예, 템플릿의 지역 변수를 따옴표와 # {} 표시기로 래핑하여이 작업을 수행했습니다.
Askdesigners

이 대답은 위험하며 lagginreflex의 대답은 문자열을 올바르게 인코딩합니다 (로그인 이름의 줄 바꿈으로 코드 실행이 가능할 수 있음).
Paul Grove

그래서 문제는 작은 따옴표 뿐이고 이중은 예상되는 것입니까?
Augustin Riedinger 2017 년

나에게 문제는 점이었다. 스크립트 블록 끝에있었습니다. "스크립트"키워드 뒤에 점이 있으면 매력처럼 작동합니다. 감사합니다!
Mirko

103

!{}위한 이스케이프 코드 에 더 적합하다 보간 개체

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>

1
훌륭한 대답입니다! 나는이 주제를 20 분 이상 검색해 왔으며 다른 답변은! {}와 # {}의 차이를 언급하지 않았습니다. 이번 내내 저는! {]가 # {}의 비추천 제품이라고 생각했습니다 ... 다시 한 번 감사드립니다.
Patrick E.

맨 위로! 좋은 대답입니다.
Scarysize

훌륭한 대답이며 개체에 대해 작동합니다! Btw, JSON전역 개체입니까? 다른 라이브러리를 가져 오지 않고도 작동하는 것처럼 보였습니다. 그렇다면 브라우저 지원은 어떻습니까?
chharvey

@chharvey JSON 은 자바 스크립트 언어 내장 (날짜 또는 수학과 같은)이며 모든 브라우저에서 지원합니다.
laggingreflex

1
이것이 최선의 대답이라는 데 동의했지만 잠재적으로 위험한 문자열을 피할 수있는 올바른 장소라고 생각하지 않습니다. IMO replace는이 코드 에서 호출 을 생략하고 다른 입력과 마찬가지로이 값을 처리하는 것이 좋습니다 . JSON.stringify는 유효한 자바 스크립트 (또는 실패)를 생성하도록 보장되며, 잠재적으로 위험한이 값을 메모리에 저장 한 후에는 사용하기 전에 필요에 따라이를 삭제해야합니다.
Riley Lark

9

제 경우에는 익스프레스 경로 (OPs 설정과 유사)를 통해 개체를 템플릿에 전달하려고했습니다. 그런 다음 퍼그 템플릿의 스크립트 태그를 통해 호출 한 함수에 해당 개체를 전달하고 싶었습니다. lagginreflex의 답변 이 나를 가까워 졌지만 결국 다음과 같이 끝났습니다.

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

이렇게하면 함수에서 역 직렬화 할 필요없이 개체가 예상대로 전달됩니다. 또한 다른 답변은 기본 요소에서 잘 작동하는 것처럼 보였지만 배열 등이 객체와 함께 전달되면 문자열 값으로 구문 분석되었습니다.


7

나처럼 변수를 많이 전달하는이 방법을 사용하는 경우 쓰기없는 코드 솔루션이 있습니다.

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'마법처럼' 전달 된 모든 변수 / 객체가 window브라우저 의 실제 객체에 들어가서 Reactjs, Angular, ... 또는 바닐라 자바 ​​스크립트에서 사용할 수 있습니다.


1
이것은 내가 본 최고의 대답입니다.
Tohir 2010 년

3

이 문제를 해결 한 방법은 다음과 같습니다 (평균 파생 상품 사용).

내 변수 :

{
  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

참고 : 기본값이 ":"이기 때문에 "heirarchy indicator"를 "__"(이중 밑줄)로 재설정하여 bash에서 변수를 설정하기가 더 어렵습니다. 이 스레드에 대한 다른 게시물을 참조하십시오.

이제 jade 부분 : 다음으로 값을 렌더링해야 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>        

이 시점에서 앵귤러는 코드를 쉽게 활용할 수 있습니다.


이것은 받아 들여진 대답이 이미 말하는 것을 말하는 매우 긴 바람의 방법입니다. 또한 MEAN, nconf 등을 언급하는 것은 관련이 없습니다. 문제는 개발자 스택을 어떻게 수행했는지가 아니라 클라이언트에 변수를 전달하는 방법에 관한 것입니다. 이 답변에 여전히 많은 노력을 기울 였으므로 반대 투표는 아닙니다.
Mrchief

지나치게 복잡
andygoestohollywood

2

이 질문을보십시오 : JADE + EXPRESS : 인라인 JS 코드 (클라이언트 측)에서 객체를 반복합니까?

나는 같은 문제가 있습니다. Jade는 지역 변수를 자바 스크립트 스크립트에 전달하지 않습니다 (또는 템플릿을 전혀 수행하지 않음). 단순히 전체 블록을 리터럴 텍스트로 전달합니다. Jade 파일에서 스크립트 태그 위의 지역 변수 'address'와 'port'를 사용하면 표시되어야합니다.

가능한 해결책은 위에서 링크 한 질문에 나열되어 있지만 다음 중 하나를 수행 할 수 있습니다.-모든 줄을 이스케이프 처리되지 않은 텍스트 (모든 줄의 시작 부분에! =)로 전달하고 javascript의 모든 줄 앞에 "-"를 입력합니다. 지역 변수 또는 :-dom 요소를 통해 변수를 전달하고 JQuery를 통해 액세스합니다.

더 좋은 방법이 없습니까? GitHub : https://github.com/visionmedia/jade/pull/405의 스레드에서 볼 수 있듯이 Jade 제작자는 여러 줄 자바 스크립트 지원을 원하지 않는 것 같습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.