簡體   English   中英

用Grunt從一個Jade模板創建多個HTML文件

[英]Creating multiple HTML files from a single Jade template with Grunt

我正在尋找使用Grunt從一個Jade模板創建多個HTML文件。

這是我在做什么:

  1. 從外部文件獲取JSON數據
  2. 遍歷該對象
  3. 為該JSON對象中的每個值創建一個grunt配置任務

這是我的代碼:

neighborhoods = grunt.file.readJSON('data/neighborhoods.json');

for(var i = 0; i < Object.keys(neighborhoods).length; i++) {

    var neighborhood = {
        "title" : Object.keys(neighborhoods)[i],
        "data"  : neighborhoods[Object.keys(neighborhoods)[i]]
    };

    grunt.config(['jade', neighborhood.title], {
        options: {
            data: function() {
                return {
                    neighborhoods: neighborhood.data
                }
            }
        },
        files: {
            "build/neighborhoods/<%= neighborhood.title %>.html": "layouts/neighborhood.jade"
        }
    });
}

我遇到的問題是

Running "jade:Art Museum" (jade) task
Warning: An error occurred while processing a template (Cannot read property 'title' of undefined). Use --force to continue.

如果我將文件名設為字符串,則可以正常運行,但顯然可以使用相同的文件名創建所有文件,因此只能創建一個文件。 我需要使該文件名動態。

我在這里找到解決方案:

使用全局變量在Grunt中設置構建輸出路徑

問題在於模塊會在設置這些全局變量之前導出,因此它們在initConfig()任務中定義的后續任務中都未定義。


這成功了!

var neighborhoods = grunt.file.readJSON('data/neighborhoods.json');

for(var i = 0; i < Object.keys(neighborhoods).length; i++) {

    var neighborhood = {
        "title" : Object.keys(neighborhoods)[i],
        "data"  : neighborhoods[Object.keys(neighborhoods)[i]]
    };

    /* 
     * DEFINE VALUE AS GRUNT OPTION
     */

    grunt.option('neighborhood_title', neighborhood.title);

    grunt.config(['jade', neighborhood.title], {
        options: {
            data: function() {
                return {
                    neighborhoods: neighborhood.data,
                    neighborhood_title: neighborhood.title
                }
            }
        },

        /* 
         * OUTPUT GRUNT OPTION AS FILENAME
         */

        files: {
            "build/neighborhoods/<%= grunt.option('neighborhood_title') %>.html": "layouts/neighborhood.jade"
        }
    });
}


這將產生所需的輸出:

Running "jade:East Passyunk" (jade) task
File build/neighborhoods/Society Hill.html created.

Running "jade:Fishtown" (jade) task
File build/neighborhoods/Society Hill.html created.

Running "jade:Graduate Hospital" (jade) task
File build/neighborhoods/Society Hill.html created.

Running "jade:Midtown Village" (jade) task
File build/neighborhoods/Society Hill.html created.

Running "jade:Northern Liberties" (jade) task
File build/neighborhoods/Society Hill.html created.

...

我知道這是一篇舊文章,但在嘗試解決類似問題的同時,我一直回到這里。 我想使用for循環從單個jade模板文件中輸出多個html文件。

我遇到的兩個問題是設置輸出文件名(JavaScript對象文字KEY)並確保立即運行內聯javascript函數,以便循環變量可用。

這是我完整的帶有注釋的源代碼。 我希望這對在這篇文章中遇到麻煩的其他人有用。

Gruntfile.js:

module.exports = function(grunt) {

  // Create basic grunt config (e.g. watch files)
  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),
    watch: {
      grunt: { files: ['Gruntfile.js'] },
      jade: {
        files: 'src/*.jade',
        tasks: ['jade']
      }
    }
  });

  // Load json to populate jade templates and build loop
  var json = grunt.file.readJSON('test.json');

  for(var i = 0; i < json.length; i++) {
      var obj = json[i];

      // For each json item create a new jade task with a custom 'target' name.
      // Because a custom target is provided don't nest options/data/file parameters 
      // in another target like 'compile' as grunt wont't be able to find them 
      // Make sure that functions are called using immediate invocation or the variables will be lost
      // http://stackoverflow.com/questions/939386/immediate-function-invocation-syntax      
      grunt.config(['jade', obj.filename], {
        options: {
            // Pass data to the jade template
            data: (function(dest, src) {
                return {
                  myJadeName: obj.myname,
                  from: src,
                  to: dest
                };
            }()) // <-- n.b. using() for immediate invocation
        },
        // Add files using custom function
        files: (function() {
          var files = {};
          files['build/' + obj.filename + '.html'] = 'src/index.jade';
          return files;
        }()) // <-- n.b. using () for immediate invocation
      });
  }

  grunt.loadNpmTasks('grunt-contrib-jade');
  grunt.loadNpmTasks('grunt-contrib-watch');

  // Register all the jade tasks using top level 'jade' task
  // You can also run subtasks using the target name e.g. 'jade:cats'
  grunt.registerTask('default', ['jade', 'watch']);
};

src / index.jade:

doctype html
html(lang="en")
  head
    title= pageTitle
    script(type='text/javascript').
      if (foo) {
         bar(1 + 5)
      }
  body
    h1 #{myJadeName} - node template engine    
    #container.col
      p.
        Jade is a terse and simple
        templating language with a
        strong focus on performance
        and powerful features.

test.json:

[{
    "id" : "1", 
    "filename"   : "cats",
    "tid" : "2016-01-01 23:35",
    "myname": "Cat Lady"
},
{
    "id" : "2", 
    "filename"   : "dogs",
    "tid" : "2016-01-01 23:45",
    "myname": "Dog Man"
}]

運行“ grunt”后,輸出應為:

build/cats.html
build/dogs.html

遇到了我正在從事的項目的類似要求,但無法使其正常工作。 由於grunt選項對所有任務都具有相同的值(最后一個值),因此我一直只生成一個文件。 因此,我最終使用<%= grunt.task.current.target %>作為文件名,在您的情況下,該文件名與neighborhood.title相同。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM