api-builder: add cheatsheet-package to generate cheatsheet data
Closes #348
This commit is contained in:
@@ -2,12 +2,15 @@ var path = require('canonical-path');
|
||||
var Package = require('dgeni').Package;
|
||||
var basePackage = require('../docs-package');
|
||||
var targetPackage = require('../target-package');
|
||||
var cheatsheetPackage = require('../cheatsheet-package');
|
||||
|
||||
var PROJECT_PATH = path.resolve(__dirname, "../../..");
|
||||
var PUBLIC_PATH = path.resolve(PROJECT_PATH, 'public');
|
||||
var DOCS_PATH = path.resolve(PUBLIC_PATH, 'docs');
|
||||
var ANGULAR2_DOCS_PATH = path.resolve(__dirname, '../../../../angular/modules/angular2/docs');
|
||||
|
||||
module.exports = new Package('angular.io', [basePackage, targetPackage])
|
||||
|
||||
module.exports = new Package('angular.io', [basePackage, targetPackage, cheatsheetPackage])
|
||||
|
||||
.factory(require('./services/renderMarkdown'))
|
||||
.processor(require('./processors/addJadeDataDocsProcessor'))
|
||||
@@ -41,6 +44,11 @@ module.exports = new Package('angular.io', [basePackage, targetPackage])
|
||||
readTypeScriptModules.hidePrivateMembers = true;
|
||||
|
||||
readFilesProcessor.basePath = DOCS_PATH;
|
||||
readFilesProcessor.sourceFiles = [{
|
||||
basePath: ANGULAR2_DOCS_PATH,
|
||||
include: path.resolve(ANGULAR2_DOCS_PATH, 'cheatsheet/*.md')
|
||||
}];
|
||||
|
||||
writeFilesProcessor.outputFolder = 'js/latest/api';
|
||||
})
|
||||
|
||||
@@ -51,7 +59,6 @@ module.exports = new Package('angular.io', [basePackage, targetPackage])
|
||||
|
||||
.config(function(readFilesProcessor, generateNavigationDoc, createOverviewDump) {
|
||||
// Clear out unwanted processors
|
||||
readFilesProcessor.$enabled = false;
|
||||
generateNavigationDoc.$enabled = false;
|
||||
createOverviewDump.$enabled = false;
|
||||
})
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
{$ doc.sections | json $}
|
||||
@@ -0,0 +1,10 @@
|
||||
var Package = require('dgeni').Package;
|
||||
|
||||
module.exports = new Package('cheatsheet', [require('../content-package')])
|
||||
|
||||
.factory(require('./services/cheatsheetItemParser'))
|
||||
.processor(require('./processors/createCheatsheetDoc'))
|
||||
|
||||
.config(function(parseTagsProcessor, getInjectables) {
|
||||
parseTagsProcessor.tagDefinitions = parseTagsProcessor.tagDefinitions.concat(getInjectables(require('./tag-defs')));
|
||||
});
|
||||
@@ -0,0 +1,9 @@
|
||||
var Package = require('dgeni').Package;
|
||||
|
||||
module.exports = function mockPackage() {
|
||||
|
||||
return new Package('mockPackage', [require('../'), require('dgeni-packages/nunjucks')])
|
||||
|
||||
// provide a mock log service
|
||||
.factory('log', function() { return require('dgeni/lib/mocks/log')(false); });
|
||||
};
|
||||
@@ -0,0 +1,41 @@
|
||||
var _ = require('lodash');
|
||||
|
||||
module.exports = function createCheatsheetDoc(createDocMessage, renderMarkdown) {
|
||||
return {
|
||||
$runAfter: ['processing-docs'],
|
||||
$runBefore: ['docs-processed'],
|
||||
$process: function(docs) {
|
||||
|
||||
var cheatsheetDoc = {
|
||||
id: 'cheatsheet',
|
||||
aliases: ['cheatsheet'],
|
||||
docType: 'json-data',
|
||||
sections: []
|
||||
};
|
||||
|
||||
docs = docs.filter(function(doc) {
|
||||
if (doc.docType === 'cheatsheet-section') {
|
||||
var section = _.pick(doc, ['name', 'description', 'items', 'index']);
|
||||
|
||||
// Let's make sure that the descriptions are rendered as markdown
|
||||
section.description = renderMarkdown(section.description);
|
||||
section.items.forEach(function(item) {
|
||||
item.description = renderMarkdown(item.description);
|
||||
});
|
||||
|
||||
|
||||
cheatsheetDoc.sections.push(section);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
// Sort the sections by their index
|
||||
cheatsheetDoc.sections.sort(function(a,b) { return a.index - b.index; });
|
||||
|
||||
docs.push(cheatsheetDoc);
|
||||
|
||||
return docs;
|
||||
}
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,85 @@
|
||||
/**
|
||||
* @dgService
|
||||
* @description
|
||||
* Parse the text from a cheatsheetItem tag into a cheatsheet item object
|
||||
* The text must contain a syntax block followed by zero or more bold matchers and finally a description
|
||||
* The syntax block and bold matchers must be wrapped in backticks and be separated by pipes.
|
||||
* For example
|
||||
*
|
||||
* ```
|
||||
* `<div [ng-switch]="conditionExpression">
|
||||
* <template [ng-switch-when]="case1Exp">...</template>
|
||||
* <template ng-switch-when="case2LiteralString">...</template>
|
||||
* <template ng-switch-default>...</template>
|
||||
* </div>`|`[ng-switch]`|`[ng-switch-when]`|`ng-switch-when`|`ng-switch-default`
|
||||
* Conditionally swaps the contents of the div by selecting one of the embedded templates based on the current value of conditionExpression.
|
||||
* ```
|
||||
*
|
||||
* will be parsed into
|
||||
*
|
||||
* ```
|
||||
* {
|
||||
* syntax: '<div [ng-switch]="conditionExpression">\n'+
|
||||
* ' <template [ng-switch-when]="case1Exp">...</template>\n'+
|
||||
* ' <template ng-switch-when="case2LiteralString">...</template>\n'+
|
||||
* ' <template ng-switch-default>...</template>\n'+
|
||||
* '</div>',
|
||||
* bold: ['[ng-switch]', '[ng-switch-when]', 'ng-switch-when', 'ng-switch-default'],
|
||||
* description: 'Conditionally swaps the contents of the div by selecting one of the embedded templates based on the current value of conditionExpression.'
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
module.exports = function cheatsheetItemParser() {
|
||||
|
||||
return function(text) {
|
||||
var index = 0;
|
||||
var item = {
|
||||
syntax: '',
|
||||
bold: [],
|
||||
description: ''
|
||||
};
|
||||
|
||||
var STATES = {
|
||||
inSyntax: function() {
|
||||
if (text.charAt(index) !== '`') throw new Error('item syntax must start with a backtick');
|
||||
index += 1;
|
||||
var syntaxStart = index;
|
||||
while(index < text.length && text.charAt(index) !== '`') index++;
|
||||
if (index === text.length) throw new Error('item syntax must end with a backtick');
|
||||
item.syntax = text.substring(syntaxStart, index);
|
||||
state = STATES.pipe;
|
||||
index++;
|
||||
},
|
||||
pipe: function() {
|
||||
if (text.charAt(index) === '|') {
|
||||
index++;
|
||||
while(index < text.length && /\s/.test(text.charAt(index))) index++;
|
||||
state = STATES.bold;
|
||||
} else {
|
||||
state = STATES.description;
|
||||
}
|
||||
},
|
||||
bold: function() {
|
||||
if (text.charAt(index) !== '`') throw new Error('bold matcher must start with a backtick');
|
||||
index += 1;
|
||||
var boldStart = index;
|
||||
while(index < text.length && text.charAt(index) !== '`') index++;
|
||||
if (index === text.length) throw new Error('bold matcher must end with a backtick');
|
||||
item.bold.push(text.substring(boldStart, index));
|
||||
state = STATES.pipe;
|
||||
index++;
|
||||
},
|
||||
description: function() {
|
||||
item.description = text.substring(index);
|
||||
state = null;
|
||||
}
|
||||
};
|
||||
|
||||
var state = STATES.inSyntax;
|
||||
while(state) {
|
||||
state();
|
||||
}
|
||||
|
||||
return item;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
var mockPackage = require('../mocks/mockPackage');
|
||||
var Dgeni = require('dgeni');
|
||||
|
||||
describe('cheatsheetItemParser', function() {
|
||||
var dgeni, injector, cheatsheetItemParser;
|
||||
|
||||
beforeEach(function() {
|
||||
dgeni = new Dgeni([mockPackage()]);
|
||||
injector = dgeni.configureInjector();
|
||||
cheatsheetItemParser = injector.get('cheatsheetItemParser');
|
||||
});
|
||||
|
||||
it('should extract the syntax', function() {
|
||||
expect(cheatsheetItemParser('`abc`')).toEqual({
|
||||
syntax: 'abc',
|
||||
bold: [],
|
||||
description: ''
|
||||
});
|
||||
});
|
||||
|
||||
it('should extract the bolds', function() {
|
||||
expect(cheatsheetItemParser('`abc`|`bold1`|`bold2`')).toEqual({
|
||||
syntax: 'abc',
|
||||
bold: ['bold1', 'bold2'],
|
||||
description: ''
|
||||
});
|
||||
});
|
||||
|
||||
it('should extract the description', function() {
|
||||
expect(cheatsheetItemParser('`abc`|`bold1`|`bold2`some description')).toEqual({
|
||||
syntax: 'abc',
|
||||
bold: ['bold1', 'bold2'],
|
||||
description: 'some description'
|
||||
});
|
||||
});
|
||||
|
||||
it('should allow bold to be optional', function() {
|
||||
expect(cheatsheetItemParser('`abc`some description')).toEqual({
|
||||
syntax: 'abc',
|
||||
bold: [],
|
||||
description: 'some description'
|
||||
});
|
||||
});
|
||||
|
||||
it('should allow whitespace between the parts', function() {
|
||||
expect(cheatsheetItemParser('`abc`| `bold1`| `bold2`\n\nsome description')).toEqual({
|
||||
syntax: 'abc',
|
||||
bold: ['bold1', 'bold2'],
|
||||
description: '\n\nsome description'
|
||||
});
|
||||
})
|
||||
});
|
||||
@@ -0,0 +1,13 @@
|
||||
module.exports = function(createDocMessage) {
|
||||
return {
|
||||
name: 'cheatsheetIndex',
|
||||
docProperty: 'index',
|
||||
transforms: function(doc, tag, value) {
|
||||
try {
|
||||
return parseInt(value, 10);
|
||||
} catch(x) {
|
||||
throw new Error(createDocMessage('"@'+ tag.tagName +'" must be followed by a number', doc));
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,14 @@
|
||||
module.exports = function(createDocMessage, cheatsheetItemParser) {
|
||||
return {
|
||||
name: 'cheatsheetItem',
|
||||
multi: true,
|
||||
docProperty: 'items',
|
||||
transforms: function(doc, tag, value) {
|
||||
try {
|
||||
return cheatsheetItemParser(value);
|
||||
} catch(x) {
|
||||
throw new Error(createDocMessage('"@'+ tag.tagName +'" tag has an invalid format - ' + x.message, doc));
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,10 @@
|
||||
module.exports = function() {
|
||||
return {
|
||||
name: 'cheatsheetSection',
|
||||
docProperty: 'docType',
|
||||
transforms: function(doc, tag, value) {
|
||||
doc.name = value ? value.trim() : '';
|
||||
return 'cheatsheet-section';
|
||||
}
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,5 @@
|
||||
module.exports = [
|
||||
require('./cheatsheet-section'),
|
||||
require('./cheatsheet-index'),
|
||||
require('./cheatsheet-item')
|
||||
];
|
||||
Reference in New Issue
Block a user