mirror of
https://github.com/danielsogl/awesome-cordova-plugins.git
synced 2026-05-20 00:06:24 +08:00
feat!: replace dgeni/gulp with TypeDoc for README generation
Replace the legacy dgeni/gulp documentation pipeline with TypeDoc and typedoc-plugin-markdown. Generates plugin README files with extracted @Plugin() decorator metadata. Register custom JSDoc tags used by plugin source files.
This commit is contained in:
@@ -1,4 +0,0 @@
|
||||
{
|
||||
"v2DocsDir": "docs/native",
|
||||
"pluginDir": "dist/@awesome-cordova-plugins/plugins"
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
module.exports = function (getLinkInfo) {
|
||||
getLinkInfo.useFirstAmbiguousLink = false;
|
||||
};
|
||||
@@ -1,3 +0,0 @@
|
||||
module.exports = function (log) {
|
||||
log.level = 'error'; //'silly', 'debug', 'info', 'warn', 'error'
|
||||
};
|
||||
@@ -1,3 +0,0 @@
|
||||
module.exports = function (parseTagsProcessor) {
|
||||
parseTagsProcessor.tagDefinitions = parseTagsProcessor.tagDefinitions.concat(require('../tag-defs/tag-defs'));
|
||||
};
|
||||
@@ -1,12 +0,0 @@
|
||||
module.exports = function (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: '#>',
|
||||
};
|
||||
};
|
||||
@@ -1,9 +0,0 @@
|
||||
module.exports = function (templateEngine) {
|
||||
// add custom filters to nunjucks
|
||||
templateEngine.filters.push(
|
||||
require('../filters/capital'),
|
||||
require('../filters/code'),
|
||||
require('../filters/dump'),
|
||||
require('../filters/dashify')
|
||||
);
|
||||
};
|
||||
@@ -1,75 +0,0 @@
|
||||
'use strict';
|
||||
const Package = require('dgeni').Package,
|
||||
jsdocPackage = require('dgeni-packages/jsdoc'),
|
||||
nunjucksPackage = require('dgeni-packages/nunjucks'),
|
||||
typescriptPackage = require('dgeni-packages/typescript'),
|
||||
linksPackage = require('dgeni-packages/links'),
|
||||
path = require('path'),
|
||||
config = require('../config.json');
|
||||
|
||||
module.exports = (currentVersion) => {
|
||||
return (
|
||||
new Package('ionic-native-docs', [jsdocPackage, nunjucksPackage, typescriptPackage, linksPackage])
|
||||
|
||||
.processor(require('./processors/remove-private-members'))
|
||||
.processor(require('./processors/hide-private-api'))
|
||||
.processor(require('./processors/parse-optional'))
|
||||
.processor(require('./processors/mark-properties'))
|
||||
.processor(require('./processors/npm-id'))
|
||||
.processor(require('./processors/jekyll'))
|
||||
|
||||
.config(require('./configs/log'))
|
||||
.config(require('./configs/template-filters'))
|
||||
.config(require('./configs/template-tags'))
|
||||
.config(require('./configs/tag-defs'))
|
||||
.config(require('./configs/links'))
|
||||
|
||||
.config(function (renderDocsProcessor, computePathsProcessor) {
|
||||
currentVersion = {
|
||||
href: '/' + config.v2DocsDir.replace('content/', ''),
|
||||
folder: '',
|
||||
name: currentVersion,
|
||||
};
|
||||
|
||||
renderDocsProcessor.extraData.version = {
|
||||
list: [currentVersion],
|
||||
current: currentVersion,
|
||||
latest: currentVersion,
|
||||
};
|
||||
|
||||
computePathsProcessor.pathTemplates = [
|
||||
{
|
||||
docTypes: ['class'],
|
||||
getOutputPath: (doc) => 'content/' + config.v2DocsDir + '/' + doc.name + '/index.md',
|
||||
},
|
||||
];
|
||||
})
|
||||
|
||||
//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(__dirname, '../../..');
|
||||
readTypeScriptModules.sourceFiles = ['./src/@awesome-cordova-plugins/plugins/**/*.ts'];
|
||||
})
|
||||
|
||||
// Configure file writing
|
||||
.config(function (writeFilesProcessor) {
|
||||
writeFilesProcessor.outputFolder = '../ionic-site/';
|
||||
})
|
||||
|
||||
// Configure rendering
|
||||
.config(function (templateFinder) {
|
||||
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',
|
||||
];
|
||||
})
|
||||
);
|
||||
};
|
||||
@@ -1,74 +0,0 @@
|
||||
'use strict';
|
||||
const Package = require('dgeni').Package,
|
||||
jsdocPackage = require('dgeni-packages/jsdoc'),
|
||||
nunjucksPackage = require('dgeni-packages/nunjucks'),
|
||||
typescriptPackage = require('dgeni-packages/typescript'),
|
||||
linksPackage = require('dgeni-packages/links'),
|
||||
path = require('path'),
|
||||
config = require('../config.json');
|
||||
|
||||
module.exports = (currentVersion) => {
|
||||
return (
|
||||
new Package('ionic-native-readmes', [jsdocPackage, nunjucksPackage, typescriptPackage, linksPackage])
|
||||
|
||||
.processor(require('./processors/readmes'))
|
||||
.processor(require('./processors/remove-private-members'))
|
||||
.processor(require('./processors/hide-private-api'))
|
||||
.processor(require('./processors/npm-id'))
|
||||
|
||||
.config(require('./configs/log'))
|
||||
.config(require('./configs/template-filters'))
|
||||
.config(require('./configs/template-tags'))
|
||||
.config(require('./configs/tag-defs'))
|
||||
.config(require('./configs/links'))
|
||||
|
||||
.config(function (renderDocsProcessor, computePathsProcessor) {
|
||||
currentVersion = {
|
||||
href: '/' + config.v2DocsDir.replace('content/', ''),
|
||||
folder: '',
|
||||
name: currentVersion,
|
||||
};
|
||||
|
||||
renderDocsProcessor.extraData.version = {
|
||||
list: [currentVersion],
|
||||
current: currentVersion,
|
||||
latest: currentVersion,
|
||||
};
|
||||
|
||||
computePathsProcessor.pathTemplates = [
|
||||
{
|
||||
docTypes: ['class'],
|
||||
getOutputPath: (doc) =>
|
||||
doc.originalModule.replace(config.pluginDir + '/', '').replace(/\/index$/, '/README.md'),
|
||||
},
|
||||
];
|
||||
})
|
||||
|
||||
//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/@awesome-cordova-plugins/plugins/**/*.ts'];
|
||||
})
|
||||
|
||||
// Configure file writing
|
||||
.config(function (writeFilesProcessor) {
|
||||
writeFilesProcessor.outputFolder = './dist/@awesome-cordova-plugins/';
|
||||
})
|
||||
|
||||
.config(function (writeFilesProcessor) {
|
||||
writeFilesProcessor.outputFolder = './docs/';
|
||||
})
|
||||
|
||||
// Configure rendering
|
||||
.config(function (templateFinder) {
|
||||
templateFinder.templateFolders.unshift(path.resolve(__dirname, 'templates'));
|
||||
|
||||
// Specify how to match docs to templates.
|
||||
templateFinder.templatePatterns = ['${ doc.template }', '${ doc.docType }.template.md', 'readme.template.md'];
|
||||
})
|
||||
);
|
||||
};
|
||||
@@ -1,5 +0,0 @@
|
||||
'use strict';
|
||||
module.exports = {
|
||||
name: 'capital',
|
||||
process: (str) => (str ? str.charAt(0).toUpperCase() + str.substring(1) : ''),
|
||||
};
|
||||
@@ -1,24 +0,0 @@
|
||||
'use strict';
|
||||
const 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: (str, lang) => code(str, true, lang),
|
||||
};
|
||||
@@ -1,5 +0,0 @@
|
||||
'use strict';
|
||||
module.exports = {
|
||||
name: 'dashify',
|
||||
process: (str) => (str ? str.replace(/\s/g, '-') : ''),
|
||||
};
|
||||
@@ -1,5 +0,0 @@
|
||||
'use strict';
|
||||
module.exports = {
|
||||
name: 'dump',
|
||||
process: (obj) => console.log(obj),
|
||||
};
|
||||
@@ -1,39 +0,0 @@
|
||||
'use strict';
|
||||
module.exports = function test() {
|
||||
return {
|
||||
name: 'debug',
|
||||
$runBefore: ['rendering-docs'],
|
||||
$process: function (docs) {
|
||||
docs.forEach(function (doc) {
|
||||
if (doc.name == 'Camera') {
|
||||
console.log(doc.tags);
|
||||
doc.tags.forEach(function (tag) {
|
||||
if (tag.tagName == 'classes') {
|
||||
}
|
||||
});
|
||||
|
||||
doc.moduleDoc.exports.forEach(function (d, i) {
|
||||
if (d.name === 'CameraOptions') {
|
||||
console.log('Name: ' + d.name);
|
||||
console.log('Type: ' + d.docType);
|
||||
console.log('First member: ', d.members[0]);
|
||||
}
|
||||
});
|
||||
|
||||
var exports = doc.exportSymbol.parent.exports;
|
||||
for (var p in exports) {
|
||||
if (p == 'CameraOptions') {
|
||||
var x = exports[p];
|
||||
console.log(x.members.quality);
|
||||
}
|
||||
}
|
||||
doc.members.forEach(function (method) {
|
||||
if (method.name === 'getPicture') {
|
||||
console.log(method);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
};
|
||||
};
|
||||
@@ -1,9 +0,0 @@
|
||||
'use strict';
|
||||
module.exports = function removePrivateApi() {
|
||||
return {
|
||||
name: 'remove-private-api',
|
||||
description: 'Prevent the private apis from being rendered',
|
||||
$runBefore: ['rendering-docs'],
|
||||
$process: (docs) => docs.filter((doc) => !doc.private && (!doc.tags || !doc.tags.tagsByName.get('hidden'))),
|
||||
};
|
||||
};
|
||||
@@ -1,63 +0,0 @@
|
||||
'use strict';
|
||||
module.exports = function jekyll(renderDocsProcessor) {
|
||||
return {
|
||||
name: 'jekyll',
|
||||
description: 'Create jekyll includes',
|
||||
$runAfter: ['paths-computed'],
|
||||
$runBefore: ['rendering-docs'],
|
||||
$process: (docs) => {
|
||||
// pretty up and sort the docs object for menu generation
|
||||
docs = docs.filter((doc) => (!!doc.name && !!doc.outputPath) || doc.docType === 'index-page');
|
||||
|
||||
docs.push({
|
||||
docType: 'class',
|
||||
URL: 'https://github.com/ionic-team/ionic-native-google-maps/blob/master/documents/README.md',
|
||||
name: 'Google Maps',
|
||||
});
|
||||
|
||||
docs.sort((a, b) => {
|
||||
const textA = a.name ? a.name.toUpperCase() : '',
|
||||
textB = b.name ? b.name.toUpperCase() : '';
|
||||
|
||||
return textA < textB ? -1 : textA > textB ? 1 : 0;
|
||||
});
|
||||
|
||||
docs.forEach((doc) => {
|
||||
if (!doc.outputPath) {
|
||||
return;
|
||||
}
|
||||
|
||||
doc.outputPath = doc.outputPath.toLowerCase().replace(/\s/g, '-');
|
||||
doc.URL = doc.outputPath.replace('docs//', 'docs/').replace('/index.md', '').replace('content/', '');
|
||||
// add trailing slash to plugin pages
|
||||
if (!doc.URL.endsWith('/') && !doc.URL.endsWith('.html')) {
|
||||
doc.URL = doc.URL + '/';
|
||||
}
|
||||
|
||||
doc.URL = '/' + doc.URL;
|
||||
});
|
||||
|
||||
const betaDocs = [];
|
||||
|
||||
docs = docs.filter((doc) => {
|
||||
if (doc.beta === true) {
|
||||
betaDocs.push(doc);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
docs = docs.concat(betaDocs);
|
||||
|
||||
// add side menu
|
||||
docs.push({
|
||||
docType: 'nativeMenu',
|
||||
id: 'native_menu',
|
||||
template: 'native_menu.template.html',
|
||||
outputPath: 'content/_includes/fluid/native_menu.html',
|
||||
});
|
||||
|
||||
return docs;
|
||||
},
|
||||
};
|
||||
};
|
||||
@@ -1,16 +0,0 @@
|
||||
'use strict';
|
||||
module.exports = function markProperties() {
|
||||
return {
|
||||
name: 'mark-properties',
|
||||
$runBefore: ['rendering-docs'],
|
||||
$process: (docs) =>
|
||||
docs.map((doc) => {
|
||||
for (let i in doc.members) {
|
||||
if (doc.members.hasOwnProperty(i) && typeof doc.members[i].parameters === 'undefined') {
|
||||
doc.members[i].isProperty = true;
|
||||
}
|
||||
}
|
||||
return doc;
|
||||
}),
|
||||
};
|
||||
};
|
||||
@@ -1,20 +0,0 @@
|
||||
'use strict';
|
||||
module.exports = function npmId(renderDocsProcessor) {
|
||||
return {
|
||||
name: 'npm-id',
|
||||
$runAfter: ['paths-computed'],
|
||||
$runBefore: ['rendering-docs'],
|
||||
$process: (docs) => {
|
||||
// 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.forEach((doc) => {
|
||||
doc.npmId = doc.id.match(/plugins\/(.*)\/index/)[1];
|
||||
});
|
||||
|
||||
return docs;
|
||||
},
|
||||
};
|
||||
};
|
||||
@@ -1,22 +0,0 @@
|
||||
'use strict';
|
||||
module.exports = function parseOptional() {
|
||||
return {
|
||||
$runBefore: ['rendering-docs'],
|
||||
$process: (docs) => {
|
||||
docs.forEach((doc) => {
|
||||
if (doc.members && doc.members.length) {
|
||||
for (let i in doc.members) {
|
||||
if (doc.members[i].params && doc.members[i].params.length) {
|
||||
for (let 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;
|
||||
},
|
||||
};
|
||||
};
|
||||
@@ -1,19 +0,0 @@
|
||||
'use strict';
|
||||
module.exports = function readmes(renderDocsProcessor) {
|
||||
return {
|
||||
name: 'readmes',
|
||||
description: 'Create jekyll includes',
|
||||
$runAfter: ['paths-computed'],
|
||||
$runBefore: ['rendering-docs'],
|
||||
$process: (docs) => {
|
||||
// pretty up and sort the docs object for menu generation
|
||||
docs = docs.filter((doc) => (!!doc.name && !!doc.outputPath) || doc.docType === 'index-page');
|
||||
|
||||
docs.forEach((doc) => {
|
||||
doc.outputPath = doc.outputPath.replace('src/@awesome-cordova-plugins/', '');
|
||||
});
|
||||
|
||||
return docs;
|
||||
},
|
||||
};
|
||||
};
|
||||
@@ -1,22 +0,0 @@
|
||||
'use strict';
|
||||
module.exports = function removePrivateMembers() {
|
||||
return {
|
||||
name: 'remove-private-members',
|
||||
description: 'Remove member docs with @private tags',
|
||||
$runAfter: ['tags-parsed'],
|
||||
$runBefore: ['rendering-docs'],
|
||||
$process: (docs) => {
|
||||
docs.forEach((doc) => {
|
||||
if (doc.members) {
|
||||
doc.members = doc.members.filter((member) => !member.tags.tagsByName.get('hidden'));
|
||||
}
|
||||
|
||||
if (doc.statics) {
|
||||
doc.statics = doc.statics.filter((staticMethod) => !staticMethod.tags.tagsByName.get('hidden'));
|
||||
}
|
||||
});
|
||||
|
||||
return docs;
|
||||
},
|
||||
};
|
||||
};
|
||||
@@ -1,11 +0,0 @@
|
||||
'use strict';
|
||||
module.exports = [
|
||||
{ name: 'advanced' },
|
||||
{ name: 'demo' },
|
||||
{ name: 'beta', transforms: (doc, tag, value) => typeof value !== 'undefined' }, // make the value true or undefined instead of '' or undefined
|
||||
{ name: 'usage' },
|
||||
{ name: 'hidden' }, // hide from docs
|
||||
{ name: 'classes' }, // related classes
|
||||
{ name: 'interfaces' }, // related interfaces
|
||||
{ name: 'paid', transforms: (doc, tag, value) => typeof value !== 'undefined' }, // paid plugin, set value to true
|
||||
];
|
||||
@@ -1,192 +0,0 @@
|
||||
---
|
||||
layout: "fluid/docs_base"
|
||||
version: "<$ version.current.name $>"
|
||||
versionHref: "<$ version.current.href.replace('content/','') $>"
|
||||
path: "<$ doc.path $>"
|
||||
category: native
|
||||
id: "<$ doc.name|lower|replace(' ','-') $>"
|
||||
title: "<@ if doc.docType == "directive" @><$ doc.name | dashCase $><@ else @><$ doc.name $><@ endif @>"
|
||||
header_sub_title: "<$ doc.docType | capital $> in module <$ doc.module $>"
|
||||
doc: "<$ doc.name $>"
|
||||
docType: "<$ doc.docType $>"
|
||||
---
|
||||
|
||||
<@- macro interfaceTable(interface) -@> <@ for export in doc.moduleDoc.exports -@> <@ if export.name == interface @>
|
||||
<table class="table param-table" style="margin: 0">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Param</th>
|
||||
<th>Type</th>
|
||||
<th>Details</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<@ for param in export.members @>
|
||||
<tr>
|
||||
<td><$ param.name $></td>
|
||||
<td>
|
||||
<code><$ param.returnType | escape $></code>
|
||||
</td>
|
||||
<td><$ param.description | marked $> <@ if param.optional @><em>(optional)</em><@ endif @></td>
|
||||
</tr>
|
||||
<@ endfor @>
|
||||
</tbody>
|
||||
</table>
|
||||
<@ endif @> <@- endfor @> <@- endmacro -@> <@- macro githubViewLink(doc) -@>
|
||||
<a
|
||||
href="https://github.com/ionic-team/ionic-native/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 -@></td>
|
||||
<td><$ typeList(param.typeList) $></td>
|
||||
<td>
|
||||
<$ param.description | marked $> <@- if param.defaultValue @>
|
||||
<p><em>(default: <$ param.defaultValue $>)</em></p>
|
||||
<@ endif -@>
|
||||
</td>
|
||||
</tr>
|
||||
<@ endfor -@>
|
||||
</tbody>
|
||||
</table>
|
||||
<@- endmacro -@> <@- macro functionSyntax(fn) @> <@- set sep = joiner(', ') -@>
|
||||
<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
|
||||
>
|
||||
<@- endmacro -@> <@- macro typeList(types) -@> <@ set separator = joiner("|") @> <@- for type in types @><$ separator()
|
||||
$><$ type | code $><@ endfor -@> <@- endmacro -@> <@- macro typeInfo(fn) -@> <$ typeList(fn.typeList) $> <$
|
||||
fn.description $> <@- endmacro -@> <@- macro documentPlatforms(method) -@> <@- if method.decorators @> <@ for prop in
|
||||
method.decorators[0].argumentInfo @> <@ if prop.platforms @>
|
||||
<p>
|
||||
<strong>Platforms:</strong>
|
||||
<@- for platform in prop.platforms -@>
|
||||
<strong class="tag"><$ platform $></strong> <@- endfor -@>
|
||||
</p>
|
||||
<@ endif @> <@ endfor @> <@- endif @> <@- endmacro -@> <@ macro documentMethod(method) -@>
|
||||
<h3><a class="anchor" name="<$ method.name $>" href="#<$ method.name $>"></a><$ functionSyntax(method) $></h3>
|
||||
<$ documentPlatforms(method) $> <$ method.description $> <@ if method.params -@> <$ paramTable(method.params) $> <@-
|
||||
endif @> <@ if method.returns -@>
|
||||
<div class="return-value" markdown="1">
|
||||
<i class="icon ion-arrow-return-left"></i>
|
||||
<b>Returns:</b> <$ typeInfo(method.returns) $>
|
||||
</div>
|
||||
<@- endif @> <@- endmacro -@> <@- macro documentClass(doc) @> <@- if doc.statics.length -@>
|
||||
<h2><a class="anchor" name="static-members" href="#static-members"></a>Static Members</h2>
|
||||
<@ for method in doc.statics -@> <$ documentMethod(method) $> <@ endfor -@> <@ endif @> <# --- methods in 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 -@> <$ documentMethod(method) $> <@- endfor @> <@- endif -@> <@ endmacro @>
|
||||
|
||||
<h1 class="api-title">
|
||||
<$ doc.name $> <@- if doc.beta == true -@>
|
||||
<span class="beta" title="beta">β</span>
|
||||
<@- endif -@> <@- if doc.paid == true -@>
|
||||
<span class="paid" title="paid">Paid</span>
|
||||
<@- endif -@>
|
||||
</h1>
|
||||
|
||||
<a
|
||||
class="improve-v2-docs"
|
||||
href="http://github.com/ionic-team/ionic-native/edit/master/<$ doc.fileInfo.relativePath|replace('/home/ubuntu/ionic-native/', '')|replace('//','/') $>#L<$ doc.location.start.line $>"
|
||||
>
|
||||
Improve this doc
|
||||
</a>
|
||||
|
||||
<# --- Decorators --- #> <@- if doc.decorators @> <@ for prop in doc.decorators[0].argumentInfo @> <@ if doc.beta ==
|
||||
true @>
|
||||
<p class="beta-notice">
|
||||
This plugin is still in beta stage and may not work as expected. Please submit any issues to the
|
||||
<a target="_blank" href="<$ prop.repo $>/issues">plugin repo</a>.
|
||||
</p>
|
||||
<@ endif @> <@ if doc.paid == true @>
|
||||
<p class="paid-notice">
|
||||
This plugin might require a paid license, or might take a share of your app's earnings. Check the
|
||||
<a target="_blank" rel="nofollow" href="<$ prop.repo $>">plugin's repo</a> for more information.
|
||||
</p>
|
||||
<@ endif @> <# --- Plugin description --- #> <$ doc.description | marked $>
|
||||
|
||||
<p>
|
||||
Repo:
|
||||
<a href="<$ prop.repo $>"> <$ prop.repo $> </a>
|
||||
</p>
|
||||
|
||||
<# --- Install commands --- #>
|
||||
<h2><a class="anchor" name="installation" href="#installation"></a>Installation</h2>
|
||||
<ol class="installation">
|
||||
<li>
|
||||
Install the Cordova and Ionic Native plugins:<br />
|
||||
<pre><code class="nohighlight">$ <@ if prop.install @><$ prop.install | replace('<', '<').replace('>', '>') $><@ else @>ionic cordova plugin add <$ prop.plugin $><@ endif @>
|
||||
$ npm install @ionic-native/<$ doc.npmId $>
|
||||
</code></pre>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://ionicframework.com/docs/native/#Add_Plugins_to_Your_App_Module"
|
||||
>Add this plugin to your app's module</a
|
||||
>
|
||||
</li>
|
||||
</ol>
|
||||
|
||||
<# --- Plugin supported platforms --- #> <@ if prop.platforms @>
|
||||
<h2><a class="anchor" name="platforms" href="#platforms"></a>Supported platforms</h2>
|
||||
<ul>
|
||||
<@ for platform in prop.platforms -@>
|
||||
<li><$ platform $></li>
|
||||
<@- endfor @>
|
||||
</ul>
|
||||
<@ endif @> <@ endfor @> <@ endif -@> <# --- end of: if doc.decorators --- #> <# --- Plugin usage --- #> <@ if doc.usage
|
||||
@>
|
||||
<h2><a class="anchor" name="usage" href="#usage"></a>Usage</h2>
|
||||
<$ doc.usage | marked $> <@ endif @> <# --- Plugin attributes --- #> <@- 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 -@> <# --- Plugin class documentation --- #> <$ documentClass(doc) $> <# --- Advanced usage --- #> <@- if
|
||||
doc.advanced -@>
|
||||
<h2><a class="anchor" name="advanced" href="#advanced"></a>Advanced</h2>
|
||||
<$ doc.advanced | marked $> <@- endif -@> <# --- Other classes --- #> <@- for tag in doc.tags.tags -@> <@- if
|
||||
tag.tagName == 'classes' -@> <@- set classes = tag.description.split('\n') -@> <@- for item in classes -@> <@- if
|
||||
item.length > 1 -@> <@- for export in doc.moduleDoc.exports -@> <@- if export.name == item -@>
|
||||
<h2><a class="anchor" name="<$ item $>" href="#<$ item $>"></a><$ item $></h2>
|
||||
<$ documentClass(export) $> <@- endif -@> <@- endfor -@> <@- endif -@> <@- endfor -@> <@- endif -@> <@- endfor -@> <#
|
||||
--- Other interfaces --- #> <@ for tag in doc.tags.tags -@> <@ if tag.tagName == 'interfaces' @> <@ set interfaces =
|
||||
tag.description.split('\n') @> <@ for item in interfaces -@> <@ if item.length > 1 @>
|
||||
<h2><a class="anchor" name="<$ item $>" href="#<$ item $>"></a><$ item $></h2>
|
||||
<$ interfaceTable(item) $> <@ endif @> <@- endfor @> <@ endif @> <@- endfor @> <# --- Related links --- #> <@- if
|
||||
doc.see @>
|
||||
<h2><a class="anchor" name="related" href="#related"></a>Related</h2>
|
||||
<@ for s in doc.see @> <$ s | safe $> <@- endfor -@> <@- endif -@>
|
||||
@@ -1,14 +0,0 @@
|
||||
<li class="capitalize {% if page.id == 'overview' %}active{% endif %}">
|
||||
<a href="/docs/native/">Overview</a>
|
||||
</li>
|
||||
<li class="capitalize {% if page.id == 'mocking' %}active{% endif %}">
|
||||
<a href="/docs/native/browser.html">Browser Usage</a>
|
||||
</li>
|
||||
<@- for doc in docs @><@ if doc.URL and doc.private != true @>
|
||||
<li class="capitalize {% if page.id == '<$ doc.name|lower|dashify $>' %}active{% endif %}">
|
||||
<a href="<$ doc.URL $>"
|
||||
><$ doc.name $><@ if doc.paid == true @> <span class="paid">Paid</span><@ endif @><@ if doc.beta == true @>
|
||||
<span class="beta">β</span><@ endif @></a
|
||||
>
|
||||
</li>
|
||||
<@ endif @><@ endfor @>
|
||||
@@ -1,36 +0,0 @@
|
||||
# <$ doc.name $>
|
||||
|
||||
<@- if doc.beta == true @>
|
||||
|
||||
<p style="color:orange">
|
||||
This plugin is still in beta stage and may not work as expected. Please
|
||||
submit any issues to the <a target="_blank"
|
||||
href="<$ prop.repo $>/issues">plugin repo</a>.
|
||||
</p>
|
||||
<@ endif -@>
|
||||
|
||||
<@ for prop in doc.decorators[0].argumentInfo @>
|
||||
|
||||
```
|
||||
$ <@ if prop.install @><$ prop.install $><@ else @>ionic cordova plugin add <$ prop.plugin $><@ endif @>
|
||||
$ npm install @awesome-cordova-plugins/<$ doc.npmId|replace('plugins/','') $>
|
||||
```
|
||||
|
||||
## [Usage Documentation](https://danielsogl.gitbook.io/awesome-cordova-plugins/plugins/<$ doc.fileInfo.relativePath|replace('/home/ubuntu/ionic-native/', '')|replace('//','/')|replace('index.ts','')|replace('src/@awesome-cordova-plugins/plugins/','') $>)
|
||||
|
||||
Plugin Repo: [<$ prop.repo $>](<$ prop.repo $>)
|
||||
|
||||
<$ doc.description $>
|
||||
|
||||
<@- if prop.platforms @>
|
||||
|
||||
## Supported platforms
|
||||
|
||||
<@ for platform in prop.platforms -@>
|
||||
|
||||
- <$ platform $>
|
||||
<@ endfor @>
|
||||
|
||||
<@ endif -@>
|
||||
|
||||
<@ endfor @>
|
||||
@@ -0,0 +1,257 @@
|
||||
import {
|
||||
Application,
|
||||
Converter,
|
||||
Context,
|
||||
ReflectionKind,
|
||||
DeclarationReflection,
|
||||
CommentTag,
|
||||
ProjectReflection,
|
||||
LogLevel,
|
||||
} from 'typedoc';
|
||||
import { cpSync, mkdirSync, writeFileSync } from 'node:fs';
|
||||
import { resolve, join } from 'node:path';
|
||||
import {
|
||||
Node,
|
||||
Symbol as TsSymbol,
|
||||
isClassDeclaration,
|
||||
isCallExpression,
|
||||
isIdentifier,
|
||||
isObjectLiteralExpression,
|
||||
isPropertyAssignment,
|
||||
isStringLiteral,
|
||||
isNumericLiteral,
|
||||
isArrayLiteralExpression,
|
||||
getDecorators,
|
||||
SyntaxKind,
|
||||
} from 'typescript';
|
||||
|
||||
const ROOT = resolve(__dirname, '../..');
|
||||
const PLUGINS_SRC = join(ROOT, 'src/@awesome-cordova-plugins/plugins');
|
||||
const DOCS_OUT = join(ROOT, 'docs/plugins');
|
||||
|
||||
interface PluginMeta {
|
||||
pluginName?: string;
|
||||
plugin?: string;
|
||||
pluginRef?: string;
|
||||
repo?: string;
|
||||
platforms?: string[];
|
||||
install?: string;
|
||||
}
|
||||
|
||||
// Map from reflection id to extracted decorator metadata
|
||||
const pluginMetaMap = new Map<number, PluginMeta>();
|
||||
|
||||
function parseLiteralValue(node: Node): string | number | boolean | string[] | undefined {
|
||||
if (isStringLiteral(node)) return node.text;
|
||||
if (isNumericLiteral(node)) return Number(node.text);
|
||||
if (node.kind === SyntaxKind.TrueKeyword) return true;
|
||||
if (node.kind === SyntaxKind.FalseKeyword) return false;
|
||||
if (isArrayLiteralExpression(node)) {
|
||||
return node.elements.map((el) => {
|
||||
const val = parseLiteralValue(el);
|
||||
return typeof val === 'string' ? val : String(val);
|
||||
});
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function extractPluginMeta(symbol: TsSymbol | undefined): PluginMeta | undefined {
|
||||
if (!symbol) return undefined;
|
||||
const decl = symbol.declarations?.[0];
|
||||
if (!decl || !isClassDeclaration(decl)) return undefined;
|
||||
|
||||
const decorators = getDecorators(decl);
|
||||
if (!decorators) return undefined;
|
||||
|
||||
const pluginDec = decorators.find((d) => {
|
||||
const expr = d.expression;
|
||||
return isCallExpression(expr) && isIdentifier(expr.expression) && expr.expression.text === 'Plugin';
|
||||
});
|
||||
if (!pluginDec) return undefined;
|
||||
|
||||
const callExpr = pluginDec.expression;
|
||||
if (!isCallExpression(callExpr)) return undefined;
|
||||
|
||||
const args = callExpr.arguments[0];
|
||||
if (!args || !isObjectLiteralExpression(args)) return undefined;
|
||||
|
||||
const meta: Record<string, string | number | boolean | string[] | undefined> = {};
|
||||
for (const prop of args.properties) {
|
||||
if (!isPropertyAssignment(prop) || !isIdentifier(prop.name)) continue;
|
||||
meta[prop.name.text] = parseLiteralValue(prop.initializer);
|
||||
}
|
||||
return meta as unknown as PluginMeta;
|
||||
}
|
||||
|
||||
function getCommentText(reflection: DeclarationReflection): string {
|
||||
if (!reflection.comment) return '';
|
||||
|
||||
// Prefer summary text (text before any block tags)
|
||||
const summary = reflection.comment.summary
|
||||
.map((part) => part.text)
|
||||
.join('')
|
||||
.trim();
|
||||
|
||||
if (summary) return summary;
|
||||
|
||||
// Fall back to @description block tag (used by most plugins)
|
||||
const descTag = reflection.comment.blockTags?.find((t: CommentTag) => t.tag === '@description');
|
||||
if (descTag) {
|
||||
return descTag.content
|
||||
.map((part) => part.text)
|
||||
.join('')
|
||||
.trim();
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
function getTagValue(reflection: DeclarationReflection, tagName: string): string | undefined {
|
||||
if (!reflection.comment) return undefined;
|
||||
const tag = reflection.comment.blockTags?.find((t: CommentTag) => t.tag === `@${tagName}`);
|
||||
if (!tag) return undefined;
|
||||
return tag.content
|
||||
.map((part) => part.text)
|
||||
.join('')
|
||||
.trim();
|
||||
}
|
||||
|
||||
function generateReadme(name: string, pluginSlug: string, description: string, meta: PluginMeta): string {
|
||||
const installCmd = meta.install ?? `ionic cordova plugin add ${meta.plugin ?? 'PLUGIN_NAME'}`;
|
||||
const npmPkg = `@awesome-cordova-plugins/${pluginSlug}`;
|
||||
|
||||
let readme = `# ${name}\n\n`;
|
||||
|
||||
readme += '```\n';
|
||||
readme += `$ ${installCmd}\n`;
|
||||
readme += `$ npm install ${npmPkg}\n`;
|
||||
readme += '```\n\n';
|
||||
|
||||
readme += `## [Usage Documentation](https://danielsogl.gitbook.io/awesome-cordova-plugins/plugins/${pluginSlug}/)\n\n`;
|
||||
|
||||
if (meta.repo) {
|
||||
readme += `Plugin Repo: [${meta.repo}](${meta.repo})\n\n`;
|
||||
}
|
||||
|
||||
if (description) {
|
||||
readme += `${description}\n\n`;
|
||||
}
|
||||
|
||||
if (meta.platforms && meta.platforms.length > 0) {
|
||||
readme += '## Supported platforms\n\n';
|
||||
for (const platform of meta.platforms) {
|
||||
readme += `- ${platform}\n`;
|
||||
}
|
||||
readme += '\n';
|
||||
}
|
||||
|
||||
return readme;
|
||||
}
|
||||
|
||||
// Custom JSDoc block tags used by plugin source files (rendered in Gitbook)
|
||||
const CUSTOM_BLOCK_TAGS = [
|
||||
'@advanced',
|
||||
'@author',
|
||||
'@capacitorincompatible',
|
||||
'@classes',
|
||||
'@description',
|
||||
'@enums',
|
||||
'@interfaces',
|
||||
'@Interfaces',
|
||||
'@kind',
|
||||
'@link',
|
||||
'@name',
|
||||
'@note',
|
||||
'@paid',
|
||||
'@platform',
|
||||
'@premier',
|
||||
'@return',
|
||||
'@static',
|
||||
'@usage',
|
||||
'@warning',
|
||||
] as const;
|
||||
|
||||
// TypeDoc default block tags + project-specific custom tags for Gitbook
|
||||
const BLOCK_TAGS = [
|
||||
'@param', '@returns', '@template', '@typeParam', '@module', '@inheritDoc',
|
||||
'@group', '@category', '@categoryDescription', '@groupDescription',
|
||||
'@defaultValue', '@default', '@example', '@remarks', '@see', '@throws',
|
||||
'@since', '@deprecated', '@overload', '@enum', '@typedef', '@callback',
|
||||
'@prop', '@property', '@satisfies', '@import', '@type', '@hidden',
|
||||
'@ignore', '@internal', '@packageDocumentation', '@document', '@license',
|
||||
'@private', '@protected', '@public',
|
||||
...CUSTOM_BLOCK_TAGS,
|
||||
] as const;
|
||||
|
||||
async function main(): Promise<void> {
|
||||
// TypeDoc's CJS type exports map several option fields to incorrect types (e.g. `string` instead of
|
||||
// `boolean` or `object`). The `unknown` cast works around this without affecting runtime behavior.
|
||||
const app = await Application.bootstrapWithPlugins({
|
||||
entryPoints: [`${PLUGINS_SRC}/*/index.ts`],
|
||||
tsconfig: join(ROOT, 'tsconfig.json'),
|
||||
skipErrorChecking: true,
|
||||
logLevel: LogLevel.Error,
|
||||
blockTags: [...BLOCK_TAGS],
|
||||
inlineTags: ['@link', '@inheritDoc', '@label', '@code', '@type'],
|
||||
validation: { notDocumented: false, invalidLink: false },
|
||||
} as unknown as Parameters<typeof Application.bootstrapWithPlugins>[0]);
|
||||
|
||||
// Extract @Plugin() decorator metadata during TypeScript conversion
|
||||
app.converter.on(
|
||||
Converter.EVENT_CREATE_DECLARATION,
|
||||
(context: Context, reflection: DeclarationReflection) => {
|
||||
if (reflection.kind !== ReflectionKind.Class) return;
|
||||
|
||||
const symbol = context.getSymbolFromReflection(reflection);
|
||||
if (!symbol) return;
|
||||
|
||||
const meta = extractPluginMeta(symbol);
|
||||
if (meta) {
|
||||
pluginMetaMap.set(reflection.id, meta);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
const project: ProjectReflection | undefined = await app.convert();
|
||||
if (!project) {
|
||||
console.error('TypeDoc conversion failed');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// Copy root README to core docs
|
||||
const coreDocsDir = join(DOCS_OUT, 'core');
|
||||
mkdirSync(coreDocsDir, { recursive: true });
|
||||
cpSync(join(ROOT, 'README.md'), join(coreDocsDir, 'README.md'));
|
||||
|
||||
let count = 0;
|
||||
|
||||
for (const reflection of project.getReflectionsByKind(ReflectionKind.Class)) {
|
||||
const classRef = reflection as DeclarationReflection;
|
||||
const meta = pluginMetaMap.get(classRef.id);
|
||||
|
||||
if (!meta || !meta.plugin) continue;
|
||||
|
||||
// Extract plugin slug from source file path
|
||||
// Use @awesome-cordova-plugins/plugins/ prefix to avoid matching "awesome-cordova-plugins/src/"
|
||||
const sourcePath = classRef.sources?.[0]?.fullFileName ?? '';
|
||||
const slugMatch = sourcePath.match(/@awesome-cordova-plugins\/plugins\/([^/]+)\//);
|
||||
if (!slugMatch) continue;
|
||||
const pluginSlug = slugMatch[1];
|
||||
|
||||
const pluginName = getTagValue(classRef, 'name') ?? classRef.name;
|
||||
const description = getCommentText(classRef);
|
||||
|
||||
const readmeContent = generateReadme(pluginName, pluginSlug, description, meta);
|
||||
const outDir = join(DOCS_OUT, pluginSlug);
|
||||
mkdirSync(outDir, { recursive: true });
|
||||
writeFileSync(join(outDir, 'README.md'), readmeContent, 'utf-8');
|
||||
count++;
|
||||
}
|
||||
|
||||
console.log(`${count} README files generated`);
|
||||
}
|
||||
|
||||
main().catch((err: unknown) => {
|
||||
console.error(err);
|
||||
process.exit(1);
|
||||
});
|
||||
@@ -1,36 +0,0 @@
|
||||
'use strict';
|
||||
const config = require('./config.json'),
|
||||
projectPackage = require('../../package.json'),
|
||||
path = require('path'),
|
||||
fs = require('fs-extra'),
|
||||
Dgeni = require('dgeni');
|
||||
|
||||
module.exports = (gulp) => {
|
||||
gulp.task('docs', () => {
|
||||
try {
|
||||
const ionicPackage = require('./dgeni/dgeni-config')(projectPackage.version),
|
||||
dgeni = new Dgeni([ionicPackage]);
|
||||
|
||||
return dgeni.generate().then((docs) => console.log(docs.length + ' docs generated'));
|
||||
} catch (err) {
|
||||
console.log(err.stack);
|
||||
}
|
||||
});
|
||||
|
||||
gulp.task('readmes', () => {
|
||||
fs.copySync(
|
||||
path.resolve(__dirname, '..', '..', 'README.md'),
|
||||
path.resolve(__dirname, '..', '..', config.pluginDir, 'core', 'README.md')
|
||||
);
|
||||
|
||||
try {
|
||||
const ionicPackage = require('./dgeni/dgeni-readmes-config')(projectPackage.version),
|
||||
dgeni = new Dgeni([ionicPackage]);
|
||||
return dgeni.generate().then((docs) => {
|
||||
console.log(docs.length + ' README files generated');
|
||||
});
|
||||
} catch (err) {
|
||||
console.log(err.stack);
|
||||
}
|
||||
});
|
||||
};
|
||||
Reference in New Issue
Block a user