angular-cn/aio/tools/transforms/links-package/services/getLinkInfo.js

85 lines
3.2 KiB
JavaScript

var path = require('canonical-path');
/**
* @dgService getLinkInfo
* @description
* Get link information to a document that matches the given url
* @kind function
* @param {String} url The url to match
* @param {String} title An optional title to return in the link information
* @return {Object} The link information
*
* @property {boolean} relativeLinks Whether we expect the links to be relative to the originating doc
* @property {array<function(url, title, currentDoc, ambiguousDocs) : array} disambiguators a collection of functions
* that attempt to resolve ambiguous links. Each disambiguator returns a new collection of docs with
* unwanted ambiguous docs removed (see moduleScopeLinkDisambiguator service for an example).
*/
module.exports = function getLinkInfo(getDocFromAlias, encodeCodeBlock, log) {
getLinkInfoImpl.disambiguators = [];
return getLinkInfoImpl;
function getLinkInfoImpl(url, title, currentDoc) {
var linkInfo = {url: url, type: 'url', valid: true, title: title || url};
if (!url) {
throw new Error('Invalid url');
}
var docs = getDocFromAlias(url, currentDoc);
// Give each disambiguator a chance to reduce the number of ambiguous docs
docs = getLinkInfoImpl.disambiguators.reduce(function(docs, disambiguator) {
return disambiguator(url, title, currentDoc, docs);
}, docs);
if (!getLinkInfoImpl.useFirstAmbiguousLink && docs.length > 1) {
linkInfo.valid = false;
linkInfo.errorType = 'ambiguous';
linkInfo.error = 'Ambiguous link: "' + url + '".\n' + docs.reduce(function(msg, doc) {
return msg + '\n "' + doc.id + '" (' + doc.docType + ') : (' + doc.path + ' / ' +
doc.fileInfo.relativePath + ')';
}, 'Matching docs: ');
} else if (docs.length >= 1) {
linkInfo.url = docs[0].path;
linkInfo.title = title || docs[0].title || docs[0].name && encodeCodeBlock(docs[0].name, true);
linkInfo.type = 'doc';
if (getLinkInfoImpl.relativeLinks && currentDoc && currentDoc.path) {
var currentFolder = path.dirname(currentDoc.path);
var docFolder = path.dirname(linkInfo.url);
var relativeFolder =
path.relative(path.join('/', currentFolder), path.join('/', docFolder));
linkInfo.url = path.join(relativeFolder, path.basename(linkInfo.url));
log.debug(currentDoc.path, docs[0].path, linkInfo.url);
}
} else if (url.indexOf('#') > 0) {
var pathAndHash = url.split('#');
linkInfo = getLinkInfoImpl(pathAndHash[0], title, currentDoc);
linkInfo.url = linkInfo.url + '#' + pathAndHash[1];
return linkInfo;
} else if (url.indexOf('/') === -1 && url.indexOf('#') !== 0) {
linkInfo.valid = false;
linkInfo.errorType = 'missing';
linkInfo.error = 'Invalid link (does not match any doc): "' + url + '"';
} else {
linkInfo.title =
title || ((url.indexOf('#') === 0) ? url.substring(1) : path.basename(url, '.html'));
}
if (linkInfo.title === undefined) {
linkInfo.valid = false;
linkInfo.errorType = 'no-title';
linkInfo.error = 'The link is missing a title';
}
return linkInfo;
}
};