Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 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 | 5x 87x 87x 87x 2x 2x 2x 8x 8x 8x 6x 1x 5x 5x 1x 4x 4x 2x 2x 2x 941x 873x 68x 68x 14x 68x 11x 112x 112x | import _ from 'lodash';
import * as linkProcessor from './linkProcessor.js';
import type { NodeProcessorConfig } from './NodeProcessor.js';
import { MbNode } from '../utils/node.js';
import { setHeadingId } from './headerProcessor.js';
const tagsToValidate: Set<string> = new Set([
'img',
'pic',
'thumbnail',
'a',
'link',
'script',
]);
export class SiteLinkManager {
protected config: NodeProcessorConfig;
protected intralinkCollection: Map<string, Set<string>>;
protected filePathToHashesMap: Map<string, Set<string>>;
constructor(config: NodeProcessorConfig) {
this.config = config;
this.intralinkCollection = new Map();
this.filePathToHashesMap = new Map();
}
/**
* Adds a resourcePath and cwf to the intralinkCollection,
* ensuring each pair of (resourcePath, cwf) appears only once
*/
_addToCollection(resourcePath: string, cwf: string) {
if (!this.intralinkCollection.has(cwf)) {
this.intralinkCollection.set(cwf, new Set());
}
// We have checked and set cwf in intralinkCollection above
this.intralinkCollection.get(cwf)!.add(resourcePath);
}
validateAllIntralinks() {
Iif (!this.config.intrasiteLinkValidation.enabled) {
return;
}
this.intralinkCollection.forEach((resourcePaths, cwf) => {
resourcePaths.forEach(resourcePath => linkProcessor.validateIntraLink(resourcePath,
cwf,
this.config,
this.filePathToHashesMap));
});
this.intralinkCollection = new Map();
}
/**
* Add a link to the intralinkCollection to be validated later,
* if the node should be validated and intralink validation is not disabled.
*/
collectIntraLinkToValidate(node: MbNode, cwf: string) {
if (!tagsToValidate.has(node.name)) {
return 'Should not validate';
}
const hasIntralinkValidationDisabled = _.has(node.attribs, 'no-validation');
if (hasIntralinkValidationDisabled) {
return 'Intralink validation disabled';
}
const resourcePath = linkProcessor.getDefaultTagsResourcePath(node);
if (!resourcePath || !linkProcessor.isIntraLink(resourcePath)) {
return 'Should not validate';
}
this._addToCollection(resourcePath, cwf);
return 'Intralink collected to be validated later';
}
/**
* Add sections that could be reached by intra-link with hash to this node to filePathToHashesMap,
* The reachable sections include nodes with ids and headings.
*/
maintainFilePathToHashesMap(node: MbNode, cwf: string) {
if (!this.config.intrasiteLinkValidation.enabled) {
return;
}
const path = cwf.substring(this.config.rootPath.length);
if (!this.filePathToHashesMap.has(path)) {
this.filePathToHashesMap.set(path, new Set());
}
if (node.attribs!.id) {
this.filePathToHashesMap.get(path)!.add(node.attribs!.id);
}
}
/**
* Recursively add reachable sections of the included node to the filePathToHashesMap for validation.
*/
maintainHashesForInclude(node: MbNode, cwf: string) {
if (!this.config.intrasiteLinkValidation.enabled) {
return;
}
const isHeadingTag = (/^h[1-6]$/).test(node.name);
Iif (isHeadingTag && node.attribs && !node.attribs.id) {
setHeadingId(node, this.config, false);
this.maintainFilePathToHashesMap(node, cwf);
node.attribs.id = undefined;
}
Iif (node.attribs && node.attribs.id) {
this.maintainFilePathToHashesMap(node, cwf);
}
Iif (node.children) {
node.children.forEach((child) => {
this.maintainHashesForInclude(child as MbNode, cwf);
});
}
}
}
|