From 389d4879da4aa620ee95d789b19ff9be44eb730a Mon Sep 17 00:00:00 2001 From: Peter Bacon Darwin Date: Wed, 12 Feb 2014 22:47:42 +0000 Subject: chore(doc-gen): new docs chore(doc-gen): implement dgeni --- docs/config/ignore.words | 701 ++++++++++++++++++++++++ docs/config/index.js | 29 + docs/config/processors/index-page.js | 42 ++ docs/config/processors/keywords.js | 91 +++ docs/config/processors/pages-data.js | 200 +++++++ docs/config/processors/versions-data.js | 42 ++ docs/config/tag-defs/tutorial-step.js | 9 + docs/config/templates/indexPage.template.html | 217 ++++++++ docs/config/templates/pages-data.template.js | 4 + docs/config/templates/tutorial.template.html | 1 + docs/config/templates/versions-data.template.js | 4 + 11 files changed, 1340 insertions(+) create mode 100644 docs/config/ignore.words create mode 100644 docs/config/index.js create mode 100644 docs/config/processors/index-page.js create mode 100644 docs/config/processors/keywords.js create mode 100644 docs/config/processors/pages-data.js create mode 100644 docs/config/processors/versions-data.js create mode 100644 docs/config/tag-defs/tutorial-step.js create mode 100644 docs/config/templates/indexPage.template.html create mode 100644 docs/config/templates/pages-data.template.js create mode 100644 docs/config/templates/tutorial.template.html create mode 100644 docs/config/templates/versions-data.template.js (limited to 'docs/config') diff --git a/docs/config/ignore.words b/docs/config/ignore.words new file mode 100644 index 00000000..82b9f2fc --- /dev/null +++ b/docs/config/ignore.words @@ -0,0 +1,701 @@ +a +able +about +above +abst +accordance +according +accordingly +across +act +actually +added +adj +adopted +affected +affecting +affects +after +afterwards +again +against +ah +all +almost +alone +along +already +also +although +always +am +among +amongst +an +and +announce +another +any +anybody +anyhow +anymore +anyone +anything +anyway +anyways +anywhere +apparently +approximately +are +aren +arent +arise +around +as +aside +ask +asking +at +auth +available +away +awfully +b +back +be +became +because +become +becomes +becoming +been +before +beforehand +begin +beginning +beginnings +begins +behind +being +believe +below +beside +besides +between +beyond +biol +both +brief +briefly +but +by +c +ca +came +can +cannot +can't +cant +cause +causes +certain +certainly +co +com +come +comes +contain +containing +contains +could +couldnt +d +date +did +didn't +didnt +different +do +does +doesn't +doesnt +doing +done +don't +dont +down +downwards +due +during +e +each +ed +edu +effect +eg +eight +eighty +either +else +elsewhere +end +ending +enough +especially +et +et-al +etc +even +ever +every +everybody +everyone +everything +everywhere +ex +except +f +far +few +ff +fifth +first +five +fix +followed +following +follows +for +former +formerly +forth +found +four +from +further +furthermore +g +gave +get +gets +getting +give +given +gives +giving +go +goes +gone +got +gotten +h +had +happens +hardly +has +hasn't +hasnt +have +haven't +havent +having +he +hed +hence +her +here +hereafter +hereby +herein +heres +hereupon +hers +herself +hes +hi +hid +him +himself +his +hither +home +how +howbeit +however +hundred +i +id +ie +if +i'll +ill +im +immediate +immediately +importance +important +in +inc +indeed +index +information +instead +into +invention +inward +is +isn't +isnt +it +itd +it'll +itll +its +itself +i've +ive +j +just +k +keep +keeps +kept +keys +kg +km +know +known +knows +l +largely +last +lately +later +latter +latterly +least +less +lest +let +lets +like +liked +likely +line +little +'ll +'ll +look +looking +looks +ltd +m +made +mainly +make +makes +many +may +maybe +me +mean +means +meantime +meanwhile +merely +mg +might +million +miss +ml +more +moreover +most +mostly +mr +mrs +much +mug +must +my +myself +n +na +name +namely +nay +nd +near +nearly +necessarily +necessary +need +needs +neither +never +nevertheless +new +next +nine +ninety +no +nobody +non +none +nonetheless +noone +nor +normally +nos +not +noted +nothing +now +nowhere +o +obtain +obtained +obviously +of +off +often +oh +ok +okay +old +omitted +on +once +one +ones +only +onto +or +ord +other +others +otherwise +ought +our +ours +ourselves +out +outside +over +overall +owing +own +p +page +pages +part +particular +particularly +past +per +perhaps +placed +please +plus +poorly +possible +possibly +potentially +pp +predominantly +present +previously +primarily +probably +promptly +proud +provides +put +q +que +quickly +quite +qv +r +ran +rather +rd +re +readily +really +recent +recently +ref +refs +regarding +regardless +regards +related +relatively +research +respectively +resulted +resulting +results +right +run +s +said +same +saw +say +saying +says +sec +section +see +seeing +seem +seemed +seeming +seems +seen +self +selves +sent +seven +several +shall +she +shed +she'll +shell +shes +should +shouldn't +shouldnt +show +showed +shown +showns +shows +significant +significantly +similar +similarly +since +six +slightly +so +some +somebody +somehow +someone +somethan +something +sometime +sometimes +somewhat +somewhere +soon +sorry +specifically +specified +specify +specifying +state +states +still +stop +strongly +sub +substantially +successfully +such +sufficiently +suggest +sup +sure +t +take +taken +taking +tell +tends +th +than +thank +thanks +thanx +that +that'll +thatll +thats +that've +thatve +the +their +theirs +them +themselves +then +thence +there +thereafter +thereby +thered +therefore +therein +there'll +therell +thereof +therere +theres +thereto +thereupon +there've +thereve +these +they +theyd +they'll +theyll +theyre +they've +theyve +think +this +those +thou +though +thoughh +thousand +throug +through +throughout +thru +thus +til +tip +to +together +too +took +toward +towards +tried +tries +truly +try +trying +ts +twice +two +u +un +under +unfortunately +unless +unlike +unlikely +until +unto +up +upon +ups +us +use +used +useful +usefully +usefulness +uses +using +usually +v +value +various +'ve +'ve +very +via +viz +vol +vols +vs +w +want +wants +was +wasn't +wasnt +way +we +wed +welcome +we'll +well +went +were +weren't +werent +we've +weve +what +whatever +what'll +whatll +whats +when +whence +whenever +where +whereafter +whereas +whereby +wherein +wheres +whereupon +wherever +whether +which +while +whim +whither +who +whod +whoever +whole +who'll +wholl +whom +whomever +whos +whose +why +widely +will +willing +wish +with +within +without +won't +wont +words +would +wouldn't +wouldnt +www +x +y +yes +yet +you +youd +you'll +youll +your +youre +yours +yourself +yourselves +you've +youve +z +zero diff --git a/docs/config/index.js b/docs/config/index.js new file mode 100644 index 00000000..ae905889 --- /dev/null +++ b/docs/config/index.js @@ -0,0 +1,29 @@ +var _ = require('lodash'); +var path = require('canonical-path'); +var packagePath = __dirname; + +var angularjsPackage = require('dgeni-packages/ngdoc'); + +module.exports = function(config) { + + config = angularjsPackage(config); + + config.append('processing.processors', [ + require('./processors/keywords'), + require('./processors/versions-data'), + require('./processors/pages-data'), + require('./processors/index-page') + ]); + + config.append('processing.tagDefinitions', [ + require('./tag-defs/tutorial-step') + ]); + + config.set('processing.search.ignoreWordsFile', path.resolve(packagePath, 'ignore.words')); + + config.prepend('rendering.templateFolders', [ + path.resolve(packagePath, 'templates') + ]); + + return config; +}; diff --git a/docs/config/processors/index-page.js b/docs/config/processors/index-page.js new file mode 100644 index 00000000..3ba1ac73 --- /dev/null +++ b/docs/config/processors/index-page.js @@ -0,0 +1,42 @@ +var _ = require('lodash'); +var log = require('winston'); +var path = require('canonical-path'); +var deployment; + +module.exports = { + name: 'index-page', + runAfter: ['adding-extra-docs'], + runBefore: ['extra-docs-added'], + description: 'This processor creates docs that will be rendered as the index page for the app', + init: function(config) { + deployment = config.deployment; + if ( !deployment || !deployment.environments ) { + throw new Errro('No deployment environments found in the config.'); + } + }, + process: function(docs) { + + // Collect up all the areas in the docs + var areas = {}; + _.forEach(docs, function(doc) { + if ( doc.area ) { + areas[doc.area] = doc.area; + } + }); + areas = _.keys(areas); + + _.forEach(deployment.environments, function(environment) { + + var indexDoc = _.defaults({ + docType: 'indexPage', + areas: areas + }, environment); + + indexDoc.id = 'index' + (environment.name === 'default' ? '' : '-' + environment.name); + // Use .. to put it at the root of the build + indexDoc.outputPath = indexDoc.id + '.html'; + + docs.push(indexDoc); + }); + } +}; \ No newline at end of file diff --git a/docs/config/processors/keywords.js b/docs/config/processors/keywords.js new file mode 100644 index 00000000..6f7e9c21 --- /dev/null +++ b/docs/config/processors/keywords.js @@ -0,0 +1,91 @@ +var _ = require('lodash'); +var log = require('winston'); +var fs = require('fs'); +var path = require('canonical-path'); + +// Keywords to ignore +var wordsToIgnore = []; +var propertiesToIgnore; +var areasToSearch; + +// Keywords start with "ng:" or one of $, _ or a letter +var KEYWORD_REGEX = /^((ng:|[\$_a-z])[\w\-_]+)/; + +module.exports = { + name: 'keywords', + runAfter: ['docs-processed'], + runBefore: ['adding-extra-docs'], + description: 'This processor extracts all the keywords from the document', + init: function(config) { + + // Load up the keywords to ignore, if specified in the config + if ( config.processing.search && config.processing.search.ignoreWordsFile ) { + + var ignoreWordsPath = path.resolve(config.basePath, config.processing.search.ignoreWordsFile); + wordsToIgnore = fs.readFileSync(ignoreWordsPath, 'utf8').toString().split(/[,\s\n\r]+/gm); + + log.debug('Loaded ignore words from "' + ignoreWordsPath + '"'); + log.silly(wordsToIgnore); + + } + + areasToSearch = _.indexBy(config.get('processing.search.areasToSearch', ['api', 'guide', 'misc', 'error', 'tutorial'])); + + propertiesToIgnore = _.indexBy(config.get('processing.search.propertiesToIgnore', [])); + log.debug('Properties to ignore', propertiesToIgnore); + + }, + process: function(docs) { + + var ignoreWordsMap = _.indexBy(wordsToIgnore); + + // If the title contains a name starting with ng, e.g. "ngController", then add the module name + // without the ng to the title text, e.g. "controller". + function extractTitleWords(title) { + var match = /ng([A-Z]\w*)/.exec(title); + if ( match ) { + title = title + ' ' + match[1].toLowerCase(); + } + return title; + } + + function extractWords(text, words, keywordMap) { + + var tokens = text.toLowerCase().split(/[\.\s,`'"#]+/mg); + _.forEach(tokens, function(token){ + var match = token.match(KEYWORD_REGEX); + if (match){ + key = match[1]; + if ( !keywordMap[key]) { + keywordMap[key] = true; + words.push(key); + } + } + }); + } + + + // We are only interested in docs that live in the right area + docs = _.filter(docs, function(doc) { return areasToSearch[doc.area]; }); + + _.forEach(docs, function(doc) { + + var words = []; + var keywordMap = _.clone(ignoreWordsMap); + + // Search each top level property of the document for search terms + _.forEach(doc, function(value, key) { + if ( _.isString(value) && !propertiesToIgnore[key] ) { + extractWords(value, words, keywordMap); + } + }); + + doc.searchTerms = { + titleWords: extractTitleWords(doc.name), + keywords: _.sortBy(words).join(' ') + }; + + }); + + } +}; \ No newline at end of file diff --git a/docs/config/processors/pages-data.js b/docs/config/processors/pages-data.js new file mode 100644 index 00000000..47896db5 --- /dev/null +++ b/docs/config/processors/pages-data.js @@ -0,0 +1,200 @@ +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(navGroupPages, groupName, pageSorter, pageMapper) { + + var navItems = _(navGroupPages) + .sortBy(pageSorter) + .map(pageMapper) + .value(); + + return { + name: groupName, + type: 'group', + navItems: navItems + }; +} + + +var navGroupMappers = { + api: function(areaPages, areaName) { + var navGroups = _(areaPages) + .filter('module') // We are not interested in docs that are not in a module + + .groupBy('module') + + .map(function(modulePages, moduleName) { + console.log('moduleName', moduleName); + var navItems = []; + var modulePage; + + _(modulePages) + + .groupBy('docType') + + .tap(function(docTypes) { + console.log(_.keys(docTypes)); + // Extract the module page from the collection + modulePage = docTypes.module[0]; + delete docTypes.module; + }) + + .forEach(function(sectionPages, sectionName) { + + 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: modulePage.path, + type: 'group', + navItems: navItems + }; + }) + .value(); + return navGroups; + }, + tutorial: function(pages, areaName) { + return [getNavGroup(pages, areaName, 'step', function(page) { + return { + name: page.name, + step: page.step, + href: page.path, + type: 'tutorial' + }; + })]; + }, + error: function(pages, areaName) { + return [getNavGroup(pages, areaName, 'path', function(page) { + return { + name: page.name, + href: page.path, + type: 'error' + }; + })]; + }, + pages: function(pages, areaName) { + return [getNavGroup(pages, areaName, 'path', function(page) { + return { + name: page.name, + href: page.path, + type: 'page' + }; + })]; + } +}; + +var outputFolder; + +module.exports = { + name: 'pages-data', + description: 'This plugin will create a new doc that will be rendered as an angularjs module ' + + 'which will contain meta information about the pages and navigation', + runAfter: ['adding-extra-docs', 'component-groups-generate'], + runBefore: ['extra-docs-added'], + init: function(config) { + outputFolder = config.rendering.outputFolder; + }, + 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) { + console.log(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 != 'landingPage'; + }); + + // 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 + // + var areas = {}; + _(navPages) + .groupBy('area') + .forEach(function(pages, areaName) { + var navGroupMapper = navGroupMappers[areaName] || navGroupMappers['pages']; + var areaTitle = AREA_NAMES[areaName]; + + areas[areaName] = { + id: areaName, + name: areaTitle, + navGroups: navGroupMapper(pages, areaTitle) + }; + }); + + _.forEach(docs, function(doc) { + if ( !doc.path ) { + log.warn('Missing path property for ', doc.id); + } + }); + + // 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: 'pages-data.template.js', + outputPath: 'js/pages-data.js', + + areas: areas, + pages: pages + }; + docs.push(docData); + } +}; diff --git a/docs/config/processors/versions-data.js b/docs/config/processors/versions-data.js new file mode 100644 index 00000000..eb158e79 --- /dev/null +++ b/docs/config/processors/versions-data.js @@ -0,0 +1,42 @@ +var _ = require('lodash'); + +var version; +var versions; + +module.exports = { + name: 'versions-data', + description: 'This plugin will create a new doc that will be rendered as an angularjs module ' + + 'which will contain meta information about the versions of angular', + runAfter: ['adding-extra-docs', 'pages-data'], + runBefore: ['extra-docs-added'], + init: function(config) { + version = config.source.currentVersion; + versions = config.source.previousVersions; + + if ( !version ) { + throw new Error('Invalid configuration. Please provide a valid `source.currentVersion` property'); + } + if ( !versions ) { + throw new Error('Invalid configuration. Please provide a valid `source.previousVersions` property'); + } + }, + process: function(docs) { + + var versionDoc = { + docType: 'versions-data', + id: 'versions-data', + template: 'versions-data.template.js', + outputPath: 'js/versions-data.js', + }; + + versionDoc.currentVersion = version; + + versionDoc.versions = _(versions) + .filter(function(version) { return version.major > 0; }) + .push(version) + .reverse() + .value(); + + docs.push(versionDoc); + } +}; \ No newline at end of file diff --git a/docs/config/tag-defs/tutorial-step.js b/docs/config/tag-defs/tutorial-step.js new file mode 100644 index 00000000..4ebe9d6a --- /dev/null +++ b/docs/config/tag-defs/tutorial-step.js @@ -0,0 +1,9 @@ +module.exports = { + name: 'step', + transformFn: function(doc, tag) { + if ( doc.docType !== 'tutorial' ) { + throw new Error('Invalid tag, step. You should only use this tag on tutorial docs'); + } + return parseInt(tag.description,10); + } +}; diff --git a/docs/config/templates/indexPage.template.html b/docs/config/templates/indexPage.template.html new file mode 100644 index 00000000..6366d020 --- /dev/null +++ b/docs/config/templates/indexPage.template.html @@ -0,0 +1,217 @@ + + +
+ + + + +