build(aio): big move of docs related files (#14361)

All the docs related files (docs-app, doc-gen, content, etc)
are now to be found inside the `/aio` folder.

The related gulp tasks have been moved from the top level
gulp file to a new one inside the `/aio` folder.

The structure of the `/aio` folder now looks like:

```
/aio/
  build/         # gulp tasks
  content/       #MARKDOWN FILES for devguides, cheatsheet, etc
    devguides/
    cheatsheets/
  transforms/    #dgeni packages, templates, etc
  src/
    app/
    assets/
    content/    #HTML + JSON build artifacts produced by dgeni from /aio/content.
                #This dir is .gitignored-ed
  e2e/           #protractor tests for the doc viewer app
  node_modules/ #dependencies for both the doc viewer builds and the dgeni stuff
                #This dir is .gitignored-ed
  gulpfile.js   #Tasks for generating docs and building & deploying the doc viewer
```

Closes #14361
This commit is contained in:
Pete Bacon Darwin
2017-02-09 19:58:36 +00:00
committed by Igor Minar
parent 5e7a2fa854
commit 600402d440
437 changed files with 855 additions and 531 deletions

View File

@ -0,0 +1,22 @@
var Package = require('dgeni').Package;
var jsdocPackage = require('dgeni-packages/jsdoc');
module.exports =
new Package('links', [jsdocPackage])
.factory(require('./inline-tag-defs/link'))
.factory(require('./services/getAliases'))
.factory(require('./services/getDocFromAlias'))
.factory(require('./services/getLinkInfo'))
.factory(require('./services/moduleScopeLinkDisambiguator'))
.factory(require('./services/deprecatedDocsLinkDisambiguator'))
.config(function(inlineTagProcessor, linkInlineTagDef) {
inlineTagProcessor.inlineTagDefinitions.push(linkInlineTagDef);
})
.config(function(
getLinkInfo, moduleScopeLinkDisambiguator, deprecatedDocsLinkDisambiguator) {
getLinkInfo.disambiguators.push(moduleScopeLinkDisambiguator);
getLinkInfo.disambiguators.push(deprecatedDocsLinkDisambiguator);
});

View File

@ -0,0 +1,35 @@
var INLINE_LINK = /(\S+)(?:\s+([\s\S]+))?/;
/**
* @dgService linkInlineTagDef
* @description
* Process inline link tags (of the form {@link some/uri Some Title}), replacing them with HTML anchors
* @kind function
* @param {Object} url The url to match
* @param {Function} docs error message
* @return {String} The html link information
*
* @property {boolean} relativeLinks Whether we expect the links to be relative to the originating doc
*/
module.exports = function linkInlineTagDef(getLinkInfo, createDocMessage, log) {
return {
name: 'link',
aliases: ['linkDocs'],
description:
'Process inline link tags (of the form {@link some/uri Some Title}), replacing them with HTML anchors',
handler: function(doc, tagName, tagDescription) {
// Parse out the uri and title
return tagDescription.replace(INLINE_LINK, function(match, uri, title) {
var linkInfo = getLinkInfo(uri, title, doc);
if (!linkInfo.valid) {
log.warn(createDocMessage(linkInfo.error, doc));
}
return '<a href=\'' + linkInfo.url + '\'>' + linkInfo.title + '</a>';
});
}
};
};

View File

@ -0,0 +1,12 @@
var _ = require('lodash');
module.exports = function deprecatedDocsLinkDisambiguator() {
return function(url, title, currentDoc, docs) {
if (docs.length != 2) return docs;
var filteredDocs = _.filter(
docs, function(doc) { return !doc.fileInfo.relativePath.match(/\/(\w+)-deprecated\//); });
return filteredDocs.length > 0 ? filteredDocs : docs;
};
};

View File

@ -0,0 +1,71 @@
function parseCodeName(codeName) {
var parts = [];
var currentPart;
codeName.split('.').forEach(function(part) {
var subParts = part.split(':');
var name = subParts.pop();
var modifier = subParts.pop();
if (!modifier && currentPart) {
currentPart.name += '.' + name;
} else {
currentPart = {name: name, modifier: modifier};
parts.push(currentPart);
}
});
return parts;
}
/**
* @dgService getAliases
* @description
* Get a list of all the aliases that can be made from the doc
* @param {Object} doc A doc from which to extract aliases
* @return {Array} A collection of aliases
*/
module.exports = function getAliases() {
return function(doc) {
var codeNameParts = parseCodeName(doc.id);
var methodName;
var aliases = [];
// Add the last part to the list of aliases
var part = codeNameParts.pop();
// If the name contains a # then it is a member and that should be included in the aliases
if (part.name.indexOf('#') !== -1) {
methodName = part.name.split('#')[1];
}
// Add the part name and modifier, if provided
aliases.push(part.name);
if (part.modifier) {
aliases.push(part.modifier + ':' + part.name);
}
// Continue popping off the parts of the codeName and work forward collecting up each alias
aliases = codeNameParts.reduceRight(function(aliases, part) {
// Add this part to each of the aliases we have so far
aliases.forEach(function(name) {
// Add the part name and modifier, if provided
aliases.push(part.name + '.' + name);
if (part.modifier) {
aliases.push(part.modifier + ':' + part.name + '.' + name);
}
});
return aliases;
}, aliases);
if (methodName) {
aliases.push(methodName);
}
return aliases;
};
};

View File

@ -0,0 +1,14 @@
var getAliasesFactory = require('./getAliases');
describe('getAliases', function() {
it('should extract all the parts from a code name', function() {
var getAliases = getAliasesFactory();
expect(getAliases({id: 'module:ng.service:$http#get'})).toEqual([
'$http#get', 'service:$http#get', 'ng.$http#get', 'module:ng.$http#get',
'ng.service:$http#get', 'module:ng.service:$http#get', 'get'
]);
});
});

View File

@ -0,0 +1,31 @@
var _ = require('lodash');
/**
* @dgService getDocFromAlias
* @description Get an array of docs that match this alias, relative to the originating doc.
*/
module.exports = function getDocFromAlias(aliasMap, log) {
return function getDocFromAlias(alias, originatingDoc) {
var docs = aliasMap.getDocs(alias);
// If there is more than one item with this name then try to filter them by the originatingDoc's
// area
if (docs.length > 1 && originatingDoc && originatingDoc.area) {
docs = _.filter(docs, function(doc) { return doc.area === originatingDoc.area; });
}
// If filtering by area left us with none then let's start again
if (docs.length === 0) {
docs = aliasMap.getDocs(alias);
}
// If there is more than one item with this name then try to filter them by the originatingDoc's
// module
if (docs.length > 1 && originatingDoc && originatingDoc.module) {
docs = _.filter(docs, function(doc) { return doc.module === originatingDoc.module; });
}
return docs;
};
};

View File

@ -0,0 +1,48 @@
var testPackage = require('../../helpers/test-package');
var Dgeni = require('dgeni');
var getDocFromAlias, aliasMap;
describe('getDocFromAlias', function() {
beforeEach(function() {
var dgeni = new Dgeni([testPackage('links-package', true)]);
var injector = dgeni.configureInjector();
aliasMap = injector.get('aliasMap');
getDocFromAlias = injector.get('getDocFromAlias');
});
it('should return an array of docs that match the alias', function() {
var doc1 = {aliases: ['a', 'b', 'c']};
var doc2 = {aliases: ['a', 'b']};
var doc3 = {aliases: ['a']};
aliasMap.addDoc(doc1);
aliasMap.addDoc(doc2);
aliasMap.addDoc(doc3);
expect(getDocFromAlias('a')).toEqual([doc1, doc2, doc3]);
expect(getDocFromAlias('b')).toEqual([doc1, doc2]);
expect(getDocFromAlias('c')).toEqual([doc1]);
});
it('should return docs that match the alias and originating doc\'s area', function() {
var doc1 = {aliases: ['a'], area: 'api'};
var doc2 = {aliases: ['a'], area: 'api'};
var doc3 = {aliases: ['a'], area: 'other'};
aliasMap.addDoc(doc1);
aliasMap.addDoc(doc2);
aliasMap.addDoc(doc3);
expect(getDocFromAlias('a', {area: 'api'})).toEqual([doc1, doc2]);
});
it('should return docs that match the alias and originating doc\'s area and module', function() {
var doc1 = {aliases: ['a'], area: 'api', module: 'ng'};
var doc2 = {aliases: ['a'], area: 'api', module: 'ngMock'};
var doc3 = {aliases: ['a'], area: 'other', module: 'ng'};
aliasMap.addDoc(doc1);
aliasMap.addDoc(doc2);
aliasMap.addDoc(doc3);
expect(getDocFromAlias('a', {area: 'api', module: 'ng'})).toEqual([doc1]);
});
});

View File

@ -0,0 +1,78 @@
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 || 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'));
}
return linkInfo;
};
};

View File

@ -0,0 +1,15 @@
var _ = require('lodash');
module.exports = function moduleScopeLinkDisambiguator() {
return function(url, title, currentDoc, docs) {
if (docs.length > 1) {
// filter out target docs that are not in the same module as the source doc
var filteredDocs =
_.filter(docs, function(doc) { return doc.moduleDoc === currentDoc.moduleDoc; });
// if all target docs are in a different module then just return the full collection of
// ambiguous docs
return filteredDocs.length > 0 ? filteredDocs : docs;
}
return docs;
};
};