3

背景

我一直在使用带有 hogan.js 任务的 grunt.js 来为我们的内部文档构建静态 HTML。我边走边学 JavaScript,但我已经让任务足够好地用于布局和页面,但它确实有助于我们的工作流程让 hogan 任务将小胡子部分呈现为 HTML,如本要点中的示例:https ://gist.github.com/4132781

当前设置和我想要完成的任务

我们所有的小胡子部分都在一个名为“partials”的文件夹中。理想情况下,当 grunt 构建运行时,hogan 任务将从 partials 文件夹中获取任何部分,并将它们插入到 HTML 中,无论它们被引用到哪里(也显示在 gist 中)。

我不想要的

我不想在任务或任务配置中定义每个部分。这行不通,我们有大约 200 个部分并且还在增长,所以我们需要让任务扫描一个文件夹并根据文件名或其他内容获取部分。我也不想使用不同的语言或构建工具。我们使用了 Jade、一些基于降价的文档构建器,以及其他一些。如果我们可以像描述的那样渲染局部,我们的状态会很好!

有可能做到这一点吗?提前感谢您的任何反馈

4

1 回答 1

5

我正在查看您的代码,其中一些选项与您引用的文件名不匹配。

这是我更新您提供的代码以允许渲染部分的尝试:

咕噜声

src 是您正在构建的可能包含部分的页面列表。在这种情况下,components.mustache 将位于 'docs/components/templates/pages/components.mustache'

将布局选项更新为用于所有页面(包括 components.mustache)的 layout.mustache

将路径对象添加到具有部分文件夹路径的选项。所有这些部分都将被读取和编译并存储在 options.partials 中,以供以后在 grunt 任务中使用。

module.exports = function(grunt) {

  'use strict';

  // Project configuration
  grunt.initConfig({
    pkg: '<json:package.json>',
    meta: {
      banner:
      '/**\n' +
      '* <%= pkg.name %>.js v<%= pkg.version %> by @fat & @mdo\n' +
      '* Copyright <%= grunt.template.today("yyyy") %> <%= pkg.author %>\n' +
      '* http://www.apache.org/licenses/LICENSE-2.0.txt\n' +
      '*/'
    },

    // Build HTML docs from .mustache files
    hogan: {
      production: {
        src: 'docs/components/templates/pages/*.mustache',
        dest: 'docs/components/FILE.html',
        options: {
          title:      'Sellside',
          url:        'docs',
          setAccount: 'NA',
          setSiteId:  'NA',
          layout:     'docs/components/templates/layout.mustache',
          dev:        true,
          docs:       true,
          app:        false,
          website:    false,
          paths: {
            partials: 'docs/components/templates/partials/*.mustache'
          }
        }
      }
    }
  });

  // Load npm tasks.
  grunt.loadNpmTasks('grunt-contrib');

  // Load local tasks.
  grunt.loadTasks('tasks');

  grunt.registerTask('default', 'hogan');

};

hogan.js

更新此任务以读取所有部分并编译它们。

正在更新帮助程序以将“body”部分(即编译页面)添加到 options.partials 列表中。

然后将 options.partials 传递给 hogan.render 方法,因此所有部分都可用于所有页面。

/*
 * Build HTML from mustache files
 * https://github.com/sellside/ui/grunt.js
 *
 * Copyright (c) 2012 Sellside
 * Authored by Jon Schlinkert
 */

module.exports = function(grunt) {

  // Grunt utilities.
  var task   = grunt.task,
    file     = grunt.file,
    utils    = grunt.util,
    log      = grunt.log,
    verbose  = grunt.verbose,
    fail     = grunt.fail,
    option   = grunt.option,
    config   = grunt.config,
    template = grunt.template,
    _        = utils._

  // external dependencies
  var fs   = require('fs'),
    hogan  = require('hogan');


  // ==========================================================================
  // TASKS
  // ==========================================================================
  grunt.registerMultiTask('hogan', 'Compile mustache files to HTML with hogan.js', function() {

    var data     = this.data,
      src        = grunt.file.expandFiles(this.file.src),
      dest       = grunt.template.process(data.dest),

      // Options are set in gruntfile
      defaults   = {
        production:  false,
        docs:        false,
        title:      'Sellside',
        setAccount: 'NA',
        setSiteId:  'NA',
        layout:     'docs/templates/layout.mustache',
        paths: {},
        partials: {}
      },

      options = _.extend(defaults, this.data.options || {})

      !src && grunt.warn('Missing src property.')
      if(!src) return false

      !dest && grunt.warn('Missing dest property')
      if(!dest) return false

    var done         = this.async()
    var srcFiles     = file.expandFiles(src)

    if(options.paths.partials) {

      var partials = grunt.file.expandFiles(options.paths.partials);
      log.writeln('Compiling Partials...');
      partials.forEach(function(filepath) {
        var filename = _.first(filepath.match(/[^\\\/:*?"<>|\r\n]+$/i)).replace(/\.mustache$/, '');
        log.writeln(filename.magenta);

        var partial = fs.readFileSync(filepath, 'utf8');
        options.partials[filename] = hogan.compile(partial);

      });
      log.writeln();
}

    try {
      options.layout   = fs.readFileSync(options.layout, 'utf8')
      options.layout   = hogan.compile(options.layout, {
        sectionTags: [{
          o: '_i',
          c: 'i'
        }]
      })
    } catch(err) {
      grunt.warn(err) && done(false)
      return
    }

    srcFiles.forEach(function(filepath) {
      var filename = _.first(filepath.match(/[^\\\/:*?"<>|\r\n]+$/i)).replace(/\.mustache$/, '')

      grunt.helper('hogan', filepath, filename, options, function(err, result) {
        err && grunt.warn(err) && done(false)
        if(err) return

        file.write(dest.replace('FILE', filename), result)
      })
    })

    done()
  })

  // ==========================================================================
  // HELPERS
  // ==========================================================================
  grunt.registerHelper('hogan', function(src, filename, options, callback) {
    log.writeln('Compiling ' + filename.magenta);

    var page                = fs.readFileSync(src, 'utf8'),
        html                = null,
        layout              = options.layout,
        context             = {};

        context[filename]   = 'active';
        context._i          = true;
        context.production  = options.production;
        context.docs        = options.docs;
        context.setAccount  = options.setAccount;
        context.setSiteId   = options.setSiteId;

    var title               = _.template("<%= page == 'Index' ? site : page + ' · ' + site %>")
    context.title           = title({
      page: _(filename).humanize().replace('css', 'CSS'),
      site: options.title
    })
    try {
      page = hogan.compile(page, {
        sectionTags: [{
          o: '_i',
          c: 'i'
        }]
      })

      options.partials.body = page;
      page = layout.render(context, options.partials)

      callback(null, page)
    } catch(err) {
      callback(err)
      return
    }
  })
};

需要注意的一件事是,如果要将数据传递到部分中,则需要将其添加到文件 layout.render 调用中的上下文对象中。

希望这一切都有意义并帮助您。

于 2012-11-28T03:16:40.607 回答