Skip to content

Commit 6ec5d55

Browse files
committed
Fix #80 and also add associated unit tests for limiter.
Update some package versions etc.
1 parent 2ad2a93 commit 6ec5d55

11 files changed

Lines changed: 105 additions & 51 deletions

.npmrc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
package-lock = false

dist/CommentCoreLibrary.js

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -990,12 +990,12 @@ var CommentManager = (function() {
990990
opacity:1,
991991
scale:1
992992
},
993-
limit: 0
993+
limit: 0,
994+
seekTrigger: 2000
994995
};
995996
this.timeline = [];
996997
this.runline = [];
997998
this.position = 0;
998-
this.limiter = 0;
999999

10001000
this.factory = null;
10011001
this.filter = null;
@@ -1111,7 +1111,9 @@ var CommentManager = (function() {
11111111

11121112
CommentManager.prototype.time = function (time) {
11131113
time = time - 1;
1114-
if (this.position >= this.timeline.length || Math.abs(this._lastPosition - time) >= 2000) {
1114+
if (this.position >= this.timeline.length ||
1115+
Math.abs(this._lastPosition - time) >= this.options.seekTrigger) {
1116+
11151117
this.seek(time);
11161118
this._lastPosition = time;
11171119
if (this.timeline.length <= this.position) {
@@ -1122,7 +1124,7 @@ var CommentManager = (function() {
11221124
}
11231125
for (;this.position < this.timeline.length;this.position++) {
11241126
if (this.timeline[this.position]['stime']<=time) {
1125-
if (this.options.limit > 0 && this.runline.length > this.limiter) {
1127+
if (this.options.limit > 0 && this.runline.length >= this.options.limit) {
11261128
continue; // Skip comments but still move the position pointer
11271129
} else if (this.validate(this.timeline[this.position])) {
11281130
this.send(this.timeline[this.position]);
@@ -1229,15 +1231,15 @@ var CommentManager = (function() {
12291231

12301232
})();
12311233

1232-
/**
1234+
/**
12331235
* Comment Filters Module Simplified
12341236
* @license MIT
12351237
* @author Jim Chen
12361238
*/
12371239
var CommentFilter = (function () {
12381240

12391241
/**
1240-
* Matches a rule against an input that could be the full or a subset of
1242+
* Matches a rule against an input that could be the full or a subset of
12411243
* the comment data.
12421244
*
12431245
* @param rule - rule object to match
@@ -1275,19 +1277,22 @@ var CommentFilter = (function () {
12751277
case '=':
12761278
case 'eq':
12771279
return rule.value ===
1278-
((typeof extracted === 'number') ?
1280+
((typeof extracted === 'number') ?
12791281
extracted : extracted.toString());
1280-
case 'NOT':
1282+
case '!':
1283+
case 'not':
12811284
return !_match(rule.value, extracted);
1282-
case 'AND':
1285+
case '&&':
1286+
case 'and':
12831287
if (Array.isArray(rule.value)) {
12841288
return rule.value.every(function (r) {
12851289
return _match(r, extracted);
12861290
});
12871291
} else {
12881292
return false;
12891293
}
1290-
case 'OR':
1294+
case '||':
1295+
case 'or':
12911296
if (Array.isArray(rule.value)) {
12921297
return rule.value.some(function (r) {
12931298
return _match(r, extracted);
@@ -1352,7 +1357,10 @@ var CommentFilter = (function () {
13521357
* @return boolean indicator of whether this commentData should be shown
13531358
*/
13541359
CommentFilter.prototype.doValidate = function (cmtData) {
1355-
if ((!this.allowUnknownTypes ||
1360+
if (!cmtData.hasOwnProperty('mode')) {
1361+
return false;
1362+
}
1363+
if ((!this.allowUnknownTypes ||
13561364
cmtData.mode.toString() in this.allowTypes) &&
13571365
!this.allowTypes[cmtData.mode.toString()]) {
13581366
return false;

dist/CommentCoreLibrary.min.js

Lines changed: 2 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/CommentFilter.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,15 +26,15 @@
2626

2727
- Subject: (Subject) 规则绑定的对象
2828
比如 `subject=""` 时,则匹配整个 ICommentData 对象而 `subject="text"` 则匹配
29-
弹幕文字。可以通过 `.` 来进入子属性,比如 `subject="text.length"` 则会匹配
29+
弹幕文字。可以通过 `.` 来进入子属性,比如 `subject="text.length"` 则会匹配
3030
`cmtData.text.length` (`cmtData` 为 ICommentData对象)。
3131
- Op: (Operator) 规则使用的匹配方式
3232
- `<`/`>`: 数字匹配 (value为number)
3333
- `~``regexp`: 正则匹配 (value为正则表达式对象)
3434
- `=``eq`: 全等匹配 (value为任何对象)
35-
- `NOT`: 取反反规则,以前判定true则会返回false (value为 `rule`)
36-
- `AND`: 合并规则,只有列表中所有规则都匹配才匹配 (value为 `rule[]`)
37-
- `OR`: 或合并规则,只要列表中有一个匹配则匹配 (value为 `rule[]`)
35+
- `!``not`: 取反反规则,以前判定true则会返回false (value为 `rule`)
36+
- `&&``and`: 合并规则,只有列表中所有规则都匹配才匹配 (value为 `rule[]`)
37+
- `||``or`: 或合并规则,只要列表中有一个匹配则匹配 (value为 `rule[]`)
3838
- Value: (Target value) 规则目标参考值
3939
根据 OP 的取值,可能代表不同含义
4040
- Mode: (Rule mode) 规则类型

docs/CommentManager.md

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@
1313
* `scroll`
1414
* `opacity` 透明度
1515
* `scale` 生命时间加成(TTL Scale)
16-
* `limit` 最大显示弹幕数量,0或以下表示不限制同屏弹幕数量
16+
* `limit` 最大显示弹幕数量,`0` 或以下表示不限制同屏弹幕数量,默认 `0`
17+
* `seekTrigger``time()` 调用时间数值跳跃大于这个数值(ms)时,并不输出从上一个时间到这个时间的弹幕,而是直接更新上次弹幕时间。这个数值用于避免在手动移动时间轴时导致弹幕一起输出。数值设置太大可能导致搓时间轴时大量弹幕输出,设置太小则可能导致敏感度不足而不输出弹幕。默认 `2000`
1718

1819
### isRunning &lt;Bool&gt;
1920
管理器的弹幕是否在运行。`false`表示没有在运行,`true`表示在运行。可以通过 start/stop 控制。这
@@ -36,11 +37,11 @@
3637
rendererType 决定了渲染引擎类型,默认为CSS3渲染:
3738
- `css`: CSS3 transition
3839
- `svg`: SVG Animation
39-
- `canvas`: Canvas
40-
- `legacy`: DOM + Timer
40+
- `canvas`: Canvas
41+
- `legacy`: DOM + Timer
4142

4243
### start()
43-
启动弹幕老化进程。调用后 `send()` 发送到运行列表(runline)的弹幕会开始移动。用于在刚刚
44+
启动弹幕老化进程。调用后 `send()` 发送到运行列表(runline)的弹幕会开始移动。用于在刚刚
4445
`init()` 之后进入播放状态,或者在暂停弹幕后重新开始移动弹幕。播放时调用无作用。
4546

4647
注意:在播放状态未非播放时,调用 `send()`发送的弹幕会加入 runline,在start之后一并开始移动。
@@ -77,12 +78,12 @@ runline(运行列表)里,至于这些弹幕是否在移动,则要根据
7778
删除只会从时间轴中删除,如果被删除的弹幕正再播放,不会导致正在播放的弹幕消失。
7879

7980
### remove(filterFunction:Function)
80-
从弹幕列表中删除弹幕。filterFunction会在每个弹幕对象上被调用。当filterFunction返回 true
81+
从弹幕列表中删除弹幕。filterFunction会在每个弹幕对象上被调用。当filterFunction返回 true
8182
时(严格),删除相应弹幕。
8283

8384
### send(data:ICommentData)
8485
把一个抽象弹幕数据对象变成一个 IComment 并放入运行列表中。当 data 对象不符合 filter 规则或者
85-
时发送不会实现。代码弹幕也要通过send发送,只不过它们会进一步被派发到代码弹幕引擎。同一个
86+
时发送不会实现。代码弹幕也要通过send发送,只不过它们会进一步被派发到代码弹幕引擎。同一个
8687
ICommentData 实例如果多次用于调用这个方法会产生多个不同的弹幕实例 IComment。
8788

8889
注意:send可以发送不在时间轴里的弹幕。这个功能尤其利于实时弹幕的实现,因为对于直播实时弹幕,基本不

package.json

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
"url": "https://github.com/jabbany/CommentCoreLibrary.git"
1212
},
1313
"author": "Jim Chen <knh.jabbany@gmail.com>",
14-
"license":"MIT",
14+
"license": "MIT",
1515
"keywords": [
1616
"danmaku",
1717
"video",
@@ -30,18 +30,18 @@
3030
"grunt-contrib-coffee": "^1.0.0",
3131
"grunt-contrib-concat": "^1.0.1",
3232
"grunt-contrib-copy": "^1.0.0",
33-
"grunt-contrib-cssmin": "^2.0.0",
33+
"grunt-contrib-cssmin": "^2.2.1",
3434
"grunt-contrib-jasmine": "^1.0.3",
3535
"grunt-contrib-jshint": "^1.0.0",
3636
"grunt-contrib-uglify": "^2.3.0",
3737
"grunt-contrib-watch": "^1.0.0",
3838
"grunt-template-jasmine-istanbul": "^0.5.0",
3939
"grunt-ts": "^5.5.1",
40-
"jquery": "^3.1.1",
4140
"jasmine-jquery": "^2.0.0",
42-
"sinon": "^2.1.0",
4341
"jasmine-sinon": "^0.4.0",
42+
"jquery": "^3.1.1",
43+
"load-grunt-tasks": "^3.5.2",
4444
"promise-polyfill": "^6.0.2",
45-
"load-grunt-tasks": "^3.5.2"
45+
"sinon": "^2.4.1"
4646
}
4747
}

spec/CommentCoreLibrary_spec.coffee

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,26 @@ describe 'CommentManager', ->
55

66
describe 'instance API', ->
77
beforeEach ->
8-
c1 = stime: 1
9-
c2 = stime: 2, date: '2014-07-12T04:35:55.624Z'
8+
c1 =
9+
stime: 1
10+
mode: 1
11+
c2 =
12+
stime: 2
13+
mode: 1
14+
date: '2014-07-12T04:35:55.624Z'
1015
c3 =
1116
stime: 2
17+
mode: 1
1218
date: '2014-07-12T04:35:55.626Z'
1319
dbid: '53c0bb2b6465625061b40698'
1420
c4 =
1521
stime: 2
22+
mode: 1
1623
date: '2014-07-12T04:35:55.626Z'
1724
dbid: '53c0bb2b6465625061b40700'
1825
c5 =
1926
stime: 2
27+
mode: 1
2028
date: '2014-07-12T04:35:55.626Z'
2129
dbid: '53c0bb2b6465625061b40700'
2230
cmt =
@@ -66,6 +74,27 @@ describe 'CommentManager', ->
6674
manager.send cmt
6775
expect(manager.runline.length).toBe 1
6876

77+
describe '.time', ->
78+
it 'allocates comments to the runline', ->
79+
spy = sinon.spy manager, 'send'
80+
manager.load [ c3, c4, c5 ]
81+
manager.time 3
82+
expect(spy).toHaveBeenCalledThrice()
83+
84+
it 'limits based on limiter', ->
85+
spy = sinon.spy manager, 'send'
86+
manager.load [ c3, c4, c5 ]
87+
manager.options.limit = 2
88+
manager.time 3
89+
expect(spy).toHaveBeenCalledTwice()
90+
91+
it 'seeks if seek threshold is passed', ->
92+
manager.load [ c1 ]
93+
manager.options.seekTrigger = 100
94+
manager.time 0
95+
manager.time 200
96+
expect(manager.runline.length).toBe 0
97+
6998
describe '.start', ->
7099
it 'starts the timer', ->
71100
spy = sinon.spy window, 'setInterval'
@@ -93,7 +122,7 @@ describe 'CommentManager', ->
93122
expect(manager.timeline).toEqual [c3, c4 , c5]
94123

95124
describe '.setBounds', ->
96-
beforeEach ->
125+
beforeEach ->
97126
manager.stage.style.width = '640px'
98127
manager.stage.style.width = '480px'
99128

spec/filter/CommentFilter_spec.coffee

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,12 @@ describe 'CommentFilter', ->
1515
'date': 2000
1616
'size': 50
1717
'color': 0xff0000
18+
commentNoMode =
19+
'stime': 1
20+
'text': 'This comment has no mode'
1821

1922
ruleAccept =
20-
'mode': 'accept'
23+
'mode': 'accept'
2124
'subject': 'size'
2225
'op': '<'
2326
'value': 50
@@ -29,15 +32,15 @@ describe 'CommentFilter', ->
2932
ruleNot =
3033
'mode': 'accept'
3134
'subject': ''
32-
'op': 'NOT'
35+
'op': 'not'
3336
'value':
3437
'subject': 'text.length'
3538
'op': '<'
3639
'value': 15
3740
ruleOr =
3841
'mode': 'accept'
3942
'subject': ''
40-
'op': 'OR'
43+
'op': 'or'
4144
'value': [
4245
{
4346
'subject': 'date'
@@ -55,7 +58,7 @@ describe 'CommentFilter', ->
5558
beforeEach ->
5659
filter = new CommentFilter()
5760

58-
'doModify beforeSend doValidate addRule
61+
'doModify beforeSend doValidate addRule
5962
addModifier'.split(/\s/).forEach (method)->
6063

6164
it "has method: '#{method}'", ->
@@ -102,9 +105,12 @@ describe 'CommentFilter', ->
102105
filter.allowTypes['1'] = false
103106
expect(filter.doValidate comment).toBe false
104107

108+
it 'fails validation on no-mode comments', ->
109+
expect(filter.doValidate commentNoMode).toBe false
110+
105111
it 'passes validation unknown mode', ->
106112
expect(filter.doValidate alienModeComment).toBe true
107-
113+
108114
it 'fails validation if allowUnknownTypes false', ->
109115
filter.allowUnknownTypes = false
110116
expect(filter.doValidate alienModeComment).toBe false
@@ -113,7 +119,7 @@ describe 'CommentFilter', ->
113119
filter.addRule ruleAccept
114120
expect(filter.doValidate comment).toBe true
115121
expect(filter.doValidate commentAlt).toBe false
116-
122+
117123
it 'executes reject rules', ->
118124
filter.addRule ruleReject
119125
expect(filter.rules.length).toBe 1
@@ -149,9 +155,9 @@ describe 'CommentFilter', ->
149155
expect(filter.rules[0]).toBe rule
150156

151157
it 'rejects adding invalid rule', ->
152-
expect( =>
158+
expect( =>
153159
filter.addRule
154-
'mode': '???').toThrow()
160+
'mode': '???').toThrow()
155161

156162
describe '.addModifier', ->
157163
modifier = (cmt) ->
@@ -165,4 +171,3 @@ describe 'CommentFilter', ->
165171

166172
it 'rejects invalid modifier', ->
167173
expect( => filter.addModifier 'Boo').toThrow()
168-

src/CommentManager.js

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,12 +46,12 @@ var CommentManager = (function() {
4646
opacity:1,
4747
scale:1
4848
},
49-
limit: 0
49+
limit: 0,
50+
seekTrigger: 2000
5051
};
5152
this.timeline = [];
5253
this.runline = [];
5354
this.position = 0;
54-
this.limiter = 0;
5555

5656
this.factory = null;
5757
this.filter = null;
@@ -167,7 +167,9 @@ var CommentManager = (function() {
167167

168168
CommentManager.prototype.time = function (time) {
169169
time = time - 1;
170-
if (this.position >= this.timeline.length || Math.abs(this._lastPosition - time) >= 2000) {
170+
if (this.position >= this.timeline.length ||
171+
Math.abs(this._lastPosition - time) >= this.options.seekTrigger) {
172+
171173
this.seek(time);
172174
this._lastPosition = time;
173175
if (this.timeline.length <= this.position) {
@@ -178,7 +180,7 @@ var CommentManager = (function() {
178180
}
179181
for (;this.position < this.timeline.length;this.position++) {
180182
if (this.timeline[this.position]['stime']<=time) {
181-
if (this.options.limit > 0 && this.runline.length > this.limiter) {
183+
if (this.options.limit > 0 && this.runline.length >= this.options.limit) {
182184
continue; // Skip comments but still move the position pointer
183185
} else if (this.validate(this.timeline[this.position])) {
184186
this.send(this.timeline[this.position]);

0 commit comments

Comments
 (0)