diff --git a/docs/docs.config.js b/docs/docs.config.js index f639ce6879..2c8fd31177 100644 --- a/docs/docs.config.js +++ b/docs/docs.config.js @@ -23,7 +23,7 @@ module.exports = function(config) { var versionData = require('./generate-versions')(config); config.set('versionData', versionData); - config.set('rendering.contentsFolder', 'docs/' + versionData.current.folder); + config.set('rendering.contentsFolder', path.join('docs', versionData.current.folder)); config.set('processing.api-docs', { outputPath: 'api/${docType}/${name}/index.md', @@ -62,10 +62,11 @@ module.exports = function(config) { }); config.append('processing.processors', [ - require('./processors/version-data'), + require('./processors/latest-version'), require('./processors/keywords'), require('./processors/pages-data'), require('./processors/index-page'), + require('./processors/version-data') ]); return config; diff --git a/docs/generate-versions.js b/docs/generate-versions.js index 7249daf104..0dfbf8ce8d 100644 --- a/docs/generate-versions.js +++ b/docs/generate-versions.js @@ -10,61 +10,28 @@ module.exports = function(config) { var docsBaseFolder = path.resolve(basePath, outputFolder, 'docs'); - var versions; - try { - versions = require(docsBaseFolder + '/version-data.json'); - } catch(e) { - versions = []; - } + var versions = fs.readdirSync(docsBaseFolder) + .filter(semver.valid) + .sort(semver.rcompare); - var hasNightlyVersion = currentVersion == 'nightly' || - _.find(versions, {name: 'nightly'}); - var nightlyVersion = { - href: '/docs/nightly', - folder: 'nightly', - name: 'nightly' - }; + !_.contains(versions, currentVersion) && versions.unshift(currentVersion); + !_.contains(versions, 'nightly') && versions.unshift('nightly'); - //Remove nightly from versions before trying to sort things out - //because it's different (the only non-semver version) - _.remove(versions, {name: 'nightly'}); - - if (currentVersion == 'nightly') { - //do nothing - - } else if ( !_.find(versions, {name: currentVersion}) ) { - //If version doesn't exist, add it... - versions.unshift({ - href: '/docs/latest', - folder: 'latest', - name: currentVersion - }); - - versions.forEach(function(version, index) { - //Make sure the other versions aren't still latest, - //if so rename them - if (_.contains(version.href, 'latest') && index > 0) { - version.href = '/docs/'+version.name, - version.folder = version.name; - fs.unlinkSync(docsBaseFolder + '/' + version.name); - fs.renameSync( - docsBaseFolder + '/latest', - docsBaseFolder + '/' + version.name - ); - } - }); - } - - //Add nightly back to front if it exists - if (hasNightlyVersion) { - versions.unshift(nightlyVersion); - } - console.log(versions); + //First semver valid version is latest + var latestVersion = _.find(versions, semver.valid); + versions = versions.map(function(version) { + //Latest version is in docs root + var folder = version == latestVersion ? '' : version; + return { + href: path.join('/docs', folder), + folder: folder, + name: version + }; + }); return { list: versions, current: _.find(versions, { name: currentVersion }), - latest: _.find(versions, function(v) { return semver.valid(v.name); }) || - _.first(versions) + latest: _.find(versions, {name: latestVersion}) || _.first(versions) }; }; diff --git a/docs/processors/latest-version.js b/docs/processors/latest-version.js new file mode 100644 index 0000000000..6f0706a0f1 --- /dev/null +++ b/docs/processors/latest-version.js @@ -0,0 +1,22 @@ +var copy = require('cp-r'); +var mkdirp = require('mkdirp'); +var path = require('canonical-path'); + +module.exports = { + name: 'latest-version', + runAfter: ['write-files'], + description: 'Copy the latest version (that was compiled to docs/latest) into docs/versionName', + process: function(docs, config) { + var versionData = config.get('versionData'); + + var docsBase = path.join(config.get('basePath'), config.get('rendering.outputFolder'), 'docs'); + var versionDir = path.join(docsBase, versionData.latest.name); + var latestDir = path.join(docsBase, 'api'); + + mkdirp(versionDir, function() { + copy(latestDir, path.join(versionDir, 'api'), { + deleteFirst: true + }); + }); + } +}; diff --git a/docs/processors/pages-data.js b/docs/processors/pages-data.js index 20777ec1b5..8cba473598 100644 --- a/docs/processors/pages-data.js +++ b/docs/processors/pages-data.js @@ -2,130 +2,6 @@ var _ = require('lodash'); var path = require('canonical-path'); var log = require('winston'); -var AREA_NAMES = { - api: 'API', - guide: 'Developer Guide', - misc: 'Miscellaneous', - tutorial: 'Tutorial', - error: 'Error Reference' -}; - -function getNavGroup(pages, area, pageSorter, pageMapper) { - - var navItems = _(pages) - // We don't want the child to include the index page as this is already catered for - .omit(function(page) { return page.id === 'index'; }) - - // Apply the supplied sorting function - .sortBy(pageSorter) - - // Apply the supplied mapping function - .map(pageMapper) - - .value(); - - return { - name: area.name, - type: 'group', - href: area.id, - navItems: navItems - }; -} - - -var navGroupMappers = { - api: function(areaPages, area) { - var navGroups = _(areaPages) - .groupBy('module') - - .map(function(modulePages, moduleName) { - log.debug('moduleName: ' + moduleName); - var navItems = []; - var modulePath; - - _(modulePages) - - .groupBy('docType') - - .tap(function(docTypes) { - log.debug(_.keys(docTypes)); - modulePath = 'api/ionic'; - delete docTypes.module; - }) - - .tap(function(docTypes) { - if ( docTypes.input ) { - docTypes.directive = docTypes.directive || []; - // Combine input docTypes into directive docTypes - docTypes.directive = docTypes.directive.concat(docTypes.input); - delete docTypes.input; - } - }) - - .forEach(function(sectionPages, sectionName) { - - sectionPages = _.sortBy(sectionPages, 'name'); - - if ( sectionPages.length > 0 ) { - // Push a navItem for this section - navItems.push({ - name: sectionName, - type: 'section', - href: path.dirname(sectionPages[0].path) - }); - - // Push the rest of the sectionPages for this section - _.forEach(sectionPages, function(sectionPage) { - - navItems.push({ - name: sectionPage.name, - href: sectionPage.path, - type: sectionPage.docType - }); - - }); - } - }); - return { - name: moduleName, - href: modulePath, - type: 'group', - navItems: navItems - }; - }) - .value(); - return navGroups; - }, - tutorial: function(pages, area) { - return [getNavGroup(pages, area, 'step', function(page) { - return { - name: page.name, - step: page.step, - href: page.path, - type: 'tutorial' - }; - })]; - }, - error: function(pages, area) { - return [getNavGroup(pages, area, 'path', function(page) { - return { - name: page.name, - href: page.path, - type: page.docType === 'errorNamespace' ? 'section' : 'error' - }; - })]; - }, - pages: function(pages, area) { - return [getNavGroup(pages, area, 'path', function(page) { - return { - name: page.name, - href: page.path, - type: 'page' - }; - })]; - } -}; - var outputFolder; var processorConfig; var currentVersion; @@ -142,53 +18,61 @@ module.exports = { currentVersion = config.get('currentVersion'); }, process: function(docs) { - - _(docs) - .filter(function(doc) { return doc.area === 'api'; }) - .filter(function(doc) { return doc.docType === 'module'; }) - .map(function(doc) { return _.pick(doc, ['id', 'module', 'docType', 'area']); }) - .tap(function(docs) { - log.debug(docs); - }); - - - // We are only interested in docs that are in a area and not landing pages - var navPages = _.filter(docs, function(page) { - return page.area && - page.docType != 'componentGroup'; - }); - - // Generate an object collection of pages that is grouped by area e.g. - // - area "api" - // - group "ng" - // - section "directive" - // - ngApp - // - ngBind - // - section "global" - // - angular.element - // - angular.bootstrap - // - section "service" - // - $compile - // - group "ngRoute" - // - section "directive" - // - ngView - // - section "service" - // - $route + // Generate an object collection of pages that is grouped by section e.g. + // - section "directive" + // - group "Tab Bar" + // - ion-tabs + // - ion-tab + // - group "" + // - ion-toggle + // - ion-checkbox + // - ... // - var areas = {}; - _(navPages) - .groupBy('area') - .forEach(function(pages, areaId) { - var area = { - id: areaId, - name: AREA_NAMES[areaId] + var groups = _(docs) + .filter(function(doc) { return doc.area === 'api'; }) + .filter(function(doc) { return doc.module === 'ionic'; }) + .filter(function(doc) { return doc.docType !== 'componentGroup'; }) + .groupBy(function(doc) { if (!doc.group) doc.group = 'Other'; return doc.group; }) + .map(function(pages, groupName) { + var sections = _(pages) + .groupBy('docType') + .map(function(pages, docType) { + return { + name: docType, + pages: _(pages) + .sortBy(function(doc) { + return doc.groupMainItem; + }) + .map(function(doc) { + return { + href: doc.path, + name: doc.name, + docType: doc.docType, + type: doc.docType, + }; + }) + .filter(function(doc) { + return !!doc.name; + }) + .value() + }; + }) + .sortBy(function(section) { + //Directives always first + return section.name != 'directive'; + }) + .value(); + + return { + name: groupName, + sections: sections }; - areas[areaId] = area; - - var navGroupMapper = navGroupMappers[area.id] || navGroupMappers['pages']; - area.navGroups = navGroupMapper(pages, area); - }); - + }) + .sortBy(function(group) { + //Sort by groups with most items last + return _.values(group.sections).length; + }) + .value(); _.forEach(docs, function(doc) { if ( !doc.path ) { @@ -196,25 +80,13 @@ module.exports = { } }); - // Extract a list of basic page information for mapping paths to paritals and for client side searching - var pages = _(docs) - .map(function(doc) { - var page = _.pick(doc, [ - 'docType', 'id', 'name', 'area', 'outputPath', 'path', 'searchTerms' - ]); - return page; - }) - .indexBy('path') - .value(); - var docData = { docType: 'pages-data', id: 'pages-data', template: processorConfig.template || 'pages-data.template.js', outputPath: processorConfig.outputPath || 'js/pages-data.js', - areas: areas, - pages: pages + groups: groups }; docs.push(docData); diff --git a/docs/processors/version-data.js b/docs/processors/version-data.js index 8d4d53f239..d0baf3761f 100644 --- a/docs/processors/version-data.js +++ b/docs/processors/version-data.js @@ -1,13 +1,8 @@ module.exports = { name: 'version-data', - runBefore: ['pages-data'], - process: function(docs, config, extraData) { + runBefore: ['api-docs'], + description: 'Expose version data to templates', + process: function(extraData, config) { extraData.version = config.get('versionData'); - docs.push({ - docType: 'version-data', - id: 'version-data', - template: 'version-data.template.json', - outputPath: 'docs/version-data.json' - }); } }; diff --git a/docs/tag-defs/index.js b/docs/tag-defs/index.js index d58ab8de5b..a359735cd8 100644 --- a/docs/tag-defs/index.js +++ b/docs/tag-defs/index.js @@ -1,19 +1,19 @@ -function linkify(type, id) { - return '{@link ionic.' + type + ':' + id.trim() + '}'; -} module.exports = [ { name: 'controller', transformFn: function(doc, tag) { - return linkify('controller', tag.description); + return '{@link ionic.controller:' + tag.description.trim() + '}'; } }, { name: 'parent', transformFn: function(doc, tag) { - return tag.description.split(',').map(function(id) { - return linkify('directive', id); + doc.parentLinks = tag.description.split(',').map(function(id) { + return '{@link ' + id.trim() + '}'; }).join(' or '); + return tag.description.split(',').map(function(parent) { + return parent.trim(); + }); } }, { @@ -21,5 +21,11 @@ module.exports = [ }, { name: 'alias' + }, + { + name: 'group' + }, + { + name: 'groupMainItem' } ]; diff --git a/docs/templates/api/api.template.html b/docs/templates/api/api.template.html index 9ff738a363..1f870fb7f6 100644 --- a/docs/templates/api/api.template.html +++ b/docs/templates/api/api.template.html @@ -21,9 +21,9 @@ docType: "<$ doc.docType $>" <@ else @> <$ doc.name $> <@ endif @> -<@ if doc.parent @> +<@ if doc.parentLinks @> - (child of <$ doc.parent $>) + (child of <$ doc.parentLinks $>) <@ endif @> <@ if doc.controller @> diff --git a/docs/templates/lib/yaml.template.html b/docs/templates/lib/yaml.template.html index b04d7e293a..be274e61f3 100644 --- a/docs/templates/lib/yaml.template.html +++ b/docs/templates/lib/yaml.template.html @@ -2,3 +2,4 @@ layout: docs_api version: "<$ version.current.name $>" versionHref: "<$ version.current.href $>" path: "<$ doc.path $>" +group: "<$ doc.group $>" diff --git a/docs/templates/pages-data.template.html b/docs/templates/pages-data.template.html index 57ea047021..f2f11b41e2 100644 --- a/docs/templates/pages-data.template.html +++ b/docs/templates/pages-data.template.html @@ -57,26 +57,34 @@
diff --git a/js/ext/angular/src/directive/ionicBar.js b/js/ext/angular/src/directive/ionicBar.js index 25bfb2ac9f..032ae2b7af 100644 --- a/js/ext/angular/src/directive/ionicBar.js +++ b/js/ext/angular/src/directive/ionicBar.js @@ -18,6 +18,7 @@ angular.module('ionic.ui.header', ['ngAnimate', 'ngSanitize']) * @name ionHeaderBar * @module ionic * @restrict E + * @group page layout * @controller ionicBar * * @description @@ -26,8 +27,8 @@ angular.module('ionic.ui.header', ['ngAnimate', 'ngSanitize']) * Is able to have left or right buttons, and additionally its title can be * aligned through the {@link ionic.controller:ionicBar ionicBar controller}. * - * @param {string=} model The model to assign this headerBar's - * {@link ionic.controller:ionicBar ionicBar controller} to. + * @param {string=} model The model to assign this headerBar's + * {@link ionic.controller:ionicBar ionicBar controller} to. * Defaults to assigning to $scope.headerBarController. * @param {string=} align-title Where to align the title at the start. * Avaialble: 'left', 'right', or 'center'. Defaults to 'center'. @@ -55,6 +56,7 @@ angular.module('ionic.ui.header', ['ngAnimate', 'ngSanitize']) * @name ionFooterBar * @module ionic * @restrict E + * @group page layout * @controller ionicBar * * @description @@ -63,8 +65,8 @@ angular.module('ionic.ui.header', ['ngAnimate', 'ngSanitize']) * Is able to have left or right buttons, and additionally its title can be * aligned through the {@link ionic.controller:ionicBar ionicBar controller}. * - * @param {string=} model The model to assign this footerBar's - * {@link ionic.controller:ionicBar ionicBar controller} to. + * @param {string=} model The model to assign this footerBar's + * {@link ionic.controller:ionicBar ionicBar controller} to. * Defaults to assigning to $scope.footerBarController. * @param {string=} align-title Where to align the title at the start. * Avaialble: 'left', 'right', or 'center'. Defaults to 'center'. @@ -91,8 +93,8 @@ function barDirective(isHeader) { var BAR_TEMPLATE = isHeader ? '