const mdIt = require('markdown-it')()
, mdItAttr = require('markdown-it-attrs');
// markdown-it plugin
mdIt.use(mdItAttr, {
leftDelimiter: '{',
rightDelimiter: '}',
allowedAttributes: []
})
/**
* Catch links from Mardown file content
* @param {string} fileContent - Mardown file content
* @returns {array} - Objets array : links with type & target id
*/
function catchLinksFromContent(fileContent) {
let tempL = {}, // temp link container
links = []; // final link container
/**
* Get all paragraphs from the file content
*/
const paraphs = fileContent.match(/[^\r\n]+((\r|\n|\r\n)[^\r\n]+)*/g);
if (paraphs === null) { return []; }
/**
* Get all links from each paragraph
*/
for (let i = 0; i < paraphs.length; i++) {
// get string '***' from '[[***]]' (wikilinks), for each paragraph
let linksId = paraphs[i].match(/(?<=\[\[\s*).*?(?=\s*\]\])/gs);
if (!linksId) { continue; }
for (const linkId of linksId) {
// each linkId is put to 'tempL', for get a list witout duplicated links
if (tempL[linkId]) {
// if the linkId is already registered, we juste save one more paragraph number
tempL[linkId].paraphs.push(i)
} else {
// if the linkId is new, we register its type and a paragraph number
tempL[linkId] = normalizeLink(linkId);
tempL[linkId].paraphs = [i]
}
}
}
/**
* Put context (original paragraph) into each link
*/
for (const linkId in tempL) {
tempL[linkId].context = [];
for (let i = 0; i < paraphs.length; i++) {
// for each paraph number from the link
if (tempL[linkId].paraphs.includes(i)) {
let par = paraphs[i]; // Markdown paraph
par = mdIt.render(par); // HTML paraph
// find the link string into the paraph and <mark> it
par = par.replace('[[' + linkId + ']]', '<mark>[[' + linkId + ']]</mark>');
tempL[linkId].context.push(par);
}
}
// paraphs array to context string
tempL[linkId].context = tempL[linkId].context.join('');
links.push(tempL[linkId]); // put all link metas on final 'links' container
}
return links;
}
exports.catchLinksFromContent = catchLinksFromContent;
/**
* Get node rank from number of links & backlinks
* @param {number} backLinkNb - Number of backlinks
* @param {number} linkNb - Number of links
* @returns {number} - Rank
*/
function getRank(backLinkNb, linkNb) {
let rank = 1 // original rank
, sizeDivisor = 2; // to subside rank
rank += Math.floor(linkNb / sizeDivisor);
rank += Math.floor(backLinkNb / sizeDivisor);
return rank;
}
exports.getRank = getRank;
/**
* Add its type to a link & turn its target id to int value
* @param {string} link - The wikilink content, '***' from '[[***]]'
* @returns {object} - Object : link type & target
*/
function normalizeLink(link) {
link = link.split(':', 2);
if (link.length === 2) {
return {type: link[0], target: {id: Number(link[1])} };
}
// default value
return {type: 'undefined', target: {id: Number(link[0])} };
}
/**
* Add Mardown attributes to valid links into file content
* Leave disabled links as simple text
* @param {string} content - Mardown file content
* @param {object} file - File after links parsing
* @returns {string} - Mardown content with converted links
*/
function convertLinks(content, file) {
return content.replace(/(\[\[\s*).*?(\]\])/g, function(extract) { // get '[[***]]' strings
// extract link id, without '[[' & ']]' caracters
let link = extract.slice(0, -2).slice(2);
link = normalizeLink(link).target.id;
if (link === NaN) { return extract; } // link is not a number
const associatedMetas = file.links.find(function(i) {
return i.target.id === link; });
// link is not registred into file metas
if (associatedMetas === undefined) { return extract; }
link = associatedMetas;
// return '[[***]]' string into a Mardown link with openRecord function & class
return `[${extract}](#${link.target.id}){title="${link.target.title}" onclick=openRecord(${link.target.id}) .record-link}`;
});
}
exports.convertLinks = convertLinks;