mediawiki-extensions-Cite/lib/ext/Cite/ReferencesData.js

101 lines
2.9 KiB
JavaScript
Raw Normal View History

'use strict';
const ParsoidExtApi = module.parent.parent.parent.require('./extapi.js').versionCheck('^0.10.0');
const { ContentUtils, Sanitizer } = ParsoidExtApi;
const RefGroup = require('./RefGroup.js');
/**
* @class
*/
class ReferencesData {
constructor(env) {
this.index = 0;
this.env = env;
this.refGroups = new Map();
}
makeValidIdAttr(val) {
// Looks like Cite.php doesn't try to fix ids that already have
// a "_" in them. Ex: name="a b" and name="a_b" are considered
// identical. Not sure if this is a feature or a bug.
// It also considers entities equal to their encoding
// (i.e. '&' === '&'), which is done:
// in PHP: Sanitizer#decodeTagAttributes and
// in Parsoid: ExtensionHandler#normalizeExtOptions
return Sanitizer.escapeIdForAttribute(val);
}
getRefGroup(groupName, allocIfMissing) {
groupName = groupName || '';
if (!this.refGroups.has(groupName) && allocIfMissing) {
this.refGroups.set(groupName, new RefGroup(groupName));
}
return this.refGroups.get(groupName);
}
removeRefGroup(groupName) {
if (groupName !== null && groupName !== undefined) {
// '' is a valid group (the default group)
this.refGroups.delete(groupName);
}
}
add(env, groupName, refName, about, skipLinkback) {
var group = this.getRefGroup(groupName, true);
refName = this.makeValidIdAttr(refName);
var ref;
if (refName && group.indexByName.has(refName)) {
ref = group.indexByName.get(refName);
if (ref.content && !ref.hasMultiples) {
ref.hasMultiples = true;
// Use the non-pp version here since we've already stored attribs
// before putting them in the map.
ref.cachedHtml = ContentUtils.toXML(env.fragmentMap.get(ref.content)[0], { innerXML: true });
}
} else {
// The ids produced Cite.php have some particulars:
// Simple refs get 'cite_ref-' + index
// Refs with names get 'cite_ref-' + name + '_' + index + (backlink num || 0)
// Notes (references) whose ref doesn't have a name are 'cite_note-' + index
// Notes whose ref has a name are 'cite_note-' + name + '-' + index
var n = this.index;
var refKey = (1 + n) + '';
var refIdBase = 'cite_ref-' + (refName ? refName + '_' + refKey : refKey);
var noteId = 'cite_note-' + (refName ? refName + '-' + refKey : refKey);
// bump index
this.index += 1;
ref = {
about: about,
content: null,
dir: '',
group: group.name,
groupIndex: group.refs.length + 1,
index: n,
key: refIdBase,
id: (refName ? refIdBase + '-0' : refIdBase),
linkbacks: [],
name: refName,
target: noteId,
hasMultiples: false,
// Just used for comparison when we have multiples
cachedHtml: '',
};
group.refs.push(ref);
if (refName) {
group.indexByName.set(refName, ref);
}
}
if (!skipLinkback) {
ref.linkbacks.push(ref.key + '-' + ref.linkbacks.length);
}
return ref;
}
}
module.exports = ReferencesData;