chore(): begin adding ionic components to mono-repo.

This commit is contained in:
Josh Thomas
2017-06-21 09:33:06 -05:00
parent 1181fe98fc
commit bd5b67304d
2159 changed files with 15687 additions and 147 deletions

View File

@ -0,0 +1,82 @@
#!/bin/bash
ARG_DEFS=(
"--version-name=(.*)"
)
echo "##### "
echo "##### docs/deploy.sh"
echo "#####"
function init {
cd ..
SITE_PATH=$(readJsonProp "config.json" "sitePath")
SITE_DIR=$IONIC_DIR/$SITE_PATH
DOCS_DEST=$(readJsonProp "config.json" "docsDest")
}
function run {
cd ..
VERSION=$(readJsonProp "package.json" "version")
# download and copy over API Demos
./node_modules/.bin/gulp demos.download
./node_modules/.bin/gulp docs.demos --production=true
# if release, copy old version to seperate folder and blow out docs root api
if $IS_RELEASE; then
echo "BUILDING RELEASE DOCS"
if [ -d "$DOCS_DEST/api" ]; then
rm -R $DOCS_DEST/api
fi
if [ -d "$DOCS_DEST/nightly/api" ]; then
rm -R $DOCS_DEST/nightly/api
fi
./node_modules/.bin/gulp docs.dgeni --doc-version="$VERSION_NAME" --initial-build true
./node_modules/.bin/gulp docs.dgeni --doc-version="$VERSION_NAME"
./node_modules/.bin/gulp docs.dgeni --doc-version="nightly"
./node_modules/.bin/gulp docs.homepageVersionUpdate
else
if [ -d "$DOCS_DEST/nightly/api" ]; then
rm -R $DOCS_DEST/nightly/api
fi
./node_modules/.bin/gulp docs.dgeni --doc-version="$VERSION_NAME"
fi
# compile sass vars json for ionic-site docs
./node_modules/.bin/gulp docs.sassVariables
cp tmp/sass.json $DOCS_DEST/theming/overriding-ionic-variables/
# CD in to the site dir to commit updated docs
cd $SITE_DIR
CHANGES=$(git status --porcelain)
# if no changes, don't commit
if [[ "$CHANGES" == "" ]]; then
echo "-- No changes detected for the following commit, docs not updated."
echo "https://github.com/ionic-team/$CIRCLE_PROJECT_REPONAME/commit/$CIRCLE_SHA1"
else
git add -A
git commit -am "Automated build of ionic v$VERSION ionic-team/$CIRCLE_PROJECT_REPONAME@$CIRCLE_SHA1"
# in case a different commit was pushed to ionic-site during doc/demo gen,
# try to rebase around it before pushing
git fetch
git rebase
git push origin master
echo "-- Updated docs for $VERSION_NAME succesfully!"
fi
}
source $(dirname $0)/../utils.sh.inc

View File

