我有一个Gulp插件,stratic-paginate-indexes
:
'use strict';
var through2 = require('through2'),
path = require('path');
function makePage(originalFile, page, pageNumber) {
var newFile = originalFile.clone();
newFile.data = newFile.data || {};
newFile.data.posts = page;
newFile.data.page = pageNumber;
if (pageNumber === 1) return newFile;
var filePath = path.parse(newFile.path);
filePath.dir = path.join(filePath.dir, 'page', pageNumber.toString());
newFile.path = path.format(filePath);
return newFile;
}
module.exports = function() {
return through2.obj(function(file, enc, callback) {
var pageNumber = 1,
pageFiles = [],
page = [];
while (file.data.posts > 0) {
page = file.data.posts.splice(5);
var newFile = makePage(file, page, pageNumber);
pageFiles.push(newFile);
pageNumber++;
}
// Per-index page counts
pageFiles.forEach(function(file) {
file.data.pageCount = pageFiles.length;
this.push(file);
}, this);
callback();
});
};
此插件旨在接收代表博客帖子索引的Vinyl文件。对于索引file
,file.data.posts
是一组Vinyl文件,表示要包含在呈现页面上的各个帖子。这是我在以下方面使用的Gulp任务:
var jade = require('gulp-jade');
var rename = require('gulp-rename');
var remark = require('gulp-remark');
var remarkHtml = require('remark-html');
var adjustHeaders = require('remark-rewrite-headers');
var parse = require('stratic-parse-header');
var dateInPath = require('stratic-date-in-path');
var postsToIndex = require('stratic-posts-to-index');
var paginateIndexes = require('stratic-paginate-indexes');
var addsrc = require('gulp-add-src');
gulp.task('post-index', function() {
return gulp.src('src/blog/*.md')
.pipe(parse())
.pipe(remark().use(remarkHtml).use(adjustHeaders))
.pipe(dateInPath())
.pipe(addsrc('src/blog/index.jade'))
.pipe(postsToIndex('index.jade'))
.pipe(paginateIndexes())
.pipe(jade({pretty: true, basedir: __dirname}))
.pipe(rename({ extname: '.html' }))
.pipe(gulp.dest('dist/blog'));
});
但是,此设置实际上并未输出任何索引页。
最初,您看到的while
循环中的逻辑是使用Array.prototype.forEach
和Array.prototype.shift
实现的:
file.data.posts.forEach(function(post) {
page.push(post);
if (page.length === 10) {
var newFile = makePage(file, page, pageNumber);
pageFiles.push(newFile);
page = [];
pageNumber++;
}
});
// Handle the last page which won't have 10 posts (and so will fail the above `if` test)
if (page.length > 0) pageFiles.push(makePage(file, page, pageNumber));
这实际上创建了索引文件,但使用了 super 奇怪的file.data.posts
值。如果我没记错的话,看起来就像每个页面file.data.posts
被设置为最后几个帖子(即最终页面的值file.data.posts
)但我并不认为发生了什么。
无论如何,我有点不知所措。这对我来说似乎是一个非常简单的代码,而且我花费了大量的时间来尝试调试。
(请注意,我也是管道中其他几个插件的作者。可能是我在那些造成这个神秘错误的行为中做了些蠢事。在Gulpfile中发布的明显例外是stratic-paginate-indexes
,所以请随时查看其他模块,如果问题来自哪里。)
修改
在修复了答案中指出的一些错误之后,现在实现了:
while (file.data.posts.length > 0) {
page = file.data.posts.splice(0, 5);
var newFile = makePage(file, page, pageNumber);
pageFiles.push(newFile);
pageNumber++;
}
然而由于某种原因,这导致输出无限系列的页面,每个页面都具有与原始file.data.posts
相同的前5个元素。几乎就像我使用Array.prototype.slice
一样(除了显然我不是)。
答案 0 :(得分:1)
对于索引文件,
file.data.posts
是代表个别帖子的乙烯基文件数组
如果这是真的那么你的问题是以下两行:
while (file.data.posts > 0) {
page = file.data.posts.splice(5);
在第一行中,您将数组本身与0进行比较。您需要比较数组的length
:
while (file.data.posts.length > 0) {
但这还不够。在第二行中,您使用单个参数调用Array.splice()
。除了file.data.posts
的前5个元素之外,这将删除所有内容,因此file.data.posts.length
将永久保留在5. Boom。无限循环。
如果我正确理解你,你想把数组分成5组。在这种情况下,第二行应该是这样的:
page = file.data.posts.splice(0, 5);
这会将前5个帖子放入page
并从file.data.posts
中删除。
答案 1 :(得分:0)
问题在于这一行:
var newFile = originalFile.clone();
不幸的是,.clone()
函数的Vinyl文档不正确(至少对于Vinyl 0.4.x,这是你用Gulp 3获得的)。文档声明.clone()
做了深层克隆,但实际上它做了一个浅层克隆。使用black magic,您可以强制调用进行深度克隆:
var newFile = originalFile.clone(true);
请参阅gulpjs/vinyl#125。