-
Notifications
You must be signed in to change notification settings - Fork 23
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[FEATURE] Add JSDoc build functionalities (#42)
New tasks: - generateJsdoc - executeJsdocSdkTransformation - generateApiIndex New processors: - jsdocGenerator - sdkTransformer - apiIndexGenerator Can be tested by executing `npm run build-sdk` in the OpenUI5 testsuite project
- Loading branch information
1 parent
e2c2840
commit 293a4b0
Showing
33 changed files
with
10,853 additions
and
47 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
const resourceFactory = require("@ui5/fs").resourceFactory; | ||
const createIndex = require("./lib/create-api-index"); | ||
|
||
/** | ||
* Compiles API index resources from all <code>api.json</code> resources available in the given test resources directory | ||
* as created by the [sdkTransformer]{@link module:@ui5/builder.processors.sdkTransformer} processor. | ||
* The resulting index resources (e.g. <code>api-index.json</code>, <code>api-index-deprecated.json</code>, | ||
* <code>api-index-experimental.json</code> and <code>api-index-since.json</code>) are mainly to be used in the SDK. | ||
* | ||
* @public | ||
* @alias module:@ui5/builder.processors.apiIndexGenerator | ||
* @param {Object} parameters Parameters | ||
* @param {string} parameters.versionInfoPath Path to <code>sap-ui-version.json</code> resource | ||
* @param {string} parameters.testResourcesRootPath Path to <code>/test-resources</code> root directory in the | ||
* given fs | ||
* @param {string} parameters.targetApiIndexPath Path to create the generated API index JSON resource for | ||
* @param {string} parameters.targetApiIndexDeprecatedPath Path to create the generated API index "deprecated" JSON | ||
* resource for | ||
* @param {string} parameters.targetApiIndexExperimentalPath Path to create the generated API index "experimental" JSON | ||
* resource for | ||
* @param {string} parameters.targetApiIndexSincePath Path to create the generated API index "since" JSON resource for | ||
* @param {fs|module:@ui5/fs.fsInterface} parameters.fs Node fs or | ||
* custom [fs interface]{@link module:resources/module:@ui5/fs.fsInterface} to use | ||
* @returns {Promise<module:@ui5/fs.Resource[]>} Promise resolving with created resources <code>api-index.json</code>, | ||
* <code>api-index-deprecated.json</code>, <code>api-index-experimental.json</code> and | ||
* <code>api-index-since.json</code> (names depend on the supplied paths) | ||
*/ | ||
const apiIndexGenerator = async function({ | ||
versionInfoPath, testResourcesRootPath, targetApiIndexPath, targetApiIndexDeprecatedPath, | ||
targetApiIndexExperimentalPath, targetApiIndexSincePath, fs | ||
} = {}) { | ||
if (!versionInfoPath || !testResourcesRootPath || !targetApiIndexPath || !targetApiIndexDeprecatedPath || | ||
!targetApiIndexExperimentalPath || !targetApiIndexSincePath || !fs) { | ||
throw new Error("[apiIndexGenerator]: One or more mandatory parameters not provided"); | ||
} | ||
|
||
const resourceMap = await createIndex(versionInfoPath, testResourcesRootPath, targetApiIndexPath, | ||
targetApiIndexDeprecatedPath, targetApiIndexExperimentalPath, targetApiIndexSincePath, { | ||
fs, | ||
returnOutputFiles: true | ||
}); | ||
|
||
return Object.keys(resourceMap).map((resPath) => { | ||
return resourceFactory.createResource({ | ||
path: resPath, | ||
string: resourceMap[resPath] | ||
}); | ||
}); | ||
}; | ||
|
||
module.exports = apiIndexGenerator; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,164 @@ | ||
const spawn = require("child_process").spawn; | ||
const fs = require("graceful-fs"); | ||
const path = require("path"); | ||
const {promisify} = require("util"); | ||
const writeFile = promisify(fs.writeFile); | ||
const {resourceFactory} = require("@ui5/fs"); | ||
|
||
/** | ||
* JSDoc generator | ||
* | ||
* @public | ||
* @alias module:@ui5/builder.processors.jsdocGenerator | ||
* @param {Object} parameters Parameters | ||
* @param {string} parameters.sourcePath Path of the source files to be processed | ||
* @param {string} parameters.targetPath Path to write any output files | ||
* @param {string} parameters.tmpPath Path to write temporary and debug files | ||
* @param {Object} parameters.options Options | ||
* @param {string} parameters.options.projectName Project name | ||
* @param {string} parameters.options.namespace Namespace to build (e.g. <code>some/project/name</code>) | ||
* @param {string} parameters.options.version Project version | ||
* @param {Array} [parameters.options.variants=["apijson"]] JSDoc variants to be built | ||
* @returns {Promise<module:@ui5/fs.Resource[]>} Promise resolving with newly created resources | ||
*/ | ||
const jsdocGenerator = async function({sourcePath, targetPath, tmpPath, options} = {}) { | ||
if (!sourcePath || !targetPath || !tmpPath || !options.projectName || !options.namespace || !options.version) { | ||
throw new Error("[jsdocGenerator]: One or more mandatory parameters not provided"); | ||
} | ||
|
||
if (!options.variants || options.variants.length === 0) { | ||
options.variants = ["apijson"]; | ||
} | ||
|
||
const config = await jsdocGenerator._generateJsdocConfig({ | ||
targetPath, | ||
tmpPath, | ||
namespace: options.namespace, | ||
projectName: options.projectName, | ||
version: options.version, | ||
variants: options.variants | ||
}); | ||
|
||
const configPath = await jsdocGenerator._writeJsdocConfig(tmpPath, config); | ||
|
||
await jsdocGenerator._buildJsdoc({ | ||
sourcePath, | ||
configPath | ||
}); | ||
|
||
const fsTarget = resourceFactory.createAdapter({ | ||
fsBasePath: targetPath, | ||
virBasePath: "/" | ||
}); | ||
|
||
// create resources from the output files | ||
return Promise.all([ | ||
fsTarget.byPath(`/test-resources/${options.namespace}/designtime/api.json`) | ||
// fsTarget.byPath(`/libraries/${options.projectName}.js`) | ||
]).then((res) => res.filter(($)=>$)); | ||
}; | ||
|
||
|
||
/** | ||
* Generate jsdoc-config.json content | ||
* | ||
* @private | ||
* @param {Object} parameters Parameters | ||
* @param {string} parameters.targetPath Path to write any output files | ||
* @param {string} parameters.tmpPath Path to write temporary and debug files | ||
* @param {string} parameters.projectName Project name | ||
* @param {string} parameters.version Project version | ||
* @param {Array} parameters.variants JSDoc variants to be built | ||
* @returns {string} jsdoc-config.json content string | ||
*/ | ||
async function generateJsdocConfig({targetPath, tmpPath, namespace, projectName, version, variants}) { | ||
// Backlash needs to be escaped as double-backslash | ||
// This is not only relevant for win32 paths but also for | ||
// Unix directory names that contain a backslash in their name | ||
const backslashRegex = /\\/g; | ||
|
||
// Resolve path to this script to get the path to the JSDoc extensions folder | ||
const jsdocPath = path.normalize(__dirname); | ||
const pluginPath = path.join(jsdocPath, "lib", "ui5", "plugin.js").replace(backslashRegex, "\\\\"); | ||
const templatePath = path.join(jsdocPath, "lib", "ui5", "template").replace(backslashRegex, "\\\\"); | ||
const destinationPath = path.normalize(tmpPath).replace(backslashRegex, "\\\\"); | ||
const jsapiFilePath = path.join(targetPath, "libraries", projectName + ".js").replace(backslashRegex, "\\\\"); | ||
const apiJsonFolderPath = path.join(tmpPath, "dependency-apis").replace(backslashRegex, "\\\\"); | ||
const apiJsonFilePath = | ||
path.join(targetPath, "test-resources", path.normalize(namespace), "designtime", "api.json") | ||
.replace(backslashRegex, "\\\\"); | ||
|
||
const config = `{ | ||
"plugins": ["${pluginPath}"], | ||
"opts": { | ||
"recurse": true, | ||
"lenient": true, | ||
"template": "${templatePath}", | ||
"ui5": { | ||
"saveSymbols": true | ||
}, | ||
"destination": "${destinationPath}" | ||
}, | ||
"templates": { | ||
"ui5": { | ||
"variants": ${JSON.stringify(variants)}, | ||
"version": "${version}", | ||
"jsapiFile": "${jsapiFilePath}", | ||
"apiJsonFolder": "${apiJsonFolderPath}", | ||
"apiJsonFile": "${apiJsonFilePath}" | ||
} | ||
} | ||
}`; | ||
return config; | ||
} | ||
|
||
/** | ||
* Write jsdoc-config.json to file system | ||
* | ||
* @private | ||
* @param {string} targetDirPath Directory Path to write the jsdoc-config.json file to | ||
* @param {string} config jsdoc-config.json content | ||
* @returns {string} Full path to the written jsdoc-config.json file | ||
*/ | ||
async function writeJsdocConfig(targetDirPath, config) { | ||
const configPath = path.join(targetDirPath, "jsdoc-config.json"); | ||
await writeFile(configPath, config); | ||
return configPath; | ||
} | ||
|
||
|
||
/** | ||
* Execute JSDoc build by spawning JSDoc as an external process | ||
* | ||
* @private | ||
* @param {Object} parameters Parameters | ||
* @param {string} parameters.sourcePath Project resources (input for JSDoc generation) | ||
* @param {string} parameters.configPath Full path to jsdoc-config.json file | ||
* @returns {Promise<undefined>} | ||
*/ | ||
async function buildJsdoc({sourcePath, configPath}) { | ||
const args = [ | ||
require.resolve("jsdoc/jsdoc"), | ||
"-c", | ||
configPath, | ||
"--verbose", | ||
sourcePath | ||
]; | ||
return new Promise((resolve, reject) => { | ||
const child = spawn("node", args, { | ||
stdio: ["ignore", "ignore", process.stderr] | ||
}); | ||
child.on("close", function(code) { | ||
if (code === 0 || code === 1) { | ||
resolve(); | ||
} else { | ||
reject(new Error(`JSDoc child process closed with code ${code}`)); | ||
} | ||
}); | ||
}); | ||
} | ||
|
||
module.exports = jsdocGenerator; | ||
module.exports._generateJsdocConfig = generateJsdocConfig; | ||
module.exports._writeJsdocConfig = writeJsdocConfig; | ||
module.exports._buildJsdoc = buildJsdoc; |
Oops, something went wrong.