'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); const hasRefName = refName.length > 0; var ref; if (hasRefName && 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-' + (hasRefName ? refName + '_' + refKey : refKey); var noteId = 'cite_note-' + (hasRefName ? 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: (hasRefName ? 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;