docs(api/dart): add support for generation and display (#1888)
Fixes #1880. Supersedes #1593.
This commit is contained in:
parent
08d051d2f6
commit
1bef20abc4
|
@ -15,13 +15,13 @@ env:
|
||||||
- TASK=lint
|
- TASK=lint
|
||||||
- TASK="run-e2e-tests --fast" SCRIPT=examples-install.sh
|
- TASK="run-e2e-tests --fast" SCRIPT=examples-install.sh
|
||||||
- TASK="run-e2e-tests --fast" SCRIPT=examples-install-preview.sh
|
- TASK="run-e2e-tests --fast" SCRIPT=examples-install-preview.sh
|
||||||
- TASK=harp-compile SCRIPT=deploy-install.sh
|
- TASK=build-compile SCRIPT=deploy-install.sh
|
||||||
- TASK=harp-compile SCRIPT=deploy-install-preview.sh
|
- TASK=build-compile SCRIPT=deploy-install-preview.sh
|
||||||
matrix:
|
matrix:
|
||||||
fast_finish: true
|
fast_finish: true
|
||||||
allow_failures:
|
allow_failures:
|
||||||
- env: "TASK=\"run-e2e-tests --fast\" SCRIPT=examples-install-preview.sh"
|
- env: "TASK=\"run-e2e-tests --fast\" SCRIPT=examples-install-preview.sh"
|
||||||
- env: "TASK=harp-compile SCRIPT=deploy-install-preview.sh"
|
- env: "TASK=build-compile SCRIPT=deploy-install-preview.sh"
|
||||||
before_install:
|
before_install:
|
||||||
- npm install -g gulp --no-optional
|
- npm install -g gulp --no-optional
|
||||||
install:
|
install:
|
||||||
|
|
150
gulpfile.js
150
gulpfile.js
|
@ -30,6 +30,7 @@ var tslint = require('gulp-tslint');
|
||||||
// 2. Think about using spawn instead of exec in case of long error messages.
|
// 2. Think about using spawn instead of exec in case of long error messages.
|
||||||
|
|
||||||
var TOOLS_PATH = './tools';
|
var TOOLS_PATH = './tools';
|
||||||
|
var ANGULAR_IO_PROJECT_PATH = path.resolve('.');
|
||||||
var ANGULAR_PROJECT_PATH = '../angular';
|
var ANGULAR_PROJECT_PATH = '../angular';
|
||||||
var PUBLIC_PATH = './public';
|
var PUBLIC_PATH = './public';
|
||||||
var TEMP_PATH = './_temp';
|
var TEMP_PATH = './_temp';
|
||||||
|
@ -63,12 +64,21 @@ var _devguideShredJadeOptions = {
|
||||||
};
|
};
|
||||||
|
|
||||||
var _apiShredOptions = {
|
var _apiShredOptions = {
|
||||||
|
lang: 'ts',
|
||||||
examplesDir: path.join(ANGULAR_PROJECT_PATH, 'modules/@angular/examples'),
|
examplesDir: path.join(ANGULAR_PROJECT_PATH, 'modules/@angular/examples'),
|
||||||
fragmentsDir: path.join(DOCS_PATH, '_fragments/_api'),
|
fragmentsDir: path.join(DOCS_PATH, '_fragments/_api'),
|
||||||
zipDir: path.join(RESOURCES_PATH, 'zips/api'),
|
zipDir: path.join(RESOURCES_PATH, 'zips/api'),
|
||||||
logLevel: _dgeniLogLevel
|
logLevel: _dgeniLogLevel
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var _apiShredOptionsForDart = {
|
||||||
|
lang: 'dart',
|
||||||
|
examplesDir: path.resolve(ngPathFor('dart'), 'examples'),
|
||||||
|
fragmentsDir: path.join(DOCS_PATH, '_fragments/_api'),
|
||||||
|
zipDir: path.join(RESOURCES_PATH, 'zips/api'),
|
||||||
|
logLevel: _dgeniLogLevel
|
||||||
|
};
|
||||||
|
|
||||||
var _excludePatterns = ['**/node_modules/**', '**/typings/**', '**/packages/**'];
|
var _excludePatterns = ['**/node_modules/**', '**/typings/**', '**/packages/**'];
|
||||||
|
|
||||||
var _excludeMatchers = _excludePatterns.map(function(excludePattern){
|
var _excludeMatchers = _excludePatterns.map(function(excludePattern){
|
||||||
|
@ -96,6 +106,14 @@ var _exampleProtractorBoilerplateFiles = [
|
||||||
|
|
||||||
var _exampleConfigFilename = 'example-config.json';
|
var _exampleConfigFilename = 'example-config.json';
|
||||||
|
|
||||||
|
var lang, langs;
|
||||||
|
function configLangs(langOption) {
|
||||||
|
lang = (langOption || 'all').toLowerCase();
|
||||||
|
if (lang === 'all') { lang = '(ts|js|dart)'; }
|
||||||
|
langs = lang.match(/\w+/g); // the languages in `lang` as an array
|
||||||
|
}
|
||||||
|
configLangs(argv.lang);
|
||||||
|
|
||||||
function isDartPath(path) {
|
function isDartPath(path) {
|
||||||
// Testing via indexOf() for now. If we need to match only paths with folders
|
// Testing via indexOf() for now. If we need to match only paths with folders
|
||||||
// named 'dart' vs 'dart*' then try: path.match('/dart(/|$)') != null;
|
// named 'dart' vs 'dart*' then try: path.match('/dart(/|$)') != null;
|
||||||
|
@ -131,6 +149,7 @@ gulp.task('run-e2e-tests', runE2e);
|
||||||
* all means (ts|js|dart)
|
* all means (ts|js|dart)
|
||||||
*/
|
*/
|
||||||
function runE2e() {
|
function runE2e() {
|
||||||
|
if (!argv.lang) configLangs('ts|js'); // Exclude dart by default
|
||||||
var promise;
|
var promise;
|
||||||
if (argv.fast) {
|
if (argv.fast) {
|
||||||
// fast; skip all setup
|
// fast; skip all setup
|
||||||
|
@ -183,8 +202,6 @@ function runE2e() {
|
||||||
// each app/spec collection sequentially.
|
// each app/spec collection sequentially.
|
||||||
function findAndRunE2eTests(filter, outputFile) {
|
function findAndRunE2eTests(filter, outputFile) {
|
||||||
// create an output file with header.
|
// create an output file with header.
|
||||||
var lang = (argv.lang || '(ts|js)').toLowerCase();
|
|
||||||
if (lang === 'all') { lang = '(ts|js|dart)'; }
|
|
||||||
var startTime = new Date().getTime();
|
var startTime = new Date().getTime();
|
||||||
var header = `Doc Sample Protractor Results for ${lang} on ${new Date().toLocaleString()}\n`;
|
var header = `Doc Sample Protractor Results for ${lang} on ${new Date().toLocaleString()}\n`;
|
||||||
header += argv.fast ?
|
header += argv.fast ?
|
||||||
|
@ -528,7 +545,9 @@ gulp.task('build-docs', ['build-devguide-docs', 'build-api-docs', 'build-plunker
|
||||||
// Stop zipping examples Feb 28, 2016
|
// Stop zipping examples Feb 28, 2016
|
||||||
//gulp.task('build-docs', ['build-devguide-docs', 'build-api-docs', 'build-plunkers', '_zip-examples']);
|
//gulp.task('build-docs', ['build-devguide-docs', 'build-api-docs', 'build-plunkers', '_zip-examples']);
|
||||||
|
|
||||||
gulp.task('build-api-docs', ['build-js-api-docs', 'build-ts-api-docs', 'build-dart-cheatsheet']);
|
gulp.task('build-api-docs', ['build-js-api-docs', 'build-ts-api-docs',
|
||||||
|
// On TRAVIS? Skip building the Dart API docs for now.
|
||||||
|
...(process.env.TRAVIS ? [] : ['build-dart-api-docs'])]);
|
||||||
|
|
||||||
gulp.task('build-devguide-docs', ['_shred-devguide-examples', '_shred-devguide-shared-jade'], function() {
|
gulp.task('build-devguide-docs', ['_shred-devguide-examples', '_shred-devguide-shared-jade'], function() {
|
||||||
return buildShredMaps(true);
|
return buildShredMaps(true);
|
||||||
|
@ -542,12 +561,40 @@ gulp.task('build-js-api-docs', ['_shred-api-examples'], function() {
|
||||||
return buildApiDocs('js');
|
return buildApiDocs('js');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
gulp.task('build-dart-api-docs', ['_shred-api-examples', 'dartdoc'], function() {
|
||||||
|
// TODO(chalin): also build build-dart-cheatsheet
|
||||||
|
return buildApiDocsForDart();
|
||||||
|
});
|
||||||
|
|
||||||
gulp.task('build-plunkers', ['_copy-example-boilerplate'], function() {
|
gulp.task('build-plunkers', ['_copy-example-boilerplate'], function() {
|
||||||
return plunkerBuilder.buildPlunkers(EXAMPLES_PATH, LIVE_EXAMPLES_PATH, { errFn: gutil.log });
|
return plunkerBuilder.buildPlunkers(EXAMPLES_PATH, LIVE_EXAMPLES_PATH, { errFn: gutil.log });
|
||||||
});
|
});
|
||||||
|
|
||||||
gulp.task('build-dart-cheatsheet', [], function() {
|
gulp.task('build-dart-cheatsheet', [], function() {
|
||||||
return buildApiDocs('dart');
|
gutil.log('build-dart-cheatsheet - NOT IMPLEMENTED YET');
|
||||||
|
// return buildApiDocsForDart();
|
||||||
|
});
|
||||||
|
|
||||||
|
gulp.task('dartdoc', ['pub upgrade'], function() {
|
||||||
|
const ngRepoPath = ngPathFor('dart');
|
||||||
|
if (argv.fast && fs.existsSync(path.resolve(ngRepoPath, 'doc'))) {
|
||||||
|
gutil.log('Skipping dartdoc: --fast flag enabled and "doc" dir exists');
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
checkAngularProjectPath(ngRepoPath);
|
||||||
|
const dartdoc = spawnExt('dartdoc', ['--output', 'doc/api', '--add-crossdart'], { cwd: ngRepoPath});
|
||||||
|
return dartdoc.promise;
|
||||||
|
});
|
||||||
|
|
||||||
|
gulp.task('pub upgrade', [], function() {
|
||||||
|
const ngRepoPath = ngPathFor('dart');
|
||||||
|
if (argv.fast && fs.existsSync(path.resolve(ngRepoPath, 'packages'))) {
|
||||||
|
gutil.log('Skipping pub upgrade: --fast flag enabled and "packages" dir exists');
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
checkAngularProjectPath(ngRepoPath);
|
||||||
|
const pubUpgrade = spawnExt('pub', ['upgrade'], { cwd: ngRepoPath});
|
||||||
|
return pubUpgrade.promise;
|
||||||
});
|
});
|
||||||
|
|
||||||
gulp.task('git-changed-examples', ['_shred-devguide-examples'], function(){
|
gulp.task('git-changed-examples', ['_shred-devguide-examples'], function(){
|
||||||
|
@ -596,10 +643,35 @@ gulp.task('git-changed-examples', ['_shred-devguide-examples'], function(){
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
gulp.task('harp-compile', ['build-docs'], function() {
|
gulp.task('harp-compile', [], function() {
|
||||||
|
return harpCompile()
|
||||||
|
});
|
||||||
|
|
||||||
|
gulp.task('serve', [], function() {
|
||||||
|
// Harp will serve files from workspace.
|
||||||
|
const cmd = 'npm run harp -- server .';
|
||||||
|
gutil.log('Launching harp server (over project files)');
|
||||||
|
gutil.log(` > ${cmd}`);
|
||||||
|
gutil.log('Note: issuing this command directly from the command line will show harp comiple warnings.');
|
||||||
|
return execPromise(cmd);
|
||||||
|
});
|
||||||
|
|
||||||
|
gulp.task('serve-www', [], function() {
|
||||||
|
// Serve generated site.
|
||||||
|
return execPromise('npm run live-server ./www');
|
||||||
|
});
|
||||||
|
|
||||||
|
gulp.task('build-compile', ['build-docs'], function() {
|
||||||
return harpCompile();
|
return harpCompile();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
gulp.task('check-serve', ['build-docs'], function() {
|
||||||
|
return harpCompile().then(function() {
|
||||||
|
gutil.log('Launching live-server over ./www');
|
||||||
|
return execPromise('npm run live-server ./www');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
gulp.task('check-deploy', ['build-docs'], function() {
|
gulp.task('check-deploy', ['build-docs'], function() {
|
||||||
return harpCompile().then(function() {
|
return harpCompile().then(function() {
|
||||||
gutil.log('compile ok');
|
gutil.log('compile ok');
|
||||||
|
@ -693,8 +765,15 @@ gulp.task('_shred-clean-devguide', function(cb) {
|
||||||
});
|
});
|
||||||
|
|
||||||
gulp.task('_shred-api-examples', ['_shred-clean-api'], function() {
|
gulp.task('_shred-api-examples', ['_shred-clean-api'], function() {
|
||||||
checkAngularProjectPath();
|
const promises = [];
|
||||||
return docShredder.shred(_apiShredOptions);
|
gutil.log('Shredding API examples for languages: ' + langs.join(', '));
|
||||||
|
langs.forEach((lang) => {
|
||||||
|
if (lang === 'js') return; // JS is handled via TS.
|
||||||
|
checkAngularProjectPath(ngPathFor(lang));
|
||||||
|
const options = lang == 'dart' ? _apiShredOptionsForDart : _apiShredOptions;
|
||||||
|
promises.push(docShredder.shred(options));
|
||||||
|
});
|
||||||
|
return Q.all(promises);
|
||||||
});
|
});
|
||||||
|
|
||||||
gulp.task('_shred-clean-api', function(cb) {
|
gulp.task('_shred-clean-api', function(cb) {
|
||||||
|
@ -1087,8 +1166,8 @@ function buildApiDocs(targetLanguage) {
|
||||||
var dgeni = new Dgeni([package]);
|
var dgeni = new Dgeni([package]);
|
||||||
return dgeni.generate();
|
return dgeni.generate();
|
||||||
} catch(err) {
|
} catch(err) {
|
||||||
gutil.log(err);
|
console.error(err);
|
||||||
gutil.log(err.stack);
|
console.error(err.stack);
|
||||||
throw err;
|
throw err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1099,6 +1178,48 @@ function buildApiDocs(targetLanguage) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function buildApiDocsForDart() {
|
||||||
|
const apiDir = 'api';
|
||||||
|
const vers = 'latest';
|
||||||
|
const dab = require('./tools/dart-api-builder/dab')(ANGULAR_IO_PROJECT_PATH);
|
||||||
|
const log = dab.log;
|
||||||
|
|
||||||
|
log.level = _dgeniLogLevel;
|
||||||
|
const dabInfo = dab.dartPkgConfigInfo;
|
||||||
|
dabInfo.ngIoDartApiDocPath = path.join(DOCS_PATH, 'dart', vers, apiDir);
|
||||||
|
dabInfo.ngDartDocPath = path.join(ngPathFor('dart'), 'doc', apiDir);
|
||||||
|
// Exclude API entries for developer/internal libraries. Also exclude entries for
|
||||||
|
// the top-level catch all "angular2" library (otherwise every entry appears twice).
|
||||||
|
dabInfo.excludeLibRegExp = new RegExp(/^(?!angular2)|\.testing|_|codegen|^angular2$/);
|
||||||
|
|
||||||
|
try {
|
||||||
|
checkAngularProjectPath('dart');
|
||||||
|
var destPath = dabInfo.ngIoDartApiDocPath;
|
||||||
|
var sourceDirs = fs.readdirSync(dabInfo.ngDartDocPath)
|
||||||
|
.filter((name) => !name.match(/^index/))
|
||||||
|
.map((name) => path.join(dabInfo.ngDartDocPath, name));
|
||||||
|
log.info(`Building Dart API pages for ${sourceDirs.length} libraries`);
|
||||||
|
|
||||||
|
return copyFiles(sourceDirs, [destPath]).then(() => {
|
||||||
|
log.debug('Finished copying', sourceDirs.length, 'directories from', dabInfo.ngDartDocPath, 'to', destPath);
|
||||||
|
|
||||||
|
const apiEntries = dab.loadApiDataAndSaveToApiListFile();
|
||||||
|
const tmpDocsPath = path.resolve(path.join(process.env.HOME, 'tmp/docs.json'));
|
||||||
|
if (argv.dumpDocsJson) fs.writeFileSync(tmpDocsPath, JSON.stringify(apiEntries, null, 2));
|
||||||
|
dab.createApiDataAndJadeFiles(apiEntries);
|
||||||
|
|
||||||
|
}).catch((err) => {
|
||||||
|
console.log(err);
|
||||||
|
});
|
||||||
|
|
||||||
|
} catch(err) {
|
||||||
|
console.error(err);
|
||||||
|
console.error(err.stack);
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function buildShredMaps(shouldWrite) {
|
function buildShredMaps(shouldWrite) {
|
||||||
var options = {
|
var options = {
|
||||||
devguideExamplesDir: _devguideShredOptions.examplesDir,
|
devguideExamplesDir: _devguideShredOptions.examplesDir,
|
||||||
|
@ -1270,8 +1391,13 @@ function execCommands(cmds, options, cb) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkAngularProjectPath() {
|
function ngPathFor(lang) {
|
||||||
if (!fs.existsSync(ANGULAR_PROJECT_PATH)) {
|
return ANGULAR_PROJECT_PATH + (lang === 'dart' ? '-dart' : '');
|
||||||
throw new Error('API related tasks require the angular2 repo to be at ' + path.resolve(ANGULAR_PROJECT_PATH));
|
}
|
||||||
|
|
||||||
|
function checkAngularProjectPath(lang) {
|
||||||
|
var ngPath = path.resolve(ngPathFor(lang || 'ts'));
|
||||||
|
if (!fs.existsSync(ngPath)) {
|
||||||
|
throw new Error('API related tasks require the angular2 repo to be at ' + ngPath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
"broken-link-checker": "0.7.1",
|
"broken-link-checker": "0.7.1",
|
||||||
"browser-sync": "^2.9.3",
|
"browser-sync": "^2.9.3",
|
||||||
"canonical-path": "0.0.2",
|
"canonical-path": "0.0.2",
|
||||||
|
"cheerio": "^0.20.0",
|
||||||
"cross-spawn": "^4.0.0",
|
"cross-spawn": "^4.0.0",
|
||||||
"codelyzer": "0.0.22",
|
"codelyzer": "0.0.22",
|
||||||
"del": "^2.2.0",
|
"del": "^2.2.0",
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
// Refer to jade.template.html and addJadeDataDocsProcessor to figure out where the context of this jade file originates
|
// template: public/_includes/_hero
|
||||||
|
//- Refer to jade.template.html and addJadeDataDocsProcessor to figure out where the context of this jade file originates
|
||||||
- var textFormat = '';
|
- var textFormat = '';
|
||||||
- var headerTitle = title + (typeof varType !== 'undefined' ? (': ' + varType) : '');
|
- var headerTitle = title + (typeof varType !== 'undefined' ? (': ' + varType) : '');
|
||||||
- var capitalize = function capitalize(str) { return str.charAt(0).toUpperCase() + str.slice(1); }
|
- var capitalize = function capitalize(str) { return str.charAt(0).toUpperCase() + str.slice(1); }
|
||||||
- var useBadges = docType || stability;
|
- var useBadges = docType || stability;
|
||||||
|
//- renamer :: String -> String
|
||||||
// renamer :: String -> String
|
//- Renames `Let` and `Var` into `Const`
|
||||||
// Renames `Let` and `Var` into `Const`
|
|
||||||
- var renamer = function renamer(docType) {
|
- var renamer = function renamer(docType) {
|
||||||
- return (docType === 'Let' || docType === 'Var') ? 'Const' : docType
|
- return (docType === 'Let' || docType === 'Var') ? 'Const' : docType
|
||||||
- }
|
- }
|
||||||
|
@ -13,7 +13,7 @@
|
||||||
if current.path[4] && current.path[3] == 'api'
|
if current.path[4] && current.path[3] == 'api'
|
||||||
- var textFormat = 'is-standard-case'
|
- var textFormat = 'is-standard-case'
|
||||||
|
|
||||||
header(class="hero background-sky")
|
header(class="hero background-sky", style=fixHeroCss ? "height:auto" : "")
|
||||||
div(class="inner-header")
|
div(class="inner-header")
|
||||||
h1(class="hero-title text-display-1 #{textFormat}") #{headerTitle}
|
h1(class="hero-title text-display-1 #{textFormat}") #{headerTitle}
|
||||||
if useBadges
|
if useBadges
|
||||||
|
@ -33,5 +33,7 @@ header(class="hero background-sky")
|
||||||
if subtitle
|
if subtitle
|
||||||
h2.hero-subtitle.text-subhead #{subtitle}
|
h2.hero-subtitle.text-subhead #{subtitle}
|
||||||
|
|
||||||
|
else if current.path[3] == 'api' && current.path[1] == 'dart'
|
||||||
|
block breadcrumbs
|
||||||
else if current.path[0] == "docs"
|
else if current.path[0] == "docs"
|
||||||
!= partial("_version-dropdown")
|
!= partial("_version-dropdown")
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
//- WARNING: _layout.jade and _layout-dart-api.jade should match in terms of content
|
||||||
|
//- except that one uses Harp partial/yield and the other uses Jade extends/include.
|
||||||
|
doctype
|
||||||
|
html(lang="en" ng-app="angularIOApp" itemscope itemtype="http://schema.org/Framework")
|
||||||
|
// template: public/docs/_layout-dart-api
|
||||||
|
head
|
||||||
|
include ../_includes/_head-include
|
||||||
|
block head-extra
|
||||||
|
|
||||||
|
block var-def
|
||||||
|
body(class="l-offset-nav l-offset-side-nav" ng-controller="AppCtrl as appCtrl")
|
||||||
|
include ../_includes/_main-nav
|
||||||
|
if current.path[2]
|
||||||
|
include _includes/_side-nav
|
||||||
|
include ../_includes/_hero
|
||||||
|
include ../_includes/_banner
|
||||||
|
|
||||||
|
if current.path[3] == 'api'
|
||||||
|
if current.path[4] == 'index'
|
||||||
|
block main-content
|
||||||
|
else
|
||||||
|
article(class="l-content-small grid-fluid docs-content")
|
||||||
|
block main-content
|
||||||
|
else if current.path.indexOf('cheatsheet') > 0
|
||||||
|
block main-content
|
||||||
|
else
|
||||||
|
if current.path[3] == 'index' || current.path[3] == 'styleguide'
|
||||||
|
article(class="l-content-small grid-fluid docs-content")
|
||||||
|
block main-content
|
||||||
|
else
|
||||||
|
article(class="l-content-small grid-fluid docs-content")
|
||||||
|
div(class="c10")
|
||||||
|
.showcase
|
||||||
|
.showcase-content
|
||||||
|
block main-content
|
||||||
|
if (current.path[3] == 'guide' || current.path[3] == 'tutorial') && current.path[4]
|
||||||
|
include ../_includes/_next-item
|
||||||
|
|
||||||
|
include ../_includes/_footer
|
||||||
|
include ../_includes/_scripts-include
|
|
@ -1,8 +1,13 @@
|
||||||
|
//- WARNING: _layout.jade and _layout-dart-api.jade should match in terms of content
|
||||||
|
//- except that one uses Harp partial/yield and the other uses Jade extends/include.
|
||||||
doctype
|
doctype
|
||||||
html(lang="en" ng-app="angularIOApp" itemscope itemtype="http://schema.org/Framework")
|
html(lang="en" ng-app="angularIOApp" itemscope itemtype="http://schema.org/Framework")
|
||||||
|
// template: public/docs/_layout
|
||||||
head
|
head
|
||||||
!= partial("../_includes/_head-include")
|
!= partial("../_includes/_head-include")
|
||||||
|
block head-extra
|
||||||
|
|
||||||
|
//-
|
||||||
body(class="l-offset-nav l-offset-side-nav" ng-controller="AppCtrl as appCtrl")
|
body(class="l-offset-nav l-offset-side-nav" ng-controller="AppCtrl as appCtrl")
|
||||||
!= partial("../_includes/_main-nav")
|
!= partial("../_includes/_main-nav")
|
||||||
if current.path[2]
|
if current.path[2]
|
||||||
|
|
|
@ -1,10 +1,13 @@
|
||||||
.l-main-section
|
:marked
|
||||||
h2 Beta
|
> **WARNING:** API documentation is preliminary and subject to change.
|
||||||
|
|
||||||
p.
|
> **Known issues:** Although this generated API reference displays Dart
|
||||||
The proposed Angular 2 API does not yet have Dart-specific documentation.
|
APIs, individual pages sometimes describe TypeScript APIs accompanied with
|
||||||
However, because the Dart and JavaScript APIs are generated from the same source,
|
TypeScript code. The angular.io issue tracker contains [all known
|
||||||
you might find the JavaScript API docs helpful:
|
issues][api-issues]; if you notice others, please [report
|
||||||
|
them][new-issue]. Thanks!
|
||||||
|
|
||||||
p.text-center
|
[new-issue]: https://github.com/angular/angular.io/issues/new?labels=dart,api&title=%5BDart%5D%5BAPI%5D%20
|
||||||
<b><a href="/docs/js/latest/api/">Angular 2 API Preview (JavaScript)</a></b>
|
[api-issues]: https://github.com/angular/angular.io/issues?q=label%3Aapi+label%3Adart
|
||||||
|
|
||||||
|
api-list(src="api-list.json" lang="dart")
|
||||||
|
|
|
@ -26,6 +26,8 @@ angularIO.directive('apiList', function () {
|
||||||
controller: function($scope, $attrs, $http, $location) {
|
controller: function($scope, $attrs, $http, $location) {
|
||||||
var $ctrl = this;
|
var $ctrl = this;
|
||||||
|
|
||||||
|
var isForDart = $attrs.lang === 'dart';
|
||||||
|
|
||||||
$ctrl.apiTypes = [
|
$ctrl.apiTypes = [
|
||||||
{ cssClass: 'stable', title: 'Stable', matches: ['stable']},
|
{ cssClass: 'stable', title: 'Stable', matches: ['stable']},
|
||||||
{ cssClass: 'directive', title: 'Directive', matches: ['directive'] },
|
{ cssClass: 'directive', title: 'Directive', matches: ['directive'] },
|
||||||
|
@ -37,6 +39,9 @@ angularIO.directive('apiList', function () {
|
||||||
{ cssClass: 'const', title: 'Const', matches: ['var', 'let', 'const'] }
|
{ cssClass: 'const', title: 'Const', matches: ['var', 'let', 'const'] }
|
||||||
];
|
];
|
||||||
|
|
||||||
|
if (isForDart) $ctrl.apiTypes = $ctrl.apiTypes.filter((t) =>
|
||||||
|
!t.cssClass.match(/^(stable|directive|decorator|interface|enum)$/));
|
||||||
|
|
||||||
$ctrl.apiFilter = getApiFilterFromLocation();
|
$ctrl.apiFilter = getApiFilterFromLocation();
|
||||||
$ctrl.apiType = getApiTypeFromLocation();
|
$ctrl.apiType = getApiTypeFromLocation();
|
||||||
$ctrl.groupedSections = [];
|
$ctrl.groupedSections = [];
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -e -o pipefail
|
||||||
|
|
||||||
|
TARGET=node_modules/terraform/lib/helpers/raw.js
|
||||||
|
|
||||||
|
# Around line 282 change from/to:
|
||||||
|
# var namespace = sourcePath.split(".")[0].split("/")
|
||||||
|
# var namespace = sourcePath.split('.').slice(0, -1).join('.').split('/')
|
||||||
|
|
||||||
|
if [ -e "$TARGET" ]; then
|
||||||
|
perl -i.bak -pe 's/^(\s+var namespace.*split\("."\))\[0\]/\1.slice(0, -1).join(".")/' "$TARGET"
|
||||||
|
echo "Patched '$TARGET'."
|
||||||
|
else
|
||||||
|
echo "Nothing to patch. Can't find file '$TARGET'."
|
||||||
|
exit 1;
|
||||||
|
fi
|
|
@ -0,0 +1,18 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var Package = require('dgeni').Package;
|
||||||
|
var path = require('canonical-path');
|
||||||
|
|
||||||
|
module.exports = new Package('dart', [])
|
||||||
|
|
||||||
|
.factory(require('./services/apiListDataFileService'))
|
||||||
|
.factory(require('./services/arrayFromIterable'))
|
||||||
|
.factory(require('./services/dartPkgConfigInfo'))
|
||||||
|
.factory(require('./services/logFactory'))
|
||||||
|
.factory(require('./services/preprocessDartDocData'))
|
||||||
|
|
||||||
|
// Register the processors
|
||||||
|
.processor(require('./processors/loadDartDocData'))
|
||||||
|
// .processor(require('./processors/createApiListData'))
|
||||||
|
// .processor(require('./processors/loadDartDocHtml'))
|
||||||
|
;
|
|
@ -0,0 +1,21 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
const path = require('canonical-path');
|
||||||
|
|
||||||
|
module.exports = function loadDartDocDataProcessor(log, dartPkgConfigInfo, preprocessDartDocData) {
|
||||||
|
return {
|
||||||
|
// $runAfter: ['reading-docs'],
|
||||||
|
// $runBefore: ['docs-read'],
|
||||||
|
|
||||||
|
$process: function (docs) {
|
||||||
|
if (docs.length != 0) log.error('Expected docs array to be nonempty.');
|
||||||
|
|
||||||
|
const dataFilePath = path.resolve(dartPkgConfigInfo.ngDartDocPath, 'index.json');
|
||||||
|
const dartDocData = require(dataFilePath);
|
||||||
|
log.info('Loaded', dartDocData.length, 'dartdoc api entries from', dataFilePath);
|
||||||
|
|
||||||
|
preprocessDartDocData.preprocess(dartDocData);
|
||||||
|
docs.push(...dartDocData);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
|
@ -0,0 +1,45 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var path = require('canonical-path');
|
||||||
|
var fs = require("q-io/fs");
|
||||||
|
var q = require('q');
|
||||||
|
var cheerio = require('cheerio');
|
||||||
|
|
||||||
|
// Original sample file by @petebacondarwin
|
||||||
|
// Not currently used, but keeping it for now,
|
||||||
|
// until we completely rule out use of dgeni.
|
||||||
|
|
||||||
|
module.exports = function loadDartDocHtmlProcessor(log, dartPkgConfigInfo) {
|
||||||
|
return {
|
||||||
|
$runAfter: ['loadDartDocDataProcessor'],
|
||||||
|
// $runBefore: ['docs-read'],
|
||||||
|
|
||||||
|
$process: function (docs) {
|
||||||
|
var ngIoDartApiDocPath = dartPkgConfigInfo.ngIoDartApiDocPath;
|
||||||
|
|
||||||
|
// Return a promise sync we are async in here
|
||||||
|
return q.all(docs.map(function (doc) {
|
||||||
|
if (doc.kind.match(/-dart-api$/)) return;
|
||||||
|
|
||||||
|
// Load up the HTML and extract the contents of the body
|
||||||
|
var htmlPath = path.resolve(ngIoDartApiDocPath, doc.href);
|
||||||
|
|
||||||
|
return fs.exists(htmlPath).then(function (exists) {
|
||||||
|
|
||||||
|
if (!exists) {
|
||||||
|
log.debug('missing html ' + htmlPath);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
return fs.read().then(function (html) {
|
||||||
|
log.info('Reading ' + htmlPath)
|
||||||
|
var $ = cheerio.load(html);
|
||||||
|
doc.htmlContent = $('body').contents().html();
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
|
@ -0,0 +1,76 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
const assert = require('assert-plus');
|
||||||
|
const fs = require('fs-extra');
|
||||||
|
const path = require('canonical-path');
|
||||||
|
const Array_from = require('./arrayFromIterable');
|
||||||
|
|
||||||
|
module.exports = function apiListDataFileService(log, dartPkgConfigInfo) {
|
||||||
|
|
||||||
|
const _self = {
|
||||||
|
|
||||||
|
mainDataFileName: 'api-list.json',
|
||||||
|
mainDataFilePath: null,
|
||||||
|
|
||||||
|
libToEntryMap: null,
|
||||||
|
containerToEntryMap: null,
|
||||||
|
numExcludedEntries: 0,
|
||||||
|
|
||||||
|
createDataAndSaveToFile: function (dartDocDataWithExtraProps) {
|
||||||
|
const libToEntryMap = _self.libToEntryMap = new Map();
|
||||||
|
const containerToEntryMap = _self.containerToEntryMap = new Map();
|
||||||
|
const re = dartPkgConfigInfo.excludeLibRegExp;
|
||||||
|
|
||||||
|
// Populate the two maps from dartDocDataWithExtraProps.
|
||||||
|
dartDocDataWithExtraProps.forEach((e) => {
|
||||||
|
// Skip non-preprocessed entries.
|
||||||
|
if (!e.kind) return true;
|
||||||
|
|
||||||
|
// Exclude non-public APIs.
|
||||||
|
if (e.libName.match(re)) { _self.numExcludedEntries++; return true; }
|
||||||
|
|
||||||
|
let key;
|
||||||
|
if (e.kind.startsWith('entry')) {
|
||||||
|
// Store library entry info in lib map.
|
||||||
|
key = e.libName;
|
||||||
|
assert.equal(key, e.enclosedByQualifiedName, e);
|
||||||
|
_set(libToEntryMap, key, e);
|
||||||
|
} else if (e.enclosedBy) {
|
||||||
|
assert.notEqual(e.type, 'library');
|
||||||
|
key = e.enclosedByQualifiedName;
|
||||||
|
} else {
|
||||||
|
assert.equal(e.type, 'library');
|
||||||
|
// Add library "index" page to the library's entries in the general container map,
|
||||||
|
// but not the lib map which is used to create the main API page index.
|
||||||
|
key = e.libName;
|
||||||
|
_set(containerToEntryMap, key, e);
|
||||||
|
// Add the library as an entry to the Angular2 package container:
|
||||||
|
key = '';
|
||||||
|
}
|
||||||
|
_set(containerToEntryMap, key, e);
|
||||||
|
});
|
||||||
|
log.info('Excluded', _self.numExcludedEntries, 'library entries (regexp match).');
|
||||||
|
|
||||||
|
// Write the library map out as the top-level data file.
|
||||||
|
_self.mainDataFilePath = path.resolve(path.join(dartPkgConfigInfo.ngIoDartApiDocPath, _self.mainDataFileName));
|
||||||
|
|
||||||
|
// The data file needs to be a map of lib names to an array of entries
|
||||||
|
const fileData = Object.create(null);
|
||||||
|
for (let name of Array_from(libToEntryMap.keys()).sort()) {
|
||||||
|
fileData[name] = Array_from(libToEntryMap.get(name).values());
|
||||||
|
}
|
||||||
|
fs.writeFileSync(_self.mainDataFilePath, JSON.stringify(fileData, null, 2));
|
||||||
|
log.info('Wrote', Object.keys(fileData).length, 'library entries to', _self.mainDataFilePath);
|
||||||
|
return fileData;
|
||||||
|
},
|
||||||
|
|
||||||
|
}
|
||||||
|
return _self;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Adds e to the map of m[key].
|
||||||
|
function _set(m, key, e) {
|
||||||
|
if (!m.has(key)) m.set(key, new Map());
|
||||||
|
const entryMap = m.get(key);
|
||||||
|
entryMap.set(e.name, e);
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
module.exports = function arrayFromIterable(iterable) {
|
||||||
|
const arr = [];
|
||||||
|
for (let e of iterable) arr.push(e);
|
||||||
|
return arr;
|
||||||
|
};
|
|
@ -0,0 +1,13 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {Object} The Dart package config information
|
||||||
|
*/
|
||||||
|
module.exports = function dartPkgConfigInfo() {
|
||||||
|
const _self = {
|
||||||
|
ngIoDartApiDocPath: 'ngIoDartApiDocPath is uninitialized',
|
||||||
|
ngDartDocPath: 'ngDartDocPath is uninitialized',
|
||||||
|
excludeLibRegExp: null,
|
||||||
|
};
|
||||||
|
return _self;
|
||||||
|
};
|
|
@ -0,0 +1,8 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
module.exports = function logFactory() {
|
||||||
|
var winston = require('winston');
|
||||||
|
winston.cli();
|
||||||
|
winston.level = 'info';
|
||||||
|
return winston;
|
||||||
|
};
|
|
@ -0,0 +1,81 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
const assert = require('assert-plus');
|
||||||
|
const path = require('canonical-path');
|
||||||
|
const fs = require('fs-extra');
|
||||||
|
|
||||||
|
module.exports = function preprocessDartDocData(log, dartPkgConfigInfo) {
|
||||||
|
|
||||||
|
const _self = {
|
||||||
|
|
||||||
|
entryMap: null,
|
||||||
|
|
||||||
|
preprocess: function (dartDocData) {
|
||||||
|
// List of API entities
|
||||||
|
let entryMap = _self.entryMap = new Map(); // used to remove duplicates
|
||||||
|
let numDuplicates = 0;
|
||||||
|
|
||||||
|
dartDocData
|
||||||
|
.forEach((e) => {
|
||||||
|
if (entryMap.has(e.href)) {
|
||||||
|
log.debug('Dartdoc preprocessor: duplicate entry for', e.href);
|
||||||
|
numDuplicates++;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// Sample entry (note that enclosedBy is optional):
|
||||||
|
// {
|
||||||
|
// "name": "Pipe",
|
||||||
|
// "qualifiedName": "angular2.core.Pipe",
|
||||||
|
// "href": "angular2.core/Pipe-class.html",
|
||||||
|
// "type": "class",
|
||||||
|
// "enclosedBy": {
|
||||||
|
// "name": "angular2.core",
|
||||||
|
// "type": "library"
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Save original type property since it will be overridden.
|
||||||
|
e.origDartDocType = e.type;
|
||||||
|
const name = e.name;
|
||||||
|
const qualifiedName = e.qualifiedName;
|
||||||
|
const matches = e.href.match(/-([a-z]+)\.html/);
|
||||||
|
let type = matches ? (e.typeFromHref = matches[1]) : e.type;
|
||||||
|
// Conform to TS type names for now.
|
||||||
|
if (type === 'constant') type = 'let';
|
||||||
|
|
||||||
|
let libName;
|
||||||
|
e.enclosedByQualifiedName = path.dirname(e.href);
|
||||||
|
if (e.enclosedBy && e.enclosedBy.type === 'library') {
|
||||||
|
e.kind = 'entry-dart-api';
|
||||||
|
libName = e.enclosedBy.name;
|
||||||
|
assert.equal(libName, e.enclosedByQualifiedName, e.kind);
|
||||||
|
} else if (e.origDartDocType === 'library') {
|
||||||
|
e.kind = 'library-dart-api';
|
||||||
|
libName = e.name;
|
||||||
|
e.enclosedByQualifiedName = ''; // Dart libraries can only be at the top level.
|
||||||
|
} else {
|
||||||
|
e.kind = 'subentry-dart-api';
|
||||||
|
libName = e.enclosedByQualifiedName.split('/')[0];
|
||||||
|
assert.equal(path.join(libName, e.enclosedBy.name), e.enclosedByQualifiedName, e);
|
||||||
|
}
|
||||||
|
e.docType = type;
|
||||||
|
e.libName = libName;
|
||||||
|
e.path = e.href;
|
||||||
|
e.title = name;
|
||||||
|
e.layout = false; // To prevent public/docs/_layout.jade from be applied to Dart API pages
|
||||||
|
// Also set above:
|
||||||
|
// e.kind: one of {library,entry,subentry}-dart-api
|
||||||
|
// e.enclosedByQualifiedName
|
||||||
|
// e.origDartDocType
|
||||||
|
// e.typeFromHref
|
||||||
|
Object.freeze(e);
|
||||||
|
entryMap.set(e.path, e);
|
||||||
|
log.silly('Preproc API entity =', JSON.stringify(e, null, 2));
|
||||||
|
});
|
||||||
|
// There shouldn't be duplicates (hence the warning), but there are:
|
||||||
|
// https://github.com/dart-lang/dartdoc/issues/1197
|
||||||
|
if (numDuplicates) log.warn('Number of duplicate dartdoc entries', numDuplicates);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
return _self;
|
||||||
|
};
|
|
@ -0,0 +1,26 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
// This file is likely outdated.
|
||||||
|
// To run, cd to this dir and
|
||||||
|
// node test.js
|
||||||
|
|
||||||
|
const path = require('canonical-path');
|
||||||
|
const Dgeni = require('dgeni');
|
||||||
|
const dartPkg = require(path.resolve('.'));
|
||||||
|
|
||||||
|
const ANGULAR_IO_PROJECT_PATH = '../../..';
|
||||||
|
const DOCS_PATH = path.join(ANGULAR_IO_PROJECT_PATH, 'public/docs');
|
||||||
|
const apiDocPath = path.join(DOCS_PATH, 'dart/latest/api');
|
||||||
|
|
||||||
|
dartPkg.config(function (dartPkgConfigInfo) {
|
||||||
|
dartPkgConfigInfo.ngIoDartApiDocPath = apiDocPath;
|
||||||
|
dartPkgConfigInfo.ngDartDocPath = path.join(ANGULAR_IO_PROJECT_PATH, '../ngdart/doc/api');
|
||||||
|
});
|
||||||
|
|
||||||
|
const dgeni = new Dgeni([dartPkg]);
|
||||||
|
|
||||||
|
dgeni.generate().catch(function (err) {
|
||||||
|
console.log(err);
|
||||||
|
console.log(err.stack);
|
||||||
|
throw err;
|
||||||
|
});
|
|
@ -0,0 +1,215 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
const assert = require('assert-plus');
|
||||||
|
const cheerio = require('cheerio');
|
||||||
|
const Encoder = require('node-html-encoder').Encoder;
|
||||||
|
const fs = require('fs-extra');
|
||||||
|
const path = require('canonical-path');
|
||||||
|
|
||||||
|
module.exports = function dabFactory(ngIoProjPath) {
|
||||||
|
const encoder = new Encoder('entity');
|
||||||
|
|
||||||
|
// Get the functionality we need from the dgeni package by the same name.
|
||||||
|
const dartApiBuilderDgeniProjPath = 'tools/api-builder/dart-package';
|
||||||
|
const dab = require(path.resolve(ngIoProjPath, dartApiBuilderDgeniProjPath)).module;
|
||||||
|
|
||||||
|
const log = dab.logFactory[1]();
|
||||||
|
const dartPkgConfigInfo = dab.dartPkgConfigInfo[1]();
|
||||||
|
const preprocessDartDocData = dab.preprocessDartDocData[1](log, dartPkgConfigInfo);
|
||||||
|
const loadDartDocDataProcessor = dab.loadDartDocDataProcessor[1](log, dartPkgConfigInfo, preprocessDartDocData);
|
||||||
|
const apiListDataFileService = dab.apiListDataFileService[1](log, dartPkgConfigInfo);
|
||||||
|
const Array_from = dab.arrayFromIterable[1];
|
||||||
|
|
||||||
|
// Load API data, then create and save 'api-list.json'.
|
||||||
|
function loadApiDataAndSaveToApiListFile() {
|
||||||
|
const docs = [];
|
||||||
|
loadDartDocDataProcessor.$process(docs);
|
||||||
|
log.debug('Number of Dart API entries loaded:', docs.length);
|
||||||
|
var libMap = apiListDataFileService.createDataAndSaveToFile(docs);
|
||||||
|
for (let name in libMap) {
|
||||||
|
log.debug(' ', name, 'has', libMap[name].length, 'top-level entries');
|
||||||
|
}
|
||||||
|
return docs;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create and save the container's '_data.json' file.
|
||||||
|
function _createDirData(containerName, destDirPath, entries) {
|
||||||
|
const entryNames = Array_from(entries.keys()).sort();
|
||||||
|
const dataMap = Object.create(null);
|
||||||
|
entryNames.map((n) => {
|
||||||
|
const e = entries.get(n);
|
||||||
|
assert.object(e, `entry named ${n}`);
|
||||||
|
dataMap[path.basename(e.path, '.html')] = e;
|
||||||
|
});
|
||||||
|
const dataFilePath = path.resolve(destDirPath, '_data.json');
|
||||||
|
fs.writeFile(dataFilePath, JSON.stringify(dataMap, null, 2));
|
||||||
|
log.info(containerName, 'wrote', Object.keys(dataMap).length, 'entries to', dataFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
function _insertExampleFragments(enclosedByName, eltId, $, div) {
|
||||||
|
const fragDir = path.join(dartPkgConfigInfo.ngIoDartApiDocPath, '../../../_fragments/_api');
|
||||||
|
const exList = div.find('p:contains("{@example")');
|
||||||
|
exList.each((i, elt) => {
|
||||||
|
const text = $(elt).text();
|
||||||
|
log.debug(`Found example: ${enclosedByName} ${eltId}`, text);
|
||||||
|
const matches = text.match(/{@example\s+([^\s]+)(\s+region=[\'\"]?(\w+)[\'\"]?)?\s*}/);
|
||||||
|
if (!matches) {
|
||||||
|
log.warn(enclosedByName, eltId, 'has an invalidly formed @example tag:', text);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
const exRelPath = matches[1];
|
||||||
|
const region = matches[3];
|
||||||
|
|
||||||
|
const dir = path.dirname(exRelPath)
|
||||||
|
const extn = path.extname(exRelPath);
|
||||||
|
const baseName = path.basename(exRelPath, extn);
|
||||||
|
const fileNameNoExt = baseName + (region ? `-${region}` : '')
|
||||||
|
const exFragPath = path.resolve(fragDir, dir, `${fileNameNoExt}${extn}.md`);
|
||||||
|
if (!fs.existsSync(exFragPath)) {
|
||||||
|
log.warn('Fragment not found:', exFragPath);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
$(elt).empty();
|
||||||
|
const md = fs.readFileSync(exFragPath, 'utf8');
|
||||||
|
const codeElt = _extractAndWrapInCodeTags(md);
|
||||||
|
$(elt).html(codeElt);
|
||||||
|
log.silly('Fragment code in html:', $(elt).html());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function _extractAndWrapInCodeTags(md) {
|
||||||
|
const lines = md.split('\n');
|
||||||
|
// Drop first and last lines that are the code markdown tripple ticks (and last \n):
|
||||||
|
lines.shift(); lines.pop(); lines.pop();
|
||||||
|
const code = lines.map((line) => encoder.htmlEncode(line)).join('\n');
|
||||||
|
// TS uses format="linenums"; removing that for now.
|
||||||
|
return `<code-example language="dart">${code}\n</code-example>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function _createEntryJadeFile(e, destDirPath) {
|
||||||
|
const htmlPagePath = path.resolve(dartPkgConfigInfo.ngDartDocPath, e.path);
|
||||||
|
if (!fs.existsSync(htmlPagePath)) {
|
||||||
|
log.warn('Entry', e.name, ': expected to find file but didn\'t', htmlPagePath);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const html = fs.readFileSync(htmlPagePath, 'utf8');
|
||||||
|
log.debug('Reading (and then deleting)', html.length, 'chars from', htmlPagePath);
|
||||||
|
const $ = cheerio.load(html);
|
||||||
|
const div = $('div.body.container');
|
||||||
|
$('div.sidebar-offcanvas-left').remove();
|
||||||
|
const baseNameNoExtn = path.basename(e.path, '.html');
|
||||||
|
_insertExampleFragments(e.enclosedByQualifiedName, baseNameNoExtn, $, div);
|
||||||
|
|
||||||
|
const outFileNoExtn = path.join(destDirPath, baseNameNoExtn);
|
||||||
|
const depth = path.dirname(e.path).split('/').length;
|
||||||
|
assert(depth === 1 || depth == 2, 'depth ' + depth);
|
||||||
|
const jadeFilePath = path.resolve(outFileNoExtn + '.jade');
|
||||||
|
const breadcrumbs = $('header > nav ol.breadcrumbs');
|
||||||
|
fs.writeFileSync(jadeFilePath, apiEntryJadeTemplate(depth, breadcrumbs, div));
|
||||||
|
// In case harp cached the .html version, remove it since it will be generated.
|
||||||
|
try {
|
||||||
|
fs.unlinkSync(path.resolve(outFileNoExtn + '.html'));
|
||||||
|
} catch (err) {
|
||||||
|
if (e.enclosedBy && e.enclosedBy.type === 'class' &&
|
||||||
|
e.enclosedBy.name.toLowerCase() === e.name.toLowerCase()) {
|
||||||
|
// Do nothing since this is a known bug with dartdoc:
|
||||||
|
// https://github.com/dart-lang/dartdoc/issues/1196
|
||||||
|
} else {
|
||||||
|
console.error(err);
|
||||||
|
console.error(`Output path: ${destDirPath}`);
|
||||||
|
console.error(`Entity: ${e}`);
|
||||||
|
console.error(err.stack);
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
log.debug(' ', e.enclosedByQualifiedName, 'entry', e.name, 'wrote to ', jadeFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
function _createJadeFiles(containerName, destDirPath, entries) {
|
||||||
|
let numApiPagesWritten = 0;
|
||||||
|
for (let name of entries.keys()) {
|
||||||
|
_createEntryJadeFile(entries.get(name), destDirPath);
|
||||||
|
numApiPagesWritten++
|
||||||
|
}
|
||||||
|
log.info(containerName, 'created', numApiPagesWritten, 'Jade entry files.');
|
||||||
|
return numApiPagesWritten;
|
||||||
|
}
|
||||||
|
|
||||||
|
function createApiDataAndJadeFiles(docs) {
|
||||||
|
let numApiPagesWritten = 0;
|
||||||
|
let map = apiListDataFileService.containerToEntryMap;
|
||||||
|
for (let name of map.keys()) {
|
||||||
|
if (!name) continue; // skip package-level
|
||||||
|
let destDirPath = path.resolve(dartPkgConfigInfo.ngIoDartApiDocPath, name);
|
||||||
|
let entries;
|
||||||
|
if (!fs.existsSync(destDirPath)) {
|
||||||
|
log.error(`Dartdoc API folder not found:`, destDirPath);
|
||||||
|
} else if ((entries = map.get(name)).size > 0) {
|
||||||
|
_createDirData(name, destDirPath, entries);
|
||||||
|
numApiPagesWritten += _createJadeFiles(name, destDirPath, entries);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return numApiPagesWritten;
|
||||||
|
}
|
||||||
|
|
||||||
|
const _self = {
|
||||||
|
Array_from: Array_from,
|
||||||
|
apiEntryJadeTemplate: apiEntryJadeTemplate,
|
||||||
|
apiListDataFileService: apiListDataFileService,
|
||||||
|
loadApiDataAndSaveToApiListFile: loadApiDataAndSaveToApiListFile,
|
||||||
|
createApiDataAndJadeFiles: createApiDataAndJadeFiles,
|
||||||
|
dartPkgConfigInfo: dartPkgConfigInfo,
|
||||||
|
loadDartDocDataProcessor: loadDartDocDataProcessor,
|
||||||
|
log: log,
|
||||||
|
preprocessDartDocData: preprocessDartDocData,
|
||||||
|
};
|
||||||
|
Object.freeze(_self);
|
||||||
|
return _self;
|
||||||
|
};
|
||||||
|
|
||||||
|
function _indentedEltHtml($elt, i, filterFnOpt) {
|
||||||
|
let lines = $elt.html().split('\n');
|
||||||
|
if (filterFnOpt) lines = lines.filter(filterFnOpt);
|
||||||
|
const indent = ' '.substring(0,i);
|
||||||
|
return lines.map((line) => `${indent}| ${line}`).join('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
function apiEntryJadeTemplate(baseHrefDepth, $breadcrumbs, $mainDiv) {
|
||||||
|
const baseHref = path.join(...Array(baseHrefDepth).fill('..'));
|
||||||
|
// TODO/investigate: for some reason $breadcrumbs.html() is missing the <ol></ol>. We add it back in the template below.
|
||||||
|
const breadcrumbs = _indentedEltHtml($breadcrumbs, 6, (line) => !line.match(/^\s*$/));
|
||||||
|
const mainDivHtml = _indentedEltHtml($mainDiv, 4);
|
||||||
|
// WARNING: since the following is Jade, indentation is significant.
|
||||||
|
const result = `
|
||||||
|
extends ${baseHref}/../../../_layout-dart-api
|
||||||
|
|
||||||
|
include ${baseHref}/../_util-fns
|
||||||
|
|
||||||
|
block var-def
|
||||||
|
//- FIXME: a CSS expert needs to figure out why the header CSS needs to be patched for Dart.
|
||||||
|
//- This enables the patch:
|
||||||
|
- var fixHeroCss = 1;
|
||||||
|
|
||||||
|
block head-extra
|
||||||
|
// generated Dart API page template: head-extra
|
||||||
|
//- <base> is required because all the links in dartdoc generated pages are "pseudo-absolute"
|
||||||
|
base(href="${baseHref}")
|
||||||
|
link(rel='stylesheet' href='https://fonts.googleapis.com/css?family=Source+Code+Pro|Roboto:500,400italic,300,400' type='text/css')
|
||||||
|
link(rel="stylesheet" href="static-assets/prettify.css")
|
||||||
|
link(rel="stylesheet" href="static-assets/css/bootstrap.min.css")
|
||||||
|
link(rel="stylesheet" href="static-assets/styles.css")
|
||||||
|
|
||||||
|
block breadcrumbs
|
||||||
|
// generated Dart API page template: breadcrumbs
|
||||||
|
nav.dropdown
|
||||||
|
ol.breadcrumbs.gt-separated.hidden-xs
|
||||||
|
${breadcrumbs}
|
||||||
|
|
||||||
|
block main-content
|
||||||
|
// generated Dart API page template: main-content: start
|
||||||
|
div.dart-api-entry-main
|
||||||
|
${mainDivHtml}
|
||||||
|
// generated Dart API page template: main-content: end
|
||||||
|
`;
|
||||||
|
return result;
|
||||||
|
}
|
Loading…
Reference in New Issue