/
util_parallel.js
166 lines (159 loc) · 6.07 KB
/
util_parallel.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
/*global CSL: true */
/**
* Initializes the parallel cite tracking arrays
*/
CSL.Parallel = function (state) {
this.state = state;
this.info = {};
};
CSL.Parallel.prototype.setSeriesRels = function(prevID, currID, seriesRels) {
if (this.info[prevID][currID]) {
if (!seriesRels) {
seriesRels = JSON.parse(JSON.stringify(this.info[prevID]));
}
} else {
seriesRels = false;
}
return seriesRels;
}
CSL.Parallel.prototype.getRepeats = function(prev, curr) {
var rex = /(?:type|id|seeAlso|.*-sub|.*-subjoin|.*-main)/;
var ret = {};
for (var key in prev) {
if (key.match(rex)) {
continue;
}
if (typeof prev[key] === "string" || !prev[key]) {
if (prev[key] && prev[key] === curr[key]) {
ret[key] = true;
}
} else if (typeof prev[key] === "object") {
// Could do better than this.
if (JSON.stringify(prev[key]) === JSON.stringify(curr[key])) {
ret[key] = true;
}
}
}
return ret;
}
CSL.Parallel.prototype.StartCitation = function (sortedItems, out) {
this.parallel_conditional_blobs_list = [];
this.info = {};
if (sortedItems.length > 1) {
// Harder than it looks.
// On a first pass, get the seeAlso of each item.
for (var i=0,ilen=sortedItems.length; i<ilen; i++) {
var curr = sortedItems[i][0];
this.info[curr.id] = {};
if (curr.seeAlso) {
for (var j=0,jlen=curr.seeAlso.length; j<jlen; j++) {
if (curr.id === curr.seeAlso[j]) {
continue;
}
this.info[curr.id][curr.seeAlso[j]] = true;
}
}
}
// On a second pass, set an item to FIRST if the current
// item is in its seeAlso. The seeAlso of the FIRST item control
// until (a) a non-member is encountered at CURRENT, or
// (b) the end of the array is reached.
// The seeAlso keys are deleted as each is seen.
// If neither (a) nor (b), set the current item to MID.
// If (a) and the previous item is FIRST, delete its
// parallel marker.
// If (b) and the current item is FIRST, delete its
// parallel marker.
// If (a) and the previous item is not FIRST, set it to
// LAST, and reset seeAlso from the current item.
// If (b) and the current item is not FIRST, set it to
// LAST.
var seriesRels = false;
var masterID = false;
for (var i=1,ilen=sortedItems.length; i<ilen; i++) {
var prev = sortedItems[i-1][0];
var curr = sortedItems[i][0];
var newSeriesRels = this.setSeriesRels(prev.id, curr.id, seriesRels);
if (!seriesRels) {
if (newSeriesRels) {
// first
seriesRels = newSeriesRels;
delete seriesRels[curr.id];
sortedItems[i-1][1].parallel = "first";
sortedItems[i][1].parallel = "mid";
sortedItems[i][1].repeats = this.getRepeats(prev, curr);
sortedItems[i-1][1].repeats = sortedItems[i][1].repeats;
if (!sortedItems[i][1].prefix) {
sortedItems[i][1].prefix = ", ";
}
masterID = prev.id;
this.state.registry.registry[masterID].master = true;
this.state.registry.registry[masterID].siblings = [curr.id];
}
} else {
if (seriesRels[curr.id]) {
sortedItems[i][1].parallel = "mid";
if (!sortedItems[i][1].prefix) {
sortedItems[i][1].prefix = ", ";
}
delete seriesRels[curr.id];
sortedItems[i][1].repeats = this.getRepeats(prev, curr);
//sortedItems[i-1][1].repeats = sortedItems[i][1].repeats;
this.state.registry.registry[masterID].siblings.push(curr.id);
} else {
sortedItems[i-1][1].parallel = "last";
sortedItems[i][1].repeats = this.getRepeats(prev, curr);
seriesRels = false;
}
}
if (i === (sortedItems.length-1)) {
if (sortedItems[i][1].parallel === "mid") {
sortedItems[i][1].parallel = "last";
sortedItems[i][1].repeats = this.getRepeats(prev, curr);
} else if (sortedItems[i][1].parallel !== "last") {
delete sortedItems[i][1].repeats;
}
}
}
}
};
CSL.Parallel.prototype.purgeGroupsIfParallel = function () {
for (var i = this.parallel_conditional_blobs_list.length - 1; i > -1; i += -1) {
var obj = this.parallel_conditional_blobs_list[i];
if (!obj.result && !obj.repeats) {
purgeme = false;
} else {
if (obj.condition) {
var purgeme = true;
if (obj.result === obj.condition) {
purgeme = false;
}
}
if (purgeme && obj.norepeat && obj.repeats) {
purgeme = false;
var matches = 0;
for (var j=0,jlen=obj.norepeat.length; j<jlen; j++) {
if (obj.repeats[obj.norepeat[j]]) {
matches += 1;
}
}
if (matches === obj.norepeat.length) {
purgeme = true;
}
}
}
if (purgeme) {
var buffer = [];
while (obj.blobs.length > obj.pos) {
buffer.push(obj.blobs.pop());
}
if (buffer.length) {
buffer.pop();
}
while (buffer.length) {
obj.blobs.push(buffer.pop());
}
}
this.parallel_conditional_blobs_list.pop();
}
};