New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

yog-bigpipe

Package Overview
Dependencies
Maintainers
2
Versions
19
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

yog-bigpipe - npm Package Compare versions

Comparing version 0.0.7 to 0.0.8

lib/util.js

100

lib/bigpipe.js
var Pagelet = require('./pagelet.js');
var status = Pagelet.status;
var mode = Pagelet.mode;
var mixin = require('./util.js').mixin;
var Readable = require('stream').Readable;
var util = require('util');
function mixin(a, b) {
if (a && b) {
for (var key in b) {
a[key] = b[key];
}
}
return a;
}
var BigPipe = module.exports = function BigPipe(options) {
this.options = mixin({}, BigPipe.options, options);
this.quicklings = [];
this.options = mixin(mixin({}, BigPipe.options), options);
this.pagelets = [];

@@ -22,5 +15,8 @@ this.pipelines = [];

this.state = status.pending;
this.isquicking = false;
this.quicklings = [];
Readable.call(this, null);
};
// default options
BigPipe.options = {

@@ -35,2 +31,11 @@

util.inherits(BigPipe, Readable);
// don't call this directly.
BigPipe.prototype._read = function(n) {
if (this.state === status.pending) {
this.render();
}
};
// bind pagelet data source.

@@ -43,2 +48,4 @@ // accept fucntion and model name.

// 当为 quickling 模式的时候调用。
// 设置后,只有在此列表中的 pagelet 才会渲染。
BigPipe.prototype.addQuicklingPagelets = function(pagelets) {

@@ -49,2 +56,3 @@ var arr = this.quicklings;

// 判断是否是 quickling 模式。
BigPipe.prototype.isQuickingMode = function() {

@@ -54,4 +62,6 @@ return !!(this.quicklings && this.quicklings.length);

// 添加 pagelet.
BigPipe.prototype.addPagelet = function(obj) {
// 已经晚了了,不处理。
if (this.state === status.fulfilled) {

@@ -61,3 +71,3 @@ return false;

// todo 如果 quickling 的 widget 藏在某些异步 widget 里面,岂不是找不到?
// 注意: 如果 quickling 的 widget 藏在某些异步 widget 里面,岂不是找不到?
if (!this.isQuickingMode() && obj.mode !== mode.pipeline && obj.mode !== mode.async) {

@@ -75,41 +85,54 @@

var pagelet = new Pagelet(obj);
var sources = this.sources;
var source = sources[pagelet.id];
if (!source && sources.all) {
source = sources.all.bind(null, pagelet.id);
}
source && pagelet.setSource(source);
var self = this;
this.pagelets.push(pagelet);
pagelet.mode === mode.pipeline && this.pipelines.push(pagelet);
pagelet.once('ready', this._onPageletReady.bind(this));
pagelet.once('done', this._onPageletDone.bind(this));
pagelet.on('before-render', function() {
var args = [].slice.call(arguments);
return self.emit.apply(self, ['before-pagelet-render'].concat(args));
});
pagelet.on('after-render', function() {
var args = [].slice.call(arguments);
return self.emit.apply(self, ['after-pagelet-render'].concat(args));
});
if (this.state === status.rendering) {
pagelet.render();
this.renderPagelet(pagelet);
}
};
BigPipe.prototype.render = function(stream, cb) {
BigPipe.prototype.render = function() {
var pagelets = this.pagelets.concat();
var sources = this.sources;
var self = this;
this.stream = stream;
this.cb = cb;
this.state = status.rendering;
if (!pagelets.length) {
process.nextTick(cb);
pagelets.forEach(this.renderPagelet.bind(this));
this._checkFinish();
};
BigPipe.prototype.renderPagelet = function(pagelet) {
var sources = this.sources;
var source = sources[pagelet.id];
if (!source && typeof sources.all === 'function') {
source = sources.all.bind(null, pagelet.id);
}
pagelets.forEach(function(pagelet) {
pagelet.render();
// hook
this.emit('prepare-pagelet-source', pagelet.id, function(_source) {
source = _source;
});
pagelet.start(source);
};
BigPipe.prototype.destroy = function() {
this.stream = this.cb = this.sources = null;
this.sources = null;
this.removeAllListeners();
this.rendered.concat(this.pagelets).forEach(function(pagelet) {

@@ -122,6 +145,6 @@ pagelet.destroy();

BigPipe.prototype._onPageletReady = function(pagelet) {
BigPipe.prototype._onPageletDone = function(pagelet) {
var cb, idx, item;
if (pagelet.mode ===mode.pipeline) {
if (pagelet.mode === mode.pipeline) {
// 必须按顺序

@@ -150,8 +173,5 @@ // idx = this.pipelines.indexOf(pagelet);

if (!this.pagelets.length && this.state === status.rendering) {
cb = this.cb;
// 标记已经完成。
this.state = status.fulfilled;
cb(null, '');
cb = this.cb = null;
this.push(null);
}

@@ -162,3 +182,3 @@ };

var content = this.format(pagelet);
content && this.stream.write(content);
content && this.push(content);
this._markPageletRendered(pagelet);

@@ -165,0 +185,0 @@ };

234

lib/pagelet.js
var util = require("util");
var EventEmitter = require("events").EventEmitter;
var _ = require('./util.js');
function mixin(a, b) {
if (a && b) {
for (var key in b) {
a[key] = b[key];
}
}
return a;
}
function ucfirst(str) {
return str.substring(0, 1).toUpperCase() + str.substring(1);
}
var Pagelet = module.exports = function Pagelet(obj) {
this.model = obj.model;
this.container = obj['for'];
this.container = obj['container'] || obj['for'];
this.mode = obj.mode;

@@ -24,9 +12,9 @@ this.id = obj.id;

this.compiled = obj.compiled;
this.state = status.pending;
this.scripts = [];
this.styles = [];
this.js = [];
this.css = [];
this.styles = [];
this.html = '';
// this.errorMsg = '';
};

@@ -36,2 +24,8 @@

// Status Spec.
//
// - `pending` just initialized.
// - `rendering` start rendered but not yet finished.
// - `fulfilled` render finish.
// - `failed` render failed.
var status = Pagelet.status = {

@@ -44,36 +38,58 @@ pending: 'pending',

// Mode Spec
//
// - `async` 忽略顺序,谁先准备好,谁先输出
// - `pipeline` 按顺序输出,以入库的顺序为准。
// - `quickling` 此类 pagelet 并不是 chunk 输出,而是第二次请求的时候输出。
Pagelet.mode = {
async: 'async',
pipeline: 'pipeline',
async: 'async',
quickling: 'quickling'
};
Pagelet.prototype.setSource = function(source) {
this.source = source;
};
Pagelet.prototype.render = function() {
var fn = this.source;
/**
* 开始渲染 pagelet, 可以指定一个 provider 即数据准备回调。
*
* 回调中,第一个参数为状态 error,第二个参数才为数据 data。
* @example
*
* ```javascript
* pagelet.start(function(done) {
* var model = new RemoteModel();
*
* model.fetch(function(err, val) {
* done(err, val);
* });
* });
* ```
*
* @method start
* @param {Function} provider 数据提供者
* @return {Undefined}
*/
Pagelet.prototype.start = function(provider) {
var self = this;
var eventname;
var self = this;
if (!fn && (eventname = 'onPagelet' + ucfirst(this.id)) &&
typeof this.locals[eventname] === 'function' ) {
if (this.state !== status.pending) {
return this.emit('error', new Error('Alreay rendered.'));
}
fn = this.locals[eventname];
// mark the state.
this.state = status.rendering;
if (!provider && (eventname = 'onPagelet' + _.ucfirst(this.id)) &&
typeof this.locals[eventname] === 'function') {
provider = this.locals[eventname];
}
if (!fn && typeof this.locals['onPagelet'] === 'function') {
fn = this.locals['onPagelet'].bind(null, this.id);
if (!provider && typeof this.locals['onPagelet'] === 'function') {
provider = this.locals['onPagelet'].bind(null, this.id);
}
this.state = status.rendering;
// todo 支持 pagelet.model 自动关联。
if (fn) {
fn(function(err, val) {
if (provider) {
provider(function(err, val) {
if (err) {
// todo
// self.state = status.failed;
// self.errorMsg = err;
self.emit('error', err);
return;

@@ -89,4 +105,5 @@ }

// don't call this directly.
Pagelet.prototype._render = function(model) {
var locals = this.locals;
var locals = this.locals || {};
var fn = this.compiled;

@@ -96,62 +113,100 @@ var self = this;

model && (mixin(locals, model), locals.model = model);
model && (_.mixin(locals, model), locals.model = model);
this._yog = locals._yog = locals._yog.fork();
// hook sub pagelet render.
// make that render after this pagelet render.
var origin = locals._yog.addPagelet;
var subpagelets = [];
self.onReady = function() {
subpagelets.forEach(function(args) {
origin.apply(locals._yog, args);
});
locals._yog.addPagelet = origin;
locals = self = origin = null;
};
locals._yog.addPagelet = function() {
subpagelets.push(arguments);
};
self.emit('before-render', self, locals, fn);
output = fn(locals);
this.analyse(output);
self.emit('after-render', self, locals, fn);
this._analyse(output);
this.state = status.fulfilled;
this.emit('done', this);
};
Pagelet.prototype.analyse = function(output) {
var yog = this._yog;
Pagelet.prototype._analyse = function(output) {
var scripts = this.scripts;
var styles = this.styles;
var js = this.js;
var css = this.css;
var styles = this.styles;
var yogScripts = yog.getScripts();
var yogStyles = yog.getStyles();
var p;
// 收集js, css, html
if(yog.getResourceMap()) {
scripts.push('require.resourceMap(' + JSON.stringify(this.getResourceMap()) + ');');
}
this.html = output
// 收集内联或者外链 js
.replace(/<script([^>]*?)>([\s\S]+?)<\/script>/ig, function(_, attr, content) {
var m = /src=('|")(.*?)\1/i.exec(attr);
styles.push.apply(styles, yogStyles.embed);
if (m) {
js.push(m[2]);
} else {
scripts.push(content);
}
output = output.replace(/<script[^>]*?>([\s\S]+?)<\/script>/ig, function(_, content) {
scripts.push(content);
return '';
}).replace(/<style[^>]*?>([\s\S]+?)<\/style>/ig, function(_, content) {
styles.push(content);
return '';
});
scripts.push.apply(scripts, yogScripts.embed);
yogScripts.urls && (js = this.js = yogScripts.urls.concat());
yogStyles.urls && (css = this.css = yogStyles.urls.concat());
return '';
})
this.html = output;
this.state = status.fulfilled;
this.emit('ready', this);
this.onReady && this.onReady();
// 收集内联样式
.replace(/<style[^>]*?>([\s\S]+?)<\/style>/ig, function(_, content) {
styles.push(content);
return '';
})
// 收集外链样式。
.replace(/<link(.*?)\/>/ig, function(_, attr) {
var m = /href=('|")(.*?)\1/i.exec(attr);
if (m) {
css.push(m[2]);
}
return _;
});
};
/**
* 添加内联样式。
* @method addStyle
* @param {String | Array of String} style 样式内容
*/
Pagelet.prototype.addStyle = Pagelet.prototype.addStyles = function(style) {
style = Array.isArray(style) ? style : [style];
this.styles.push.apply(this.styles, style);
};
/**
* 添加内联脚本。
* @method addScript
* @param {String | Array of String} script 脚本内容。
*/
Pagelet.prototype.addScript = Pagelet.prototype.addScripts = function(script) {
script = Array.isArray(script) ? script : [script];
this.scripts.push.apply(this.scripts, script);
};
/**
* 添加脚本。
* @method addJs
* @param {String | Array of String} js 脚本地址。
*/
Pagelet.prototype.addJs = Pagelet.prototype.addJses = function(js) {
js = Array.isArray(js) ? js : [js];
this.js.push.apply(this.js, js);
};
/**
* 添加样式。
* @method addCss
* @param {String | Array of String} js 样式地址。
*/
Pagelet.prototype.addCss = Pagelet.prototype.addCsses = function(css) {
css = Array.isArray(css) ? css : [css];
this.css.push.apply(this.css, css);
};
/**
* 获取 pagelet 渲染后的信息。
* @method toJson
* @return {Object}
*/
Pagelet.prototype.toJson = function() {

@@ -167,4 +222,9 @@ return {

};
}
};
/**
* 销毁。
* @destroy
*/
Pagelet.prototype.destroy = function() {

@@ -175,2 +235,2 @@ this.destroyed = true;

this.scripts = this.js = this.css = this.styles = null;
}
};
{
"name": "yog-bigpipe",
"version": "0.0.7",
"version": "0.0.8",
"description": "An express.js middleware for fis widget pipline output.",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
"test": "mocha --reporter dot --check-leaks test/",
"test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter dot --check-leaks test/",
"test-travis": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --reporter spec --check-leaks test/"
},

@@ -23,3 +25,10 @@ "repository": {

},
"homepage": "https://github.com/fex-team/yog-bigpipe"
"homepage": "https://github.com/fex-team/yog-bigpipe",
"devDependencies": {
"mocha": "~1.20.1",
"istanbul": "~0.2.14",
"express": "~4.4.5",
"supertest": "~0.13.0",
"should": "~4.0.4"
}
}

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc