Skip to content

Commit

Permalink
Support no-repeat attribute on cs:group
Browse files Browse the repository at this point in the history
  • Loading branch information
fbennett committed Sep 1, 2019
1 parent a42cb6c commit 5809c19
Show file tree
Hide file tree
Showing 9 changed files with 135 additions and 51 deletions.
20 changes: 16 additions & 4 deletions src/api_cite.js
Expand Up @@ -343,7 +343,10 @@ CSL.Engine.prototype.processCitationCluster = function (citation, citationsPre,
}

// evaluate parallels
this.parallel.StartCitation(citation.sortedItems);

if (this.opt.parallel.enable) {
this.parallel.StartCitation(citation.sortedItems);
}

var citations;
if (this.opt.update_mode === CSL.POSITION) {
Expand Down Expand Up @@ -873,7 +876,9 @@ CSL.Engine.prototype.makeCitationCluster = function (rawList) {
inputList.sort(this.citation.srt.compareCompositeKeys);
}
this.tmp.citation_errors = [];
this.parallel.StartCitation(inputList);
if (this.opt.parallel.enable) {
this.parallel.StartCitation(inputList);
}
var str = CSL.getCitationCluster.call(this, inputList);
return str;
};
Expand All @@ -899,7 +904,10 @@ CSL.getAmbiguousCite = function (Item, disambig, visualForm, item) {
parallel_condition: flags.parallel_condition,
parallel_result: flags.parallel_result,
changes_in_condition: flags.changes_in_condition,
parallel_repeats: flags.parallel_result,
no_repeat_condition: flags.no_repeat_condition,
layout_delimiter_override: flags.layout_delimiter_override,
parallel_repeats: flags.parallel_repeats,
no_repeat_repeats: flags.no_repeat_repeats,
condition: flags.condition,
force_suppress: flags.force_suppress,
done_vars: flags.done_vars.slice()
Expand Down Expand Up @@ -1159,6 +1167,8 @@ CSL.getCitationCluster = function (inputList, citation) {

this.tmp.in_cite_predecessor = false;
// true is to block reset of shadow numbers


if (pos > 0) {
CSL.getCite.call(this, Item, item, "" + inputList[(pos - 1)][0].id, true);
} else {
Expand Down Expand Up @@ -1213,7 +1223,9 @@ CSL.getCitationCluster = function (inputList, citation) {
}
}

this.parallel.purgeGroupsIfParallel();
if (this.opt.parallel.enable) {
this.parallel.purgeGroupsIfParallel();
}
//
// output.queue is a simple array. do a slice
// of it to get each cite item, setting params from
Expand Down
22 changes: 18 additions & 4 deletions src/attributes.js
Expand Up @@ -113,7 +113,6 @@ CSL.Attributes["@position"] = function (state, arg) {
this.tests ? {} : this.tests = [];
var tryposition;
state.opt.update_mode = CSL.POSITION;
state.parallel.use_parallels = null;
var trypositions = arg.split(/\s+/);
var testSubsequentNear = function (Item, item) {
if (item && item.position >= CSL.POSITION_SUBSEQUENT && item["near-note"]) {
Expand Down Expand Up @@ -810,15 +809,30 @@ CSL.Attributes["@locale-internal"] = function (state, arg) {
// These are not evaluated as conditions immediately: they only
// set parameters that are picked up during processing.
CSL.Attributes["@is-parallel"] = function (state, arg) {
state.opt.parallel.enable = true;
this.strings.set_parallel_condition = arg;
};
CSL.Attributes["@changes-in"] = function (state, arg) {
this.strings.set_changes_in_condition = arg.split(/\s+/);
var lst = arg.split(/\s+/);
for (var i=0,ilen=lst.length;i<ilen;i++) {
state.opt.parallel.changes_in[lst[i]] = true;
}
this.strings.set_changes_in_condition = lst;
};
CSL.Attributes["@no-repeat"] = function (state, arg) {
this.strings.set_no_repeat_condition = arg.split(/\s+/);
if (!state.opt.parallel.no_repeat) {
state.opt.parallel.no_repeat = {};
}
var lst = arg.split(/\s+/);
state.opt.parallel.enable = true;
for (var i=0,ilen=lst.length;i<ilen;i++) {
state.opt.parallel.no_repeat[lst[i]] = true;
}
this.strings.set_no_repeat_condition = lst;
};
CSL.Attributes["@layout-delimiter-override"] = function (state, arg) {
this.strings.set_layout_delimiter_override = arg;
};



CSL.Attributes["@require"] = function (state, arg) {
Expand Down
6 changes: 4 additions & 2 deletions src/build.js
Expand Up @@ -53,8 +53,6 @@ CSL.Engine = function (sys, style, lang, forceLang) {
CSL.stringCompare = this.sys.stringCompare;
}
this.sys.AbbreviationSegments = CSL.AbbreviationSegments;
this.parallel = new CSL.Parallel(this);
//this.parallel.use_parallels = true;

this.transform = new CSL.Transform(this);
// true or false
Expand Down Expand Up @@ -221,6 +219,10 @@ CSL.Engine = function (sys, style, lang, forceLang) {
var area_nodes = this.cslXml.getNodesByName(this.cslXml.dataObj, this.build.area);
this.buildTokenLists(area_nodes, this[this.build.area].tokens);

if (this.opt.parallel.enable) {
this.parallel = new CSL.Parallel(this);
}

this.juris = {};

this.configureTokenLists();
Expand Down
23 changes: 20 additions & 3 deletions src/node_group.js
Expand Up @@ -84,6 +84,8 @@ CSL.Node.group = {
label_capitalize_if_first: label_capitalize_if_first,
parallel_condition: this.strings.set_parallel_condition,
changes_in_condition: this.strings.set_changes_in_condition,
no_repeat_condition: this.strings.set_no_repeat_condition,
layout_delimiter_override: this.strings.set_layout_delimiter_override,
parallel_result: undefined,
parallel_repeats: undefined,
condition: condition,
Expand Down Expand Up @@ -212,6 +214,11 @@ CSL.Node.group = {
//}
}
}
if (state.opt.parallel.enable) {
if (!state.parallel) {
state.parallel = new CSL.Parallel(this);
}
}
// Identify the best jurisdiction for the item and return true, otherwise return false
for (var i=0,ilen=jurisdictionList.length;i<ilen;i++) {
var jurisdiction = jurisdictionList[i];
Expand Down Expand Up @@ -268,7 +275,7 @@ CSL.Node.group = {
}

// quashnonfields
func = function (state, Item) {
func = function (state, Item, item) {
state.output.endTag();
if (this.realGroup) {
var flags = state.tmp.group_context.pop();
Expand Down Expand Up @@ -300,17 +307,27 @@ CSL.Node.group = {
}
var blobs = state.output.current.value().blobs;
var pos = state.output.current.value().blobs.length - 1;
if (!state.tmp.just_looking && (flags.parallel_condition || flags.changes_in_condition)) {
if (!state.tmp.just_looking && (flags.parallel_condition || flags.changes_in_condition || flags.no_repeat_condition)) {
var parallel_condition_object = {
blobs: blobs,
condition: flags.parallel_condition,
result: flags.parallel_result,
changes_in_condition: flags.changes_in_condition,
parallel_repeats: flags.parallel_repeats,
no_repeat_condition: flags.no_repeat_condition,
no_repeat_repeats: flags.no_repeat_repeats,
layout_delimiter_override: flags.layout_delimiter_override,
id: Item.id,
pos: pos
};
state.parallel.parallel_conditional_blobs_list.push(parallel_condition_object);
if (state.parallel.checkRepeats(parallel_condition_object)) {
while (blobs.length) {
blobs.pop();
}
state.output.queue.slice(-1)[0].parallel_delimiter = parallel_condition_object.layout_delimiter_override;
} else {
state.parallel.parallel_conditional_blobs_list.push(parallel_condition_object);
}
}
} else {
state.tmp.term_predecessor = flags.old_term_predecessor;
Expand Down
1 change: 0 additions & 1 deletion src/node_sort.js
Expand Up @@ -12,7 +12,6 @@ CSL.Node.sort = {
target = state[state.build.root + "_sort"].tokens;
if (this.tokentype === CSL.START) {
if (state.build.area === "citation") {
state.parallel.use_parallels = false;
state.opt.sort_citations = true;
}
state.build.area = state.build.root + "_sort";
Expand Down
2 changes: 0 additions & 2 deletions src/registry.js
Expand Up @@ -784,11 +784,9 @@ CSL.getSortKeys = function (Item, key_type) {
this.tmp.extension = "_sort";
this.tmp.disambig_override = true;
this.tmp.disambig_request = false;
this.parallel.use_parallels = (this.parallel.use_parallels === true || this.parallel.use_parallels === null) ? null : false;
this.tmp.suppress_decorations = true;
CSL.getCite.call(this, Item);
this.tmp.suppress_decorations = false;
this.parallel.use_parallels = this.parallel.use_parallels === null ? true : false;
this.tmp.disambig_override = false;
len = this[key_type].keys.length;
for (pos = 0; pos < len; pos += 1) {
Expand Down
8 changes: 7 additions & 1 deletion src/state.js
@@ -1,6 +1,11 @@
/*global CSL: true */

CSL.Engine.Opt = function () {
this.parallel = {
enable: false,
no_repeat: null,
changes_in: {}
},
this.has_disambiguate = false;
this.mode = "html";
this.dates = {};
Expand Down Expand Up @@ -236,8 +241,9 @@ CSL.Engine.Tmp = function () {
label_form: undefined,
parallel_condition: undefined,
parallel_result: undefined,
no_repeat_condition: undefined,
parallel_repeats: undefined,
no_repeat_condition: undefined,
no_repeat_repeats: undefined,
condition: false,
force_suppress: false,
done_vars: []
Expand Down
101 changes: 67 additions & 34 deletions src/util_parallel.js
Expand Up @@ -12,34 +12,45 @@ CSL.Parallel.Partnerships = function(state, items) {
this.state = state;
this.items = items.concat([[{},{}]]);
this.partnerMap = null;
this.partnerStatus = null;
this.repeatMap = null;
};

CSL.Parallel.Partnerships.prototype.update = function(i) {
var currItem = this.items[i][0];
var nextItem = this.items[i+1][0];
var partnerStatus = null;
this.partnerStatus = null;
if (this.partnerMap) {
if (this.partnerMap[nextItem.id]) {
partnerStatus = "mid";
this.partnerStatus = "mid";
} else {
this.partnerMap = null;
partnerStatus = "last";
this.partnerStatus = "last";
}
} else {
// set partnerMap for this and its partner if none present
if (this._setPartnerStatus(i)) {
partnerStatus = "first";
if (this._setPartnerMap(i)) {
this.partnerStatus = "first";
}
}
return partnerStatus;
// set repeatMap for this an its partner
// set repeatMap for this and its partner
// This really isn't the place for this stuff, if we can avoid it.
// We're tracking ALL VARIABLES, after which we'll filter out the
// ones we're interested in. Very wasteful. And that goes for
// the partnerMap code as well.
// At the very least, this should all be disabled if the style
// does not use one of is-parallel or no-repeat.
}

CSL.Parallel.Partnerships.prototype.getPartnerStatus = function(i) {
return this.partnerStatus;
}

CSL.Parallel.Partnerships.prototype.getID = function(i) {
return this.items[i][0].id;
}

CSL.Parallel.Partnerships.prototype._setPartnerStatus = function(i) {
CSL.Parallel.Partnerships.prototype._setPartnerMap = function(i) {
var currItem = this.items[i][0];
var nextItem = this.items[i+1][0]
var hasMap = false;
Expand All @@ -55,24 +66,26 @@ CSL.Parallel.Partnerships.prototype._setPartnerStatus = function(i) {
return hasMap;
}

CSL.Parallel.Partnerships.prototype._getPartnerRepeats = function(i) {
CSL.Parallel.Partnerships.prototype._getPartnerRepeats = function(i, mode) {
var currItem = this.items[i][0];
var nextItem = this.items[i+1][0];
var rex = /(?:type|id|seeAlso|.*-sub|.*-subjoin|.*-main)/;
var rex = /(?:type|multi|id|seeAlso|.*-sub|.*-subjoin|.*-main)/;
var ret = {};
for (var key in currItem) {
if (key.match(rex)) {
continue;
}
if (!currItem[key]) continue;
if (typeof currItem[key] === "string") {
if (currItem[key] === nextItem[key]) {
ret[key] = true;
for (var key in this.state.opt.parallel[mode]) {
if (currItem[key]) {
if (key.match(rex)) {
continue;
}
} else if (typeof currItem[key] === "object") {
// Could do better than this, should be proper deepEqual polyfill
if (JSON.stringify(currItem[key]) === JSON.stringify(nextItem[key])) {
ret[key] = true;
if (!currItem[key]) continue;
if (typeof currItem[key] === "string") {
if (currItem[key] === nextItem[key]) {
ret[key] = true;
}
} else if (typeof currItem[key] === "object") {
// Could do better than this, should be proper deepEqual polyfill
if (JSON.stringify(currItem[key]) === JSON.stringify(nextItem[key])) {
ret[key] = true;
}
}
}
}
Expand All @@ -85,12 +98,13 @@ CSL.Parallel.prototype.StartCitation = function (sortedItems, out) {
var partners = new CSL.Parallel.Partnerships(this.state, sortedItems);
var masterID = false;
for (var i=0,ilen=sortedItems.length; i<ilen; i++) {
var status = partners.update(i);
partners.update(i);
var status = partners.getPartnerStatus();
var currentID = partners.getID(i);
if (status === "first") {
sortedItems[i][1].parallel = "first";
if (i < ilen-1) {
sortedItems[i+1][1].parallel_repeats = partners._getPartnerRepeats(i);
sortedItems[i+1][1].parallel_repeats = partners._getPartnerRepeats(i, "changes_in");
sortedItems[i][1].parallel_repeats = sortedItems[i+1][1].parallel_repeats;
}
masterID = currentID;
Expand All @@ -99,7 +113,7 @@ CSL.Parallel.prototype.StartCitation = function (sortedItems, out) {
} else if (status === "mid") {
sortedItems[i][1].parallel = "mid";
if (i < ilen-1) {
sortedItems[i+1][1].parallel_repeats = partners._getPartnerRepeats(i);
sortedItems[i+1][1].parallel_repeats = partners._getPartnerRepeats(i, "changes_in");
}
if (!sortedItems[i][1].prefix) {
sortedItems[i][1].prefix = ", ";
Expand All @@ -111,26 +125,45 @@ CSL.Parallel.prototype.StartCitation = function (sortedItems, out) {
sortedItems[i][1].prefix = ", ";
}
if (i < ilen-1) {
sortedItems[i+1][1].parallel_repeats = partners._getPartnerRepeats(i);
sortedItems[i+1][1].parallel_repeats = partners._getPartnerRepeats(i, "changes_in");
}
this.state.registry.registry[masterID].siblings.push(currentID);
}
// Set repeats map here?
if (this.state.opt.parallel.no_repeat) {
if (i < ilen-1) {
sortedItems[i+1][1].no_repeat_repeats = partners._getPartnerRepeats(i, "no_repeat");
}
}
}
}
};


CSL.Parallel.prototype.checkRepeats = function(obj) {
var purgeme = false;
if (obj.no_repeat_repeats && obj.no_repeat_condition) {
var matches = 0;
for (var j=0,jlen=obj.no_repeat_condition.length; j<jlen; j++) {
if (obj.no_repeat_repeats[obj.no_repeat_condition[j]]) {
matches += 1;
}
}
if (matches === obj.no_repeat_condition.length) {
purgeme = true;
}
}
return purgeme;
};

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.parallel_repeats) {
purgeme = false;
} else {
if (obj.condition) {
var purgeme = true;
if (!obj.result || obj.result === obj.condition) {
purgeme = false;
}
var purgeme = false;
if (obj.result && obj.condition) {
var purgeme = true;
if (!obj.result || obj.result === obj.condition) {
purgeme = false;
}
if (purgeme && obj.changes_in_condition && obj.parallel_repeats) {
//if (purgeme && obj.changes_in_condition && obj.parallel_repeats)
Expand Down

0 comments on commit 5809c19

Please sign in to comment.