简单来说,TreeSaver有个函数:treesaver.layout.Grid.best = function(content, grids, breakRecord) { 这个函数根据内容,选择最合适的模板。
这个函数的逻辑就是TreeSaver的模板匹配算法。
下面是对这个函数以及调用他的分析:
对于一篇文章来说,分页运算的逻辑在下面文件的 treesaver.ui.Article.prototype.paginateAsync 函数中。
https://github.com/Treesaver/treesaver/blob/master/src/ui/article.js
treesaver.ui.Article.prototype.paginateAsync 函数延迟2秒后使用调度程序对文章解析分页。
在TreeSaver中,Grid的定义就是模板的定义。(其他部分每个分页,每篇文章都是一样的。)
在TreeSaver的资源定义中,我们可以看到有很多个Grid定义,那个Grid适合我们的模板,是根据下面逻辑进行判断的。
https://github.com/Treesaver/treesaver/blob/master/src/layout/grid.js
这里的区域不是浏览器的内容区域,而是资源定义中viewer的区域,viewer区域显示的内容会同一篇文章每个页面都不一样。
这部分的代码如下:
/**
* Stretch the grids into appropriate heights, and filter out any grids* which do not fit. Return the stretched subset of grids in an array* @param {{ w: number, h: number }} size* @return {Array.<treesaver.layout.Grid>}*/treesaver.ui.Article.prototype.stretchGrids = function(size) {this.eligible_grids = this.grids.filter(function(grid) {return grid.capabilityFilter() && grid.sizeFilter(size);
}).map(function(grid) {
// Now stretch to the space
return grid.stretch(size.h);
});// Are there any grids?
if (!this.eligible_grids.length) {treesaver.debug.error('No eligible grids at ' + size.w + 'x' + size.h);}// Sort by highest text height (helps with shortcutting in scoring)
this.eligible_grids.sort(treesaver.layout.Grid.sort);
};
过滤策略:
遍历逻辑的核心代码如下,即依次建立每一个Page对象。
/**
* Paginate the article asynchronously* @param {boolean} bg Paginate remainder of article in background.* @param {number} index Paginate synchronously until this index.* @param {?treesaver.layout.ContentPosition|number} pos Paginate synchronously until this position.* @private*/treesaver.ui.Article.prototype.paginate = function(bg, index, pos) {//.......
var page;
index = index || 0;while (!this.br.finished) {page = new treesaver.layout.Page(
/** @type {!treesaver.layout.Content } */ (this.content),this.eligible_grids,
/** @type {!treesaver.layout.BreakRecord} */ (this.br));//.......
}//.......
}
Page对象的构造函数中,第一句就是挑选合适的模板Grid,然后根据挑选的模板组织页面,代码如下:
https://github.com/Treesaver/treesaver/blob/master/src/layout/page.js
/**
* Page class* @constructor* @param {!treesaver.layout.Content} content* @param {!Array.<treesaver.layout.Grid>} grids* @param {!treesaver.layout.BreakRecord} br The current breakRecord.*/treesaver.layout.Page = function(content, grids, br) {
var best = treesaver.layout.Grid.best(content, grids, br),
host = document.createElement('div'),
originalBr = br.clone(),containerFilled = false;
// ........
}
计算最佳模板,就涉及到了模板权重评分计算。
对于一个模板,它的权重计算逻辑如下:
以上模板权重评分分数计算在 treesaver.layout.Grid.prototype.score = function(content, breakRecord) { 函数中实现。注意以上只算了 模板的 Column 信息,没有计算模板的 Container 信息。
下一步我们遍历模板中每一个container,看内容中定义的的figure是否适合它。
这个算法在下面几个函数中实现:
treesaver.layout.Grid.prototype.mapContainers = function(content, br) {
Grid模板描述语言中的子元素:
内容集合
https://github.com/Treesaver/treesaver/blob/master/src/layout/content.js