繁体   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