@ -0,0 +1,192 @@
var Package = require('dgeni').Package;
var jsdocPackage = require('dgeni-packages/jsdoc');
var nunjucksPackage = require('dgeni-packages/nunjucks');
var typescriptPackage = require('dgeni-packages/typescript');
var linksPackage = require('dgeni-packages/links');
var gitPackage = require('dgeni-packages/git');
var path = require('path');
var semver = require('semver');
var fs = require('fs');
var _ = require('lodash');
var config = require('../config.json');
// Define the dgeni package for generating the docs
module.exports = function(currentVersion, initialVersionBuild) {
return new Package('ionic-v2-docs',
[jsdocPackage, nunjucksPackage, typescriptPackage,
linksPackage, gitPackage])
.processor(require('./processors/latest-version'))
.processor(require('./processors/index-page'))
.processor(require('./processors/remove-private-members'))
.processor(require('./processors/jekyll'))
.processor(require('./processors/hide-private-api'))
.processor(require('./processors/collect-inputs-outputs'))
.processor(require('./processors/parse-returns-object'))
.processor(require('./processors/parse-optional'))
.processor(require('./processors/parse-sass'))
// for debugging docs
// .processor(function test(){
// return {
//
// $runBefore: ['rendering-docs'],
// $process: function(docs){
// docs.forEach(function(doc){
// if (doc.name == "Searchbar"){
// console.log(doc.input);
// doc.members.forEach(function(method){
// if (method.name === "load") {
// console.log(method);
// }
// })
// }
// })
// }
// }
// })
.config(function(log) {
log.level = 'error'; //'silly', 'debug', 'info', 'warn', 'error'
})
.config(function(renderDocsProcessor, computePathsProcessor, versionInfo) {
try {
versions = fs.readdirSync(path.resolve(__dirname, '../../' + config.docsDest + '/'))
.filter(semver.valid)
} catch(e) {
versions = [];
}
// new version, add it to the versions list
if (currentVersion != 'nightly' && !_.includes(versions, currentVersion)){
versions.unshift(currentVersion);
}
// sort by version so we can find latest
versions.sort(semver.rcompare);
// add nightly if it isn't in the list
!_.includes(versions, 'nightly') && versions.unshift('nightly');
//First semver valid version is latest
var latestVersion = _.find(versions, semver.valid);
versions = versions.map(function(version) {
// Set nightly as docs root
//var folder = version == 'nightly' ? '' : version;
//Instead set latest version in docs root if not initial build
var folder = (version == latestVersion) && !initialVersionBuild ? '' : version;
return {
href: path.join('/' + config.v2DocsDir, folder).replace('/content',''),
folder: folder,
name: version
};
});
var versionData = {
list: versions,
current: _.find(versions, { name: currentVersion }),
latest: _.find(versions, {name: latestVersion}) || _.first(versions),
initialVersionBuild: initialVersionBuild
};
renderDocsProcessor.extraData.version = versionData;
renderDocsProcessor.extraData.versionInfo = versionInfo;
computePathsProcessor.pathTemplates = [{
docTypes: ['class', 'var', 'function', 'let'],
getOutputPath: function(doc) {
// strip ionic from path root
var docPath = doc.fileInfo.relativePath.replace(/^src\//, '');
// remove filename since we have multiple docTypes per file
docPath = docPath.substring(0, docPath.lastIndexOf('/') + 1);
docPath += doc.name + '/index.md';
var path = config.v2DocsDir + '/' + (versionData.current.folder || '') +
'/api/' + docPath;
path = path.replace('/home/ubuntu/ionic/src', '')
.replace(__dirname.replace('ionic/scripts/docs', ''),'')
.replace('/ionic/src','');
return path;
}
}];
})
//configure file reading
.config(function(readFilesProcessor, readTypeScriptModules) {
// Don't run unwanted processors since we are not using the normal file reading processor
readFilesProcessor.$enabled = false;
readFilesProcessor.basePath = path.resolve(__dirname, '../..');
readTypeScriptModules.basePath = path.resolve(path.resolve(__dirname, '../..'));
readTypeScriptModules.sourceFiles = [
'src/index.ts'
];
})
.config(function(parseTagsProcessor) {
parseTagsProcessor.tagDefinitions = parseTagsProcessor.tagDefinitions.concat(require('./tag-defs/tag-defs'));
})
// .config(function(parseTagsProcessor) {
// // We actually don't want to parse param docs in this package as we are getting the data out using TS
// parseTagsProcessor.tagDefinitions.forEach(function(tagDef) {
// console.log(tagDef);
// if (tagDef.name === 'param') {
// tagDef.docProperty = 'paramData';
// tagDef.transforms = [];
// }
// });
// })
// Configure allowedDocTypes
.config(function(extractAccessTransform) {
var allowedDocTypes = ['member'];
allowedDocTypes.forEach(function(docType) {
extractAccessTransform.allowedDocTypes.add(docType);
});
})
// Configure links
.config(function(getLinkInfo) {
getLinkInfo.useFirstAmbiguousLink = false;
})
// Configure file writing
.config(function(writeFilesProcessor) {
writeFilesProcessor.outputFolder = config.sitePath;
})
// Configure rendering
.config(function(templateFinder, templateEngine) {
// Nunjucks and Angular conflict in their template bindings so change the Nunjucks
// Also conflict with Jekyll
templateEngine.config.tags = {
variableStart: '<$',
variableEnd: '$>',
blockStart: '<@',
blockEnd: '@>',
commentStart: '<#',
commentEnd: '#>'
};
// add custom filters to nunjucks
templateEngine.filters.push(
require('./filters/capital'),
require('./filters/code'),
require('./filters/dump'),
require('./filters/platform')
);
templateFinder.templateFolders.unshift(path.resolve(__dirname, 'templates'));
// Specify how to match docs to templates.
templateFinder.templatePatterns = [
'${ doc.template }',
'${ doc.docType }.template.html',
'common.template.html'
]
})
}

View File

@ -0,0 +1,7 @@
module.exports = {
name: 'capital',
process: function(str) {
str || (str = '');
return str.charAt(0).toUpperCase() + str.substring(1);
}
};

View File

@ -0,0 +1,25 @@
var encoder = new require('node-html-encoder').Encoder();
function code(str, inline, lang) {
// Encode any HTML entities in the code string
str = encoder.htmlEncode(str, true);
// If a language is provided then attach a CSS class to the code element
lang = lang ? ' class="lang-' + lang + '"' : '';
str = '<code' + lang + '>' + str + '</code>';
// If not inline then wrap the code element in a pre element
if ( !inline ) {
str = '<pre>' + str + '</pre>';
}
return str;
};
module.exports = {
name: 'code',
process: function(str, lang) {
return code(str, true, lang);
}
};

View File

@ -0,0 +1,6 @@
module.exports = {
name: 'dump',
process: function(obj) {
console.log(obj);
}
};

View File

@ -0,0 +1,15 @@
module.exports = {
name: 'platform',
process: function (str) {
switch (str) {
case 'ios':
return 'iOS'
case 'md':
return 'Material Design'
case 'wp':
return 'Windows Platform'
default:
return 'All'
}
}
};

View File

@ -0,0 +1,96 @@
var config = require('../config.json');
module.exports = function(gulp, flags) {
gulp.task('docs', [], function() {
var Dgeni = require('dgeni');
var semver = require('semver');
var docVersion = flags['doc-version'] || 'nightly';
var initialVersionBuild = flags['initial-build'] || false;
if (docVersion != 'nightly' && !semver.valid(docVersion)) {
console.log('Usage: gulp docs --doc-version=(nightly|versionName)\nversionName must be a valid semver version.');
return process.exit(1);
}
try {
var ionicPackage = require('./dgeni-config')(docVersion, initialVersionBuild);
var dgeni = new Dgeni([ionicPackage]);
return dgeni.generate();
} catch (err) {
console.log(err.stack);
}
});
gulp.task('docs.demos', ['demos', 'src', 'temp.hack'], function(){
return gulp.src([
'dist/**',
'!dist/e2e',
'!dist/e2e/**/*',
'!dist/ionic-site',
'!dist/ionic-site/**/*',
'!dist/src',
'!dist/src/**/*'
])
.pipe(gulp.dest(config.docsDest + '/dist'));
});
gulp.task('docs.sass-variables', function() {
var fs = require('fs');
var gutil = require('gulp-util');
var es = require('event-stream');
var mkdirp = require('mkdirp');
var path = require('path');
var Entities = require('html-entities').AllHtmlEntities;
entities = new Entities();
var variables = [];
var outputFile = 'tmp/sass.json';
// Add the variable to the array, encode the html and remove !default from the value
function addVariable(variableName, defaultValue, file) {
defaultValue = entities.encode(defaultValue);
defaultValue = defaultValue.replace("!default;", "");
variables.push({
"name": variableName,
"defaultValue": defaultValue.trim(),
"file": path.relative('./', file.path)
});
}
return gulp.src('src/**/*.scss')
.pipe(es.map(function(file, callback) {
var contents = file.contents.toString();
var variableLine, variableName, defaultValue, multiline;
fs.createReadStream(file.path, {flags: 'r'})
.pipe(es.split())
.pipe(es.map(function (line, callback) {
if (line.charAt(0) == '$') {
variableLine = line.split(/:(.+)/);
variableName = variableLine[0];
defaultValue = variableLine[1];
// If there is a semicolon then it isn't a multiline value
multiline = line.indexOf(';') > -1 ? false : true;
if (!multiline && line.indexOf('!default') > -1)
addVariable(variableName, defaultValue, file);
} else if (multiline == true) {
defaultValue += '\n' + line;
// If the line has a semicolon then we've found the end of the value
if (line.indexOf(';') > -1 && line.indexOf('!default') > -1) {
addVariable(variableName, defaultValue, file);
multiline = false;
}
}
callback();
}));
callback();
}).on('end', function() {
gutil.log("Writing to file at", gutil.colors.cyan("/ionic-team/ionic/" + outputFile));
gutil.log("Place this file in", gutil.colors.cyan("/ionic-team/ionic-site/" + config.v2DocsDir + "/theming/overriding-ionic-variables/"), "in order to update the docs");
mkdirp.sync('tmp');
fs.writeFileSync(outputFile, JSON.stringify(variables));
}));
});
}

View File

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

View File

@ -0,0 +1,33 @@
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',
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,72 @@
var _ = require('lodash');
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
*/
module.exports = function getLinkInfo(getDocFromAlias, encodeCodeBlock, log) {
return 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);
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,32 @@
#!/bin/bash
echo "##### "
echo "##### prepare.sh"
echo "#####"
function init {
cd ..
SITE_PATH=$(readJsonProp "config.json" "sitePath")
cd ..
export IONIC_DIR=$PWD
SITE_DIR=$IONIC_DIR/$SITE_PATH
}
function run {
if [ ! -d "$SITE_DIR" ]; then
echo "checking out"
cd ./scripts
./git/clone.sh --repository="ionic-site" \
--directory="$SITE_DIR" \
--branch="master"
else
echo "using existing"
cd $SITE_DIR
git reset --hard
git pull origin master
fi
}
source $(dirname $0)/../utils.sh.inc

View File

@ -0,0 +1,75 @@
module.exports = function collectInputsOutputs() {
return {
$runBefore: ['rendering-docs'],
$process: function(docs) {
docs.forEach(function(doc) {
if (doc.members && doc.members.length) {
var members = [];
var inputs = [];
var outputs = [];
memberLoop:
for (var i in doc.members) {
// identify properties to differentiate from methods
if (typeof doc.members[i].parameters == 'undefined') {
doc.members[i].isProperty = true;
}
if (doc.members[i].decorators && doc.members[i].decorators.length) {
decoratorLoop:
for (var ii in doc.members[i].decorators) {
if (doc.members[i].decorators[ii].name == 'Input') {
inputs.push(parseMember(doc.members[i]));
continue memberLoop;
}
if (doc.members[i].decorators[ii].name == 'Output') {
outputs.push(parseMember(doc.members[i]));
continue memberLoop;
}
}
// not an input or output, must be a plain member
members.push(doc.members[i]);
} else {
members.push(doc.members[i]);
};
}
// update doc with pruned members list and add inputs and outputs
doc.members = members.sort(alphabetize);
doc.inputs = inputs.sort(alphabetize);
doc.outputs = outputs.sort(alphabetize);
}
function alphabetize(a, b) {
if (!a.name) {
return 1;
} else if (!b.name) {
return -1;
} else if (a.name < b.name) {
return -1;
} else if (a.name > b.name) {
return 1;
}
return 0;
}
function parseMember(member) {
member.type = member.content.substring(
member.content.indexOf('{') + 1,
member.content.indexOf('}')
);
member.description = member.content.substring(
member.content.indexOf('}') + 1,
member.content.length
);
return member;
}
});
}
};
};

View File

@ -0,0 +1,19 @@
module.exports = function removePrivateApi() {
return {
name: 'remove-private-api',
description: 'Prevent the private apis from being rendered',
$runAfter: ['paths-computed'],
$runBefore: ['rendering-docs'],
$process: function(docs) {
var publicDocs = [];
docs.forEach(function(doc){
if (!doc.private && (!doc.tags || !doc.tags.tagsByName.get('hidden'))){
publicDocs.push(doc);
return doc
}
})
docs = publicDocs;
return docs;
}
}
};

View File

@ -0,0 +1,26 @@
module.exports = function indexPage(renderDocsProcessor) {
return {
name: 'index-page',
description: 'Create documentation index page',
$runAfter: ['adding-extra-docs'],
$runBefore: ['extra-docs-added'],
$process: function(docs) {
//TODO(tlancina): move versionData into its own service
var versionData = renderDocsProcessor.extraData.version;
var currentVersion = versionData.current.name;
var latestVersion = versionData.latest.name;
// var versionPath = currentVersion == 'nightly' ? '' : currentVersion;
// If latest and not initial build, set path to docs root
var versionPath = (currentVersion == latestVersion) && !versionData.initialVersionBuild ? '' : currentVersion;
docs.push({
docType: 'index-page',
id: 'index-page',
currentVersion: currentVersion,
template: 'api_index.template.html',
outputPath: 'content/docs/' + versionPath + '/api/index.md'
});
}
}
};

View File

@ -0,0 +1,58 @@
module.exports = function jekyll(renderDocsProcessor) {
return {
name: 'jekyll',
description: 'Create jekyll includes',
$runAfter: ['paths-computed'],
$runBefore: ['rendering-docs'],
$process: function(docs) {
var currentVersion = renderDocsProcessor.extraData.version.current.name;
// pretty up and sort the docs object for menu generation
docs = docs.filter(function(doc) {
return (!!doc.name && !!doc.outputPath) || doc.docType === 'index-page';
});
docs.sort(function(a, b) {
textA = a.name ? a.name.toUpperCase() : '';
textB = b.name ? b.name.toUpperCase() : '';
return (textA < textB) ? -1 : (textA > textB) ? 1 : 0;
});
docs.forEach(function(doc, i) {
docs[i].URL = doc.outputPath.replace('docs//', 'docs/')
.replace('/index.md', '')
.replace('//home/ubuntu/ionic/src', '')
.replace('//', '/')
.replace('content/', '');
if (docs[i].relativePath) {
docs[i].relativePath = doc.relativePath
.replace('/home/ubuntu/ionic', '');
}
if (docs[i].href) {
docs[i].href = doc.href.replace('content/', '');
}
});
docs.push({
docType: 'api-menu',
id: 'api-menu',
template: 'api_menu.template.html',
outputPath: 'content/_includes/fluid/api_menu.html'
});
docs.push({
docType: 'api-menu-flat-version',
id: 'api-menu-flat-version',
template: 'api_menu_flat_version.template.html',
outputPath: 'content/_includes/fluid/api_menu_flat_' + currentVersion +
'.html'
});
docs.push({
docType: 'api-version-select',
id: 'api-version-select',
template: 'api_version_select.template.html',
outputPath: 'content/_includes/fluid/api_version_select.html'
});
// returning docs will replace docs object in the next process
return docs;
}
};
};

View File

@ -0,0 +1,33 @@
var copy = require('cpr').cpr;
var mkdirp = require('mkdirp');
var path = require('canonical-path');
var q = require('q');
var fs = require('fs');
module.exports = function latestVersion(renderDocsProcessor) {
return {
name: 'latest-version',
$runAfter: ['files-written'],
description: 'Copy the latest version (that was compiled to docs/) into docs/versionName',
$process: function(docs) {
var versionData = renderDocsProcessor.extraData.version;
var docsBase = 'dist/ionic-site/content/docs/';
var versionDir = path.resolve(docsBase, versionData.latest.name);
var latestDir = path.resolve(docsBase, 'api');
var deferred = q.defer();
mkdirp(versionDir, function() {
copy(latestDir, path.join(versionDir, 'api'), {
deleteFirst: true,
overwrite: true
}, function(err, files) {
deferred.resolve(docs);
});
});
return deferred.promise;
}
}
};

View File

@ -0,0 +1,21 @@
module.exports = function parseOptional() {
return {
$runBefore: ['rendering-docs'],
$process: function(docs) {
docs.forEach(function(doc) {
if(doc.members && doc.members.length) {
for (var i in doc.members) {
if(doc.members[i].params && doc.members[i].params.length) {
for (var ii in doc.members[i].params) {
if(doc.members[i].params[ii].optional){
doc.members[i].params[ii].description += '<strong class="tag">Optional</strong>';
}
}
}
}
}
});
return docs;
}
}
};

View File

@ -0,0 +1,50 @@
module.exports = function parseReturnsObject() {
/*
* This processor assumes the format:
* @returns {object} object general description
* {number} objectName.propertyName property description
* {number} objectName.propertyName objectName.propertyName
* ...
*
*/
return {
name: 'parse-returns-object',
description: 'If a method returns an object, and the values are listed ' +
'out, parse them in to anobject that can be iterated by dgeni',
$runBefore: ['rendering-docs'],
$process: function(docs) {
var publicDocs = [];
docs.forEach(function(doc, i) {
if (doc.members) {
docs[i].members.forEach(function(member, ii) {
if (member.returns && member.returns.typeExpression == 'object') {
var params = docs[i].members[ii].returns.description.split('\n{');
docs[i].members[ii].returns.description = params.shift();
if (params.length) {
docs[i].members[ii].returns.description = docs[i].members[ii]
.returns.description
.replace(/^(\w+)/, '<span class="fixed-width">$1</span>');
docs[i].members[ii].returnsObjectParams = parseReturn(params);
}
}
});
}
});
return docs;
function parseReturn(lineArray) {
var params = [];
lineArray.forEach(function(line, l) {
params.push({
type: line.substr(0, line.indexOf('} ')),
key: line.substr(line.indexOf('} ') + 2,
line.indexOf(' ') - line.indexOf('} ') - 2),
description: line.substr(line.indexOf(' ') + 2)
});
});
return params;
}
}
};
};

View File

@ -0,0 +1,170 @@
var path = require('path');
var fs = require('fs');
var Q = require('q');
var sassdoc = require('sassdoc');
module.exports = function parseSass () {
return {
$runBefore: ['rendering-docs'],
$process: function (docs) {
var folders = [];
var docsByComponent = [];
var promises = [];
var returnPromise = Q.defer();
// for each doc, check if new folder(component)
// if yes, get styles promises
docs.forEach( function(doc, index) {
if (doc.fileInfo) {
var folder = doc.fileInfo.filePath
.split('/')
.filter( function (item, index, self) {
return index !== self.length - 1;
})
.join('/');
if(folders.indexOf(folder) === -1) {
folders.push(folder);
docsByComponent.push([doc]);
promises.push( getStyles(folder, docsByComponent.length - 1) );
} else {
docsByComponent[folders.indexOf(folder)].push(doc);
}
}
});
// when all promises are completed, add sass info
Q.allSettled(promises).spread( function () {
var folders = Array.prototype.map.bind(arguments)(function (item) {
return item.value;
});
appendStyles(folders, docsByComponent);
returnPromise.resolve(docs);
}).catch( function (error) {
console.log('SASS ERROR: ' + error);
returnPromise.resolve(docs);
});
return returnPromise.promise;
}
}
};
function appendStyles(folders, docsByComponent) {
folders.forEach( function (folder) {
var styles = formatStyles(folder);
if (styles.length) {
docsByComponent[folder.index].forEach( function (doc) {
doc.sassVariables = styles;
});
}
});
}
function formatStyles (folder) {
// container for holding styles by platform
var concatenatedStyles = {};
// extract styles
folder.styles.filter( function (file) {
return file.data && file.data.length;
}).forEach( function (file) {
var props = file.data.filter( function (item) {
return item.property && item.property.length;
}).map( function (item) {
var property = item.property[0];
return {
name: item.context.name || '',
default: item.context.value || '',
description: property.description || '',
};
});
if( concatenatedStyles[file.platform] ) {
concatenatedStyles[file.platform] = concatenatedStyles[file.platform].concat(props);
} else {
concatenatedStyles[file.platform] = props;
}
});
// place in Array
var formattedStyles = [];
['base', 'ios', 'md', 'wp'].forEach( function (platform) {
if ( concatenatedStyles[platform] ) {
formattedStyles.push({
platform: platform,
props: concatenatedStyles[platform]
});
}
});
return formattedStyles;
}
function getStyles (folder, docIndex) {
var returnPromise = Q.defer();
// generate file names to check
var extension = 'scss';
var allFiles = fs.readdirSync(folder);
var removeNonSass = function (filename) {
return filename.split('.').pop() === extension;
};
var toFileObject = function (filename) {
// determine platform
var platform = filename.split('.')[1];
if ( ['ios', 'md', 'wp'].indexOf(platform) === -1 ) {
platform = 'base';
}
return {
platform: platform,
path: path.join(folder, filename)
};
};
var files = allFiles.filter(removeNonSass).map(toFileObject);
// for each file, fetch styles
var promises = files.map( function (file) {
return Q.promise( function (resolve, reject) {
fs.access(file.path, function (err) {
if (!err) {
sassdoc.parse(file.path )
.then( function (data) {
resolve( { platform: file.platform, data: data });
}).catch( function (error) {
reject(error);
});
} else {
// file doesn't exist
resolve({ platform: file.platform, data: null });
}
});
});
});
// when all promises are finished, return the results
Q.allSettled(promises).then( function (results) {
var styles = results.map( function (style) {
return style.value;
});
returnPromise.resolve({ index: docIndex, styles: styles });
}).catch( function (error) {
returnPromise.reject(error);
});
return returnPromise.promise;
}

View File

@ -0,0 +1,24 @@
module.exports = function removePrivateMembers() {
return {
name: 'remove-private-members',
description: 'Remove member docs with @private tags',
$runAfter: ['tags-parsed'],
$runBefore: ['rendering-docs'],
$process: function(docs) {
docs.forEach(function(doc) {
if (doc.members) {
doc.members = doc.members.filter(function(member) {
return !member.tags.tagsByName.get('hidden') && !member.tags.tagsByName.get('internal');
});
}
if (doc.statics) {
doc.statics = doc.statics.filter(function(staticMethod) {
return !staticMethod.tags.tagsByName.get('hidden') && !staticMethod.tags.tagsByName.get('internal')
});
}
});
return docs;
}
};
};

View File

@ -0,0 +1,52 @@
// var _ = require('lodash');
// var fs = require('fs');
// var semver = require('semver');
// var path = require('canonical-path');
//
// module.exports = {
// name: 'version-data',
// runBefore: ['reading-files'],
// description: 'Expose version data to templates',
// process: function(extraData, config) {
// var basePath = config.get('basePath');
// var outputFolder = config.get('rendering.outputFolder');
// var currentVersion = config.get('currentVersion');
//
// var docsBaseFolder = path.resolve(basePath, outputFolder, 'docs');
//
// var versions;
// try {
// versions = fs.readdirSync(docsBaseFolder)
// .filter(semver.valid)
// .sort(semver.rcompare);
// } catch(e) {
// versions = [];
// }
//
// !_.contains(versions, currentVersion) && versions.unshift(currentVersion);
// !_.contains(versions, 'nightly') && versions.unshift('nightly');
//
// //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('/', config.get('versionFolderBase') || '', folder),
// folder: folder,
// name: version
// };
// });
//
// var versionData = {
// list: versions,
// current: _.find(versions, { name: currentVersion }),
// latest: _.find(versions, {name: latestVersion}) || _.first(versions)
// };
//
// config.set('rendering.contentsFolder',
// path.join(config.get('versionFolderBase') || '', versionData.current.folder || ''));
// config.set('versionData', versionData);
// extraData.version = versionData;
// }
// };

View File

@ -0,0 +1,7 @@
module.exports = [
{'name': 'advanced'},
{'name': 'demo'},
{'name': 'usage'},
{'name': 'hidden'},
{'name': 'internal'}
];

View File

@ -0,0 +1,25 @@
---
layout: "fluid/docs_base"
version: "<$ version.current.name $>"
versionHref: "<$ version.current.href $>"
path: ""
category: api
id: api
title: Javascript
header_sub_title: Extend Ionic even further with the power of AngularJS
searchable: false
---
# Ionic API Docs
<img class="section-header" src="/img/docs/api-intro-header.png" />
Ionic takes everything you know and loved about Ionic V1, and builds on top of it to provide a much more flexible framework.
In the API docs, you'll find two kinds of doc pages: Component and Service APIs.
The Component APIs include classes like `Checkbox`, `Toggle` or `Item` and show you how to use them, in addition to listing their selectors, available properties and events.
The Service APIs are classes like `MenuController`, `Config` or `Platform`. These are services provided by Ionic that can be injected into your classes.

View File

@ -0,0 +1,14 @@
<@ for ver in version.list @>
<@ if ver.name != version.latest.name @>
<@ if loop.first @>
{% if page.versionHref == "<$ ver.href $>" %}
<@ else @>
{% elsif page.versionHref == "<$ ver.href $>" %}
<@ endif @>
{% include fluid/api_menu_flat_<$ ver.name $>.html %}
<@ endif @>
<@ endfor @>
<# make the last case always be to show latest version #>
{% else %}
{% include fluid/api_menu_flat_<$ version.latest.name $>.html %}
{% endif %}

View File

@ -0,0 +1,4 @@
<@ for doc in docs @><@ if doc.URL and doc.private != true and doc.name @>
<li class="capitalize {% if page.id == '<$ doc.name|lower|replace(' ','-')$>' %}active{% endif %}">
<a href="/<$ doc.URL $>"><$ doc.name $></a>
</li><@ endif @><@ endfor @>

View File

@ -0,0 +1,681 @@
<!-- App -->
<li class="menu-section">
<a href="{{ page.versionHref }}/api/components/app/IonicApp/" class="api-section">
App
</a>
<ul>
<li>
<a href="{{ page.versionHref }}/api/components/app/IonicApp/">
IonicApp
</a>
</li>
<li>
<a href="{{ page.versionHref }}/api/components/app/ionicBootStrap/">
ionicBootstrap
</a>
</li>
<li>
<a href="{{ page.versionHref }}/api/components/app/IdRef/">
IdRef
</a>
</li>
</ul>
</li>
<!-- ActionSheet -->
<li class="menu-section">
<a href="{{ page.versionHref }}/api/components/action-sheet/ActionSheet/" class="api-section">
ActionSheet
</a>
<ul>
<li>
<a href="{{ page.versionHref }}/api/components/action-sheet/ActionSheet/">
ActionSheet
</a>
</li>
</ul>
</li>
<!-- Button -->
<li class="menu-section">
<a href="{{ page.versionHref }}/api/components/button/Button/" class="api-section">
Button
</a>
<ul>
<li>
<a href="{{ page.versionHref }}/api/components/button/Button/">
Button
</a>
</li>
<li>
<a href="{{ page.versionHref }}/api/components/button/TapDisabled/">
TapDisabled
</a>
</li>
<li>
<a href="{{ page.versionHref }}/api/components/button/TapClick/">
TapClick
</a>
</li>
</ul>
</li>
<!-- Card -->
<li class="menu-section">
<a href="{{ page.versionHref }}/api/components/card/Card/" class="api-section">
Card
</a>
<ul>
<li>
<a href="{{ page.versionHref }}/api/components/card/Card/">
Card
</a>
</li>
</ul>
</li>
<!-- Checkbox -->
<li class="menu-section">
<a href="{{ page.versionHref }}/api/components/checkbox/Checkbox/" class="api-section">
Checkbox
</a>
<ul>
<li>
<a href="{{ page.versionHref }}/api/components/checkbox/Checkbox/">
Checkbox
</a>
</li>
</ul>
</li>
<!-- Content -->
<li class="menu-section">
<a href="{{ page.versionHref }}/api/components/content/Content/" class="api-section">
Content
</a>
<ul>
<li>
<a href="{{ page.versionHref }}/api/components/content/Content/">
Content
</a>
</li>
</ul>
</li>
<!-- Icon -->
<li class="menu-section">
<a href="{{ page.versionHref }}/api/components/icon/Icon/" class="api-section">
Icon
</a>
<ul>
<li>
<a href="{{ page.versionHref }}/api/components/icon/Icon/">
Icon
</a>
</li>
</ul>
</li>
<!-- IonItem -->
<li class="menu-section">
<a href="{{ page.versionHref }}/api/components/item/IonItem/" class="api-section">
IonItem
</a>
<ul>
<li>
<a href="{{ page.versionHref }}/api/components/item/IonItem/">
IonItem
</a>
</li>
<li>
<a href="{{ page.versionHref }}/api/components/item/ItemGroup/">
ItemGroup
</a>
</li>
<li>
<a href="{{ page.versionHref }}/api/components/item/ItemGroupTitle/">
ItemGroupTitle
</a>
</li>
</ul>
</li>
<!-- IonInput -->
<li class="menu-section">
<a href="{{ page.versionHref }}/api/components/form/IonInput/" class="api-section">
IonInput
</a>
<ul>
<li>
<a href="{{ page.versionHref }}/api/components/form/IonInput/">
IonInput
</a>
</li>
</ul>
</li>
<!-- TextInput -->
<li class="menu-section">
<a href="{{ page.versionHref }}/api/components/text-input/TextInput/" class="api-section">
TextInput
</a>
<ul>
<li>
<a href="{{ page.versionHref }}/api/components/text-input/TextInput/">
TextInput
</a>
</li>
<li>
<a href="{{ page.versionHref }}/api/components/text-input/TextInputElement/">
TextInputElement
</a>
</li>
<li>
<a href="{{ page.versionHref }}/api/components/label/label/">
Label
</a>
</li>
</ul>
</li>
<!-- IonList -->
<li class="menu-section">
<a href="{{ page.versionHref }}/api/components/list/IonList/" class="api-section">
IonList
</a>
<ul>
<li>
<a href="{{ page.versionHref }}/api/components/list/IonList/">
IonList
</a>
</li>
<li>
<a href="{{ page.versionHref }}/api/components/list/ListHeader/">
ListHeader
</a>
</li>
</ul>
</li>
<!-- ShowWhen -->
<li class="menu-section">
<a href="{{ page.versionHref }}/api/components/show-hide-when/ShowWhen/" class="api-section">
ShowWhen
</a>
<ul>
<li>
<a href="{{ page.versionHref }}/api/components/show-hide-when/ShowWhen/">
ShowWhen
</a>
</li>
</ul>
</li>
<!-- HideWhen -->
<li class="menu-section">
<a href="{{ page.versionHref }}/api/components/show-hide-when/HideWhen/" class="api-section">
HideWhen
</a>
<ul>
<li>
<a href="{{ page.versionHref }}/api/components/show-hide-when/HideWhen/">
HideWhen
</a>
</li>
</ul>
</li>
<!-- MaterialButton -->
<li class="menu-section">
<a href="{{ page.versionHref }}/api/components/material/MaterialButton/" class="api-section">
MaterialButton
</a>
<ul>
<li>
<a href="{{ page.versionHref }}/api/components/material/MaterialButton/">
MaterialButton
</a>
</li>
<li>
<a href="{{ page.versionHref }}/api/components/material/MaterialRippleEffect/">
MaterialRippleEffect
</a>
</li>
</ul>
</li>
<!-- Menu -->
<li class="menu-section">
<a href="{{ page.versionHref }}/api/components/menu/Menu/" class="api-section">
Menu
</a>
<ul>
<li>
<a href="{{ page.versionHref }}/api/components/menu/Menu/">
Menu
</a>
</li>
<li>
<a href="{{ page.versionHref }}/api/components/menu/MenuToggle/">
MenuToggle
</a>
</li>
<li>
<a href="{{ page.versionHref }}/api/components/menu/MenuType/">
MenuType
</a>
</li>
</ul>
</li>
<!-- Modal -->
<li class="menu-section">
<a href="{{ page.versionHref }}/api/components/modal/ionModal/" class="api-section">
Modal
</a>
<ul>
<li>
<a href="{{ page.versionHref }}/api/components/modal/ionModal/">
Modal
</a>
</li>
</ul>
</li>
<!-- Nav -->
<li class="menu-section">
<a href="{{ page.versionHref }}/api/components/nav/Nav/" class="api-section">
Nav
</a>
<ul>
<li>
<a href="{{ page.versionHref }}/api/components/nav/Nav/">
Nav
</a>
</li>
<li>
<a href="{{ page.versionHref }}/api/components/nav/NavController/">
NavController
</a>
</li>
<li>
<a href="{{ page.versionHref }}/api/components/nav/NavParams/">
NavParams
</a>
</li>
<li>
<a href="{{ page.versionHref }}/api/components/nav/NavPush/">
NavPush
</a>
</li>
<li>
<a href="{{ page.versionHref }}/api/components/nav/NavPop/">
NavPop
</a>
</li>
<li>
<a href="{{ page.versionHref }}/api/components/nav/NavRouter/">
NavRouter
</a>
</li>
</ul>
</li>
<!-- NavBar -->
<li class="menu-section">
<a href="{{ page.versionHref }}/api/components/navbar/NavBar/" class="api-section">
NavBar
</a>
<ul>
<li>
<a href="{{ page.versionHref }}/api/components/navbar/NavBar/">
NavBar
</a>
</li>
<li>
<a href="{{ page.versionHref }}/api/components/navbar/NavbarTemplate/">
NavbarTemplate
</a>
</li>
</ul>
</li>
<!-- Popup -->
<li class="menu-section">
<a href="{{ page.versionHref }}/api/components/popup/ionPopup/" class="api-section">
Popup
</a>
<ul>
<li>
<a href="{{ page.versionHref }}/api/components/popup/ionPopup/">
Popup
</a>
</li>
</ul>
</li>
<!-- Slides -->
<li class="menu-section">
<a href="{{ page.versionHref }}/api/components/slides/Slides/" class="api-section">
Slides
</a>
<ul>
<li>
<a href="{{ page.versionHref }}/api/components/slides/Slides/">
Slides
</a>
</li>
<li>
<a href="{{ page.versionHref }}/api/components/slides/Slide/">
Slide
</a>
</li>
<li>
<a href="{{ page.versionHref }}/api/components/slides/SlideLazy/">
SlideLazy
</a>
</li>
</ul>
</li>
<!-- Radio -->
<li class="menu-section">
<a href="{{ page.versionHref }}/api/components/radio/RadioGroup/" class="api-section">
Radio
</a>
<ul>
<li>
<a href="{{ page.versionHref }}/api/components/radio/RadioGroup/">
RadioGroup
</a>
</li>
<li>
<a href="{{ page.versionHref }}/api/components/radio/RadioButton/">
RadioButton
</a>
</li>
</ul>
</li>
<!-- Scroll -->
<li class="menu-section">
<a href="{{ page.versionHref }}/api/components/scroll/Scroll/" class="api-section">
Scroll
</a>
<ul>
<li>
<a href="{{ page.versionHref }}/api/components/scroll/Scroll/">
Scroll
</a>
</li>
<li>
<a href="{{ page.versionHref }}/api/components/scroll/Refresher/">
Refresher
</a>
</li>
</ul>
</li>
<!-- SearchBar -->
<li class="menu-section">
<a href="{{ page.versionHref }}/api/components/searchbar/SearchBar/" class="api-section">
SearchBar
</a>
<ul>
<li>
<a href="{{ page.versionHref }}/api/components/searchbar/SearchBar/">
SearchBar
</a>
</li>
</ul>
</li>
<!-- Segment -->
<li class="menu-section">
<a href="{{ page.versionHref }}/api/components/segment/Segment/" class="api-section">
Segment
</a>
<ul>
<li>
<a href="{{ page.versionHref }}/api/components/segment/Segment/">
Segment
</a>
</li>
<li>
<a href="{{ page.versionHref }}/api/components/segment/SegmentControlValueAccessor/">
SegmentControlValueAccessor
</a>
</li>
<li>
<a href="{{ page.versionHref }}/api/components/segment/SegmentButton/">
SegmentButton
</a>
</li>
</ul>
</li>
<!-- Switch -->
<li class="menu-section">
<a href="{{ page.versionHref }}/api/components/switch/Switch/" class="api-section">
Switch
</a>
<ul>
<li>
<a href="{{ page.versionHref }}/api/components/switch/Switch/">
Switch
</a>
</li>
</ul>
</li>
<!-- IonTabs -->
<li class="menu-section">
<a href="{{ page.versionHref }}/api/components/tabs/IonTabs/" class="api-section">
IonTabs
</a>
<ul>
<li>
<a href="{{ page.versionHref }}/api/components/tabs/IonTabs/">
IonTabs
</a>
</li>
<li>
<a href="{{ page.versionHref }}/api/components/tabs/IonTab/">
IonTab
</a>
</li>
</ul>
</li>
<!-- Toolbar -->
<li class="menu-section">
<a href="{{ page.versionHref }}/api/components/toolbar/Toolbar/" class="api-section">
Toolbar
</a>
<ul>
<li>
<a href="{{ page.versionHref }}/api/components/toolbar/Toolbar/">
Toolbar
</a>
</li>
<li>
<a href="{{ page.versionHref }}/api/components/toolbar/ToolbarBase/">
ToolbarBase
</a>
</li>
</ul>
</li>
<!-- View -->
<li class="menu-section">
<a href="{{ page.versionHref }}/api/components/view/View/" class="api-section">
View
</a>
<ul>
<li>
<a href="{{ page.versionHref }}/api/components/view/ViewItem/">
ViewItem
</a>
</li>
</ul>
</li>
<!-- Animations -->
<li class="menu-section">
<a href="{{ page.versionHref }}/api/animations/Animation/" class="api-section">
Animations
</a>
<ul>
<li>
<a href="{{ page.versionHref }}/api/animations/Animation/">
Animation
</a>
</li>
</ul>
</li>
<!-- Transitions -->
<li class="menu-section">
<a href="{{ page.versionHref }}/api/transitions/Transition/" class="api-section">
Transitions
</a>
<ul>
<li>
<a href="{{ page.versionHref }}/api/transitions/Transition/">
Transition
</a>
</li>
</ul>
</li>
<!-- Config -->
<li class="menu-section">
<a href="{{ page.versionHref }}/api/config/Config/" class="api-section">
Config
</a>
<ul>
<li>
<a href="{{ page.versionHref }}/api/config/Config/">
Config
</a>
</li>
<li>
<a href="{{ page.versionHref }}/api/config/IonicDirectives/">
IonicDirectives
</a>
</li>
<li>
<a href="{{ page.versionHref }}/api/config/IonicView/">
IonicDirectives
</a>
</li>
<li>
<a href="{{ page.versionHref }}/api/config/IonicComponent/">
IonicDirectives
</a>
</li>
<li>
<a href="{{ page.versionHref }}/api/config/App/">
App
</a>
</li>
</ul>
</li>
<!-- Net -->
<li class="menu-section">
<a href="{{ page.versionHref }}/api/net/Http/" class="api-section">
Net
</a>
<ul>
<li>
<a href="{{ page.versionHref }}/api/net/Http/">
HTTP
</a>
</li>
</ul>
</li>
<!-- Platform -->
<li class="menu-section">
<a href="{{ page.versionHref }}/api/platform/Platform/" class="api-section">
Platform
</a>
<ul>
<li>
<a href="{{ page.versionHref }}/api/platform/Platform/">
Platform
</a>
</li>
<li>
<a href="{{ page.versionHref }}/api/platform/PlatformCtrl/">
PlatformCtrl
</a>
</li>
</ul>
</li>
<!-- Util -->
<li class="menu-section">
<a href="{{ page.versionHref }}/api/util/ClickBlock/" class="api-section">
Util
</a>
<ul>
<li>
<a href="{{ page.versionHref }}/api/util/ClickBlock/">
Click Block
</a>
</li>
</ul>
</li>
<!-- Storage -->
<li class="menu-section">
<a href="{{ page.versionHref }}/api/storage/Storage/" class="api-section">
Storage
</a>
<ul>
<li>
<a href="{{ page.versionHref }}/api/storage/Storage/">
Storage
</a>
</li>
<li>
<a href="{{ page.versionHref }}/api/storage/StorageEngine/">
StorageEngine
</a>
</li>
<li>
<a href="{{ page.versionHref }}/api/storage/SqlStorage/">
SqlStorage
</a>
</li>
<li>
<a href="{{ page.versionHref }}/api/storage/LocalStorage">
LocalStorage
</a>
</li>
</ul>
</li>

View File

@ -0,0 +1,11 @@
<select name="version"
id="version-toggle"
onchange="window.location.href=this.options[this.selectedIndex].value">
<@ for ver in version.list @>
<option
value="<$ ver.href $>/{% if page.path != ''%}{{page.path}}{% else %}api/{% endif %}"
{% if page.version == "<$ ver.name $>"%}selected{% endif %}>
<$ ver.name $> <@ if version.latest.name == ver.name @>(latest)<@ endif @>
</option>
<@ endfor @>
</select>

View File

@ -0,0 +1,408 @@
---
layout: "fluid/docs_base"
version: "<$ version.current.name $>"
versionHref: "<$ version.current.href $>"
path: "<$ doc.path $>"
category: api
id: "<$ doc.name|lower|replace(' ','-') $>"
title: "<@ if doc.docType == "directive" @><$ doc.name | dashCase $><@ else @><$ doc.name $><@ endif @>"
header_sub_title: "Ionic API Documentation"
doc: "<$ doc.name $>"
docType: "<$ doc.docType $>"
<@ if doc.demo @>show_preview_device: true
preview_device_url: "<$ doc.demo $>www/"
angular_controller: APIDemoCtrl <@ endif @>
---
<@ macro paramList(paramData) -@>
<@- if paramData -@><span class="params">(
<@- for param in paramData -@>
<span class="param"><$ param | escape $><@ if not loop.last @>, <@ endif @></span>
<@- endfor @>)</span>
<@- endif @>
<@- endmacro -@>
<@ macro returnObject(params) -@>
<@- if params -@>
<table class="table returns-object-table param-table">
<thead>
<tr>
<th>Property</th>
<th>Type</th>
<th>Details</th>
</tr>
</thead>
<tbody>
<@ for param in params @>
<tr>
<td class="fixed-width">
<$ param.key $>
</td>
<td>
<$ param.type | code $>
</td>
<td>
<$ param.description | marked $>
</td>
</tr>
<@ endfor @>
</tbody>
</table>
<@- endif @>
<@- endmacro -@>
<@ macro githubViewLink(doc) -@>
<a href="https://github.com/<$ versionInfo.gitRepoInfo.owner $>/<$ versionInfo.gitRepoInfo.repo $>/tree/master/<$ doc.fileInfo.relativePath $>#L<$ doc.location.start.line+1 $>-L<$ doc.location.end.line+1 $>"><$ doc.fileInfo.relativePath $> (line <$ doc.location.start.line+1 $>)</a>
<@- endmacro -@>
<@ macro paramTable(params, isDirective) -@>
<table class="table param-table" style="margin:0;">
<thead>
<tr>
<th><@ if isDirective @>Attr<@ else @>Param<@ endif @></th>
<th>Type</th>
<th>Details</th>
</tr>
</thead>
<tbody>
<@ for param in params @>
<tr>
<td>
<$ param.name $>
<@ if param.alias @>| <$ param.alias $><@ endif @>
<@ if param.type.optional @><div><em>(optional)</em></div><@ endif @>
</td>
<td>
<$ typeList(param.typeList) $>
</td>
<td>
<$ param.description | marked $>
<@ if param.default @><p><em>(default: <$ param.default $>)</em></p><@ endif @>
</td>
</tr>
<@ endfor @>
</tbody>
</table>
<@- endmacro -@>
<@ macro inputTable(params, isDirective) -@>
<table class="table param-table" style="margin:0;">
<thead>
<tr>
<th>Attr</th>
<th>Type</th>
<th>Details</th>
</tr>
</thead>
<tbody>
<@ for param in params @>
<tr>
<td><$ param.name $></td>
<td><code><$ param.type $></code></td>
<td><$ param.description | marked $></td>
</tr>
<@ endfor @>
</tbody>
</table>
<@- endmacro -@>
<@ macro outputTable(params, isDirective) -@>
<table class="table param-table" style="margin:0;">
<thead>
<tr>
<th>Attr</th>
<th>Details</th>
</tr>
</thead>
<tbody>
<@ for param in params @>
<tr>
<td><$ param.name $></td>
<td><$ param.description | marked $></td>
</tr>
<@ endfor @>
</tbody>
</table>
<@- endmacro -@>
<@- macro functionSyntax(fn) @>
<@- set sep = joiner(',&nbsp;') -@>
<code><$ fn.name $><@- if not fn.isProperty @>(<@ endif -@><@- for param in fn.params @><$ sep() $>
<@- if param.type.optional @>[<@ endif -@>
<$ param.name $>
<@- if param.type.optional @>]<@ endif -@>
<@ endfor @><@- if not fn.isProperty @>)<@ endif -@></code>
<@ if fn.alias @><small>(alias: <$ fn.alias $>)</small><@ endif @>
<@ endmacro -@>
<@ macro typeList(types) -@>
<@ set separator = joiner("|") @>
<@ for type in types @><$ separator() $><$ type | code $><@ endfor @>
<@- endmacro -@>
<@- macro typeInfo(fn) -@>
<$ typeList(fn.typeList) $> <$ fn.description | marked $>
<@- endmacro -@>
<@- macro sassTable(files) -@>
<div id="sass-variables" ng-controller="SassToggleCtrl">
<div class="sass-platform-toggle">
<@ if files.length > 1 @>
<@ for file in files @>
<@ if loop.first @>
<a ng-init="setSassPlatform('<$ file.platform $>')" ng-class="{ active: active === '<$ file.platform $>' }" ng-click="setSassPlatform('<$ file.platform $>')" ><$ file.platform | platform $></a>
<@ else @>
<a ng-class="{ active: active === '<$ file.platform $>' }" ng-click="setSassPlatform('<$ file.platform $>')"><$ file.platform | platform $></a>
<@ endif @>
<@ endfor @>
<@ else @>
<h3 ng-init="setSassPlatform('<$ files[0].platform $>')"><$ files[0].platform | platform $></h3>
<@ endif @>
</div>
<@ for file in files @>
<table ng-show="active === '<$ file.platform $>'" id="sass-<$file.platform $>" class="table param-table" style="margin:0;">
<thead>
<tr>
<th>Property</th>
<th>Default</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<@ for prop in file.props @>
<tr>
<td><code>$<$ prop.name $></code></td>
<@ if prop.default @>
<td><$ prop.default | code $></td>
<@ else @>
<td>
</td>
<@ endif @>
<td><$ prop.description | marked $></td>
</tr>
<@ endfor @>
</tbody>
</table>
<@ endfor @>
</div>
<@- endmacro -@>
<@ block body @>
<@ block content @>
<@ block header @>
<h1 class="api-title">
<a class="anchor" name="<$ doc.name | dashCase $>" href="#<$ doc.name | dashCase $>"></a>
<@ if doc.docType == "directive" @>
<$ doc.name | dashCase $>
<@ else @>
<$ doc.name $>
<@- if doc.decorators[0].argumentInfo[0].selector @>
<h3><code><$ doc.decorators[0].argumentInfo[0].selector $></code></h3>
<@ endif -@>
<@ endif @>
<@ if doc.parent @>
<br />
<small>
Child of <$ doc.parent $>
</small>
<@ endif @>
<@ if doc.delegate @>
<br/>
<small>
Delegate: <$ doc.delegate $>
</small>
<@ endif @>
</h1>
<a class="improve-v2-docs" href="http://github.com/ionic-team/ionic/edit/master/<$ doc.fileInfo.projectRelativePath $>#L<$ doc.location.start.line $>">
Improve this doc
</a>
<@ if doc.codepen @>
{% include codepen.html id="<$ doc.codepen $>" %}
<@ endif @>
<@ endblock @>
<@ block description @>
<$ doc.description | marked $>
<@ endblock @>
<!-- @usage tag -->
<@ if doc.usage @>
<h2><a class="anchor" name="usage" href="#usage"></a>Usage</h2>
<@ block usage @>
<$ doc.usage | marked $>
<@ endblock @>
<@ endif @>
<!-- @property tags -->
<@ if doc.properties @>
<h2><a class="anchor" name="attributes" href="#attributes"></a>Attributes:</h2>
<table class="table" style="margin:0;">
<thead>
<tr>
<th>Attribute</th>
<@ set hasTypes = false @>
<@ for prop in doc.properties @>
<@ if prop.type @>
<@ set hasTypes = true @>
<@ endif @>
<@ endfor @>
<@ if hasTypes @>
<th>Type</th>
<@ endif @>
<th>Description</th>
</tr>
</thead>
<tbody>
<@ for prop in doc.properties @>
<tr>
<td>
<$ prop.name $>
</td>
<@ if hasTypes @>
<td>
<$ prop.type.name $>
</td>
<@ endif @>
<td>
<$ prop.description $>
</td>
</tr>
<@ endfor @>
</tbody>
</table>
<@ endif @>
<@- if doc.statics.length -@>
<h2><a class="anchor" name="static-members" href="#static-members"></a>Static Members</h2>
<@- for method in doc.statics @><@ if not method.internal @>
<div id="<$ method.name $>"></div>
<h3><a class="anchor" name="<$ method.name $>" href="#<$ method.name $>"></a><$ functionSyntax(method) $></h3>
<$ method.description $>
<@ if method.params @>
<$ paramTable(method.params) $>
<@ endif @>
<@ if method.this @>
<h4> Method's `this`
<$ method.this $>
</h4>
<@ endif @>
<@ if method.returns @>
<div class="anchor" class="return-value">
<i class="icon ion-arrow-return-left"></i>
<b>Returns:</b> <$ typeInfo(method.returns) $>
<@ if method.returnsObjectParams @>
<$ returnObject(method.returnsObjectParams) $>
<@ endif @>
</div>
<@ endif @>
<@ endif @>
<@ endfor -@>
<@ endif @>
<!-- instance methods on the class -->
<@- if doc.members and doc.members.length @>
<h2><a class="anchor" name="instance-members" href="#instance-members"></a>Instance Members</h2>
<@- for method in doc.members @>
<div id="<$ method.name $>"></div>
<h3>
<a class="anchor" name="<$ method.name $>" href="#<$ method.name $>"></a>
<$ functionSyntax(method) $>
</h3>
<$ method.description $>
<@ if method.params @>
<$ paramTable(method.params) $>
<@ endif @>
<@ if method.this @>
<h4> Method's `this`
<$ method.this $>
</h4>
<@ endif @>
<@ if method.returns @>
<div class="return-value">
<i class="icon ion-arrow-return-left"></i>
<b>Returns:</b> <$ typeInfo(method.returns) $>
<@ if method.returnsObjectParams @>
<$ returnObject(method.returnsObjectParams) $>
<@ endif @>
</div>
<@ endif @>
<@ endfor -@>
<@- endif -@>
<@- if doc.inputs and doc.inputs.length @>
<!-- input methods on the class -->
<h2><a class="anchor" name="input-properties" href="#input-properties"></a>Input Properties</h2>
<$ inputTable(doc.inputs) $>
<@- endif -@>
<@- if doc.outputs and doc.outputs.length @>
<!-- output events on the class -->
<h2><a class="anchor" name="output-events" href="#output-events"></a>Output Events</h2>
<$ outputTable(doc.outputs) $>
<@- endif -@>
<@ block advanced @>
<@- if doc.advanced -@>
<h2><a class="anchor" name="advanced" href="#advanced"></a>Advanced</h2>
<$ doc.advanced | marked $>
<@- endif -@>
<@ endblock @>
<@ if doc.sassVariables @>
<h2 id="sass-variable-header"><a class="anchor" name="sass-variables" href="#sass-variables"></a>Sass Variables</h2>
<$ sassTable(doc.sassVariables) $>
<@ endif @>
<!-- related link -->
<@- if doc.see @>
<h2><a class="anchor" name="related" href="#related"></a>Related</h2>
<@ for s in doc.see @>
<$ s | safe $> <@- if not loop.last @>,<@- endif -@>
<@- endfor -@>
<@- endif -@>
<!-- end content block -->
<@ endblock @>
<!-- end body block -->
<@ endblock @>

View File

@ -0,0 +1,93 @@
var Package = require('dgeni').Package;
var jsdocPackage = require('dgeni-packages/jsdoc');
var nunjucksPackage = require('dgeni-packages/nunjucks');
var typescriptPackage = require('../typescript-package');
var gitPackage = require('dgeni-packages/git');
var path = require('canonical-path');
// Define the dgeni package for generating the docs
module.exports = new Package('angular-v2-docs', [jsdocPackage, nunjucksPackage, typescriptPackage, gitPackage])
// Register the processors
.processor(require('./processors/createTypeDefinitionFile'))
.config(function(readFilesProcessor, inlineTagProcessor) {
readFilesProcessor.basePath = path.resolve(__dirname, '../..');
// Don't run unwanted processors
readFilesProcessor.$enabled = false;
inlineTagProcessor.$enabled = false;
})
// Configure the log service
.config(function(log) {
log.level = 'info';
})
.config(function(renderDocsProcessor, versionInfo) {
renderDocsProcessor.extraData.versionInfo = versionInfo;
})
.config(function(readFilesProcessor, inlineTagProcessor, readTypeScriptModules, createTypeDefinitionFile) {
// Don't run unwanted processors
readFilesProcessor.$enabled = false; // We are not using the normal file reading processor
inlineTagProcessor.$enabled = false; // We are not actually processing the inline link tags
// Configure file reading
readFilesProcessor.basePath = path.resolve(__dirname, '../..');
readTypeScriptModules.sourceFiles = [
'angular2/angular2.ts'
];
readTypeScriptModules.basePath = path.resolve(path.resolve(__dirname, '../../modules'));
createTypeDefinitionFile.typeDefinitions = [
{
id: 'angular2/angular2',
modules: {
'angular2/angular2': 'angular2/angular2',
}
}
];
})
.config(function(parseTagsProcessor, getInjectables) {
// We actually don't want to parse param docs in this package as we are getting the data out using TS
parseTagsProcessor.tagDefinitions.forEach(function(tagDef) {
if (tagDef.name === 'param') {
tagDef.docProperty = 'paramData';
tagDef.transforms = [];
}
});
})
// Configure file writing
.config(function(writeFilesProcessor) {
writeFilesProcessor.outputFolder = 'dist/docs';
})
// Configure rendering
.config(function(templateFinder, templateEngine) {
// Nunjucks and Angular conflict in their template bindings so change Nunjucks
templateEngine.config.tags = {
variableStart: '{$',
variableEnd: '$}'
};
templateFinder.templateFolders
.unshift(path.resolve(__dirname, 'templates'));
templateFinder.templatePatterns = [
'${ doc.template }',
'${ doc.id }.${ doc.docType }.template.html',
'${ doc.id }.template.html',
'${ doc.docType }.template.html',
'common.template.html'
];
});

View File

@ -0,0 +1,11 @@
var Package = require('dgeni').Package;
module.exports = function mockPackage() {
return new Package('mockPackage', [require('../')])
// provide a mock log service
.factory('log', function() { return require('dgeni/lib/mocks/log')(false); })
// .factory('templateEngine', function() { return {}; });
};

View File

@ -0,0 +1,86 @@
var _ = require('lodash');
var path = require('canonical-path');
module.exports = function createTypeDefinitionFile(log) {
return {
$runAfter: ['processing-docs'],
$runBefore: ['docs-processed'],
$validate: {
dtsPath: { presence: true },
dtsExtension: { presence: true },
typeDefinitions: { presence: true }
},
dtsPath: 'typings',
dtsExtension: '.d.ts',
typeDefinitions: [],
$process: function(docs) {
var dtsPath = this.dtsPath;
var dtsExtension = this.dtsExtension;
// For each type definition that we wish to create we define a dgeni "doc" for it
var typeDefDocs = _.map(this.typeDefinitions, function(def) {
var id = def.id + dtsExtension;
var docPath = path.join(dtsPath, id);
return {
docType: 'type-definition',
id: id,
aliases: [id],
path: docPath,
outputPath: docPath,
// A type definition may include a number of top level modules
// And those modules could be aliased (such as 'angular2/angular2.api' -> 'angular2/angular2')
moduleDocs: _.transform(def.modules, function(moduleDocs, id, alias) {
moduleDocs[id] = { id: alias, doc: null };
})
};
});
// Now add all the module docs to their corresponding type definition doc
_.forEach(docs, function(doc) {
_.forEach(typeDefDocs, function(typeDefDoc) {
if(typeDefDoc.moduleDocs[doc.id]) {
// Add a copy, because we are going to modify it
typeDefDoc.moduleDocs[doc.id].doc = doc;
}
});
});
return _.filter(typeDefDocs, function(doc) {
_.forEach(doc.moduleDocs, function(modDoc, alias) {
if (!doc || !modDoc.doc) {
log.error('createTypeDefinitionFile processor: no such module "' + alias + '" (Did you forget to add it to the modules to load?)');
doc = null;
return;
}
_.forEach(modDoc.doc.exports, function(exportDoc) {
// Search for classes with a constructor marked as `@private`
if (exportDoc.docType === 'class' && exportDoc.constructorDoc && exportDoc.constructorDoc.private) {
// Convert this class to an interface with no constructor
exportDoc.docType = 'interface';
exportDoc.constructorDoc = null;
if (exportDoc.heritage) {
// convert the heritage since interfaces use `extends` not `implements`
exportDoc.heritage = exportDoc.heritage.replace('implements', 'extends');
}
// Add the `declare var SomeClass extends InjectableReference` construct
modDoc.doc.exports.push({
docType: 'var',
name: exportDoc.name,
id: exportDoc.id,
heritage: ': InjectableReference'
});
}
});
});
return !!doc;
});
}
};
};

View File

@ -0,0 +1,48 @@
var mockPackage = require('../mocks/mockPackage');
var Dgeni = require('dgeni');
var path = require('canonical-path');
var _ = require('lodash');
describe('createTypeDefinitionFile processor', function() {
var dgeni, injector, processor;
beforeEach(function() {
dgeni = new Dgeni([mockPackage()]);
injector = dgeni.configureInjector();
processor = injector.get('createTypeDefinitionFile');
// Initialize the processor
processor.typeDefinitions = [{
id: 'angular2/angular2',
modules: { 'angular2/angular2': 'angular2/angular2' }
}];
});
describe('classes with private constructors', function() {
it('should convert heritage from `implements` into `extends`', function() {
// Create some mock docs for testing
var docs = [
{
id: 'angular2/angular2',
exports: [
{ docType: 'class', heritage: 'implements Xyz', constructorDoc: { private: true } }
]
}
];
docs = processor.$process(docs);
expect(docs.length).toEqual(1);
expect(docs[0].docType).toEqual('type-definition');
var moduleDoc = docs[0].moduleDocs['angular2/angular2'].doc;
expect(moduleDoc.exports.length).toEqual(2);
expect(moduleDoc.exports[0].heritage).toEqual('extends Xyz');
});
});
});

View File

@ -0,0 +1,17 @@
{% extends '../type-definition.template.html' %}
{% block staticDeclarations %}
interface List<T> extends Array<T> {}
interface Map<K,V> {}
interface StringMap<K,V> extends Map<K,V> {}
declare module ng {
// See https://github.com/Microsoft/TypeScript/issues/1168
class BaseException /* extends Error */ {
message: string;
stack: string;
toString(): string;
}
interface InjectableReference {}
}
{% endblock %}

View File

@ -0,0 +1,72 @@
{%- macro commentBlock(doc, level) -%}
{%- if doc.content | trim %}
{% if level > 1 %}{$ '/**' | indent(level-1, true) | replace(r/\n$/, "") $}{% else %}/**{% endif %}
{$ doc.content | trim | replace(r/^/gm, "* ") | indent(level, true) | replace(r/\n$/, "") $}
{$ '*/' | indent(level, true) | replace(r/\n$/, "") $}{% endif -%}
{%- endmacro -%}
{%- macro memberInfo(member) -%}
{$ commentBlock(member, 5) $}
{$ member.name $}{% if member.optional %}?{% endif -%}
{% if member.typeParameters %}<{% for typeParam in member.typeParameters %}{$ typeParam $}{% if not loop.last %}, {% endif %}{% endfor %}>{% endif -%}
{%- if member.parameters -%}({% for param in member.parameters %}{$ param $}{% if not loop.last %}, {% endif %}{% endfor %}){%- endif -%}
{%- if member.returnType == 'Directive' %}: DirectiveAnnotation{%- elif member.returnType -%}: {$ member.returnType $}{%- else -%}: void
{%- endif -%};
{%- endmacro -%}
// Type definitions for Angular v{$ versionInfo.currentVersion.full | replace(r/\+/, "_") $}
// Project: http://angular.io/
// Definitions by: angular team <https://github.com/angular/>
// Definitions: https://github.com/borisyankov/DefinitelyTyped
// ***********************************************************
// This file is generated by the Angular build process.
// Please do not create manual edits or send pull requests
// modifying this file.
// ***********************************************************
{% block staticDeclarations %}{% endblock %}
{% for alias, module in doc.moduleDocs %}
{$ commentBlock(module.doc, 1) $}
declare module ng {
{%- for export in module.doc.exports -%}
{%- if export.content -%}
{$ commentBlock(export, 3) $}
{%- endif %}
{$ export.docType $} {$ export.name $}{$ export.typeParams $}{%- if export.heritage == ' extends Directive' %} extends DirectiveAnnotation{% else %}{$ export.heritage $}{% endif %}
{%- if export.docType == 'class' or export.docType == 'interface' %} {
{%- if export.newMember %}
{$ memberInfo(export.newMember) $}
{% endif %}
{%- if export.callMember %}
{$ memberInfo(export.callMember) $}
{% endif -%}
{%- for member in export.members %}
{$ memberInfo(member) $}
{%- endfor %}
}
{%- elif export.docType == 'enum' %} {
{%- for member in export.members %}
{$ member $}{% if not loop.last %},
{%- endif -%}
{%- endfor %}
}
{%- else -%}
{% if export.parameters %}({% for param in export.parameters %}{$ param $}{% if not loop.last %}, {% endif %}{% endfor %}){%- endif %}
{%- if export.returnType %} : {$ export.returnType $} {% endif -%}
;
{%- endif %}
{% endfor %}
}
{% endfor %}
declare module "angular2/angular2" {
export = ng;
}