-
Notifications
You must be signed in to change notification settings - Fork 94
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(ui5-task-copyright): new task to prepend copyrights to sources (#…
…952) BREAKING CHANGE: new release
- Loading branch information
1 parent
c982231
commit d7e8ad6
Showing
18 changed files
with
535 additions
and
4 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
test/__dist__/* | ||
!test/__dist__/.keepMe |
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 @@ | ||
test |
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,69 @@ | ||
# UI5 task for appending copyright headers for TypeScript, JavaScript and XML files | ||
|
||
> :wave: This is a **community project** and there is no official support for this package! Feel free to use it, open issues, contribute, and help answering questions. | ||
Task for [ui5-builder](https://github.com/SAP/ui5-builder) for appending copyright headers to every TypeScript (`*.ts`), JavaScript (`*.js`), or XML (`*.xml`) source file. | ||
|
||
## Prerequisites | ||
|
||
- Requires at least [`@ui5/[email protected]`](https://sap.github.io/ui5-tooling/v3/pages/CLI/) (to support [`specVersion: "3.0"`](https://sap.github.io/ui5-tooling/pages/Configuration/#specification-version-30)) | ||
|
||
> :warning: **UI5 Tooling Compatibility** | ||
> All releases of this tooling extension using the major version `3` require UI5 Tooling V3. Any previous releases below major version `3` (if available) also support older versions of the UI5 Tooling. But the usage of the latest UI5 Tooling is strongly recommended! | ||
## Install | ||
|
||
```bash | ||
npm install ui5-task-copyright --save-dev | ||
``` | ||
|
||
## Configuration options (in `$yourapp/ui5.yaml`) | ||
|
||
- copyright: `String` | ||
the value of the copyright or the path to a file containing the copyright statement - if not given, the task will be skipped | ||
|
||
- copyrightPlaceholder: `String` (defaults to: `copyright`) | ||
the name of the copyright placeholder to check for in the copyright comments and to replace with the copyright value (will replace all hits of `${copyright}` or `@copyright@`) | ||
|
||
- currentYearPlaceholder: `String` (defaults to: `currentYear`) | ||
the name of the currentYear placeholder in the copyright comments which will be replaced with the currentYear value (will replace all hits of `${currentYear}` or `@currentYear@`) | ||
|
||
- excludePatterns: `Array<String>` | ||
array of paths inside `$yourapp/` to exclude from the minification, e.g. 3-rd party libs in `lib/*`. defaults to an empty array `[]`. | ||
|
||
## Usage | ||
|
||
1. Define the dependency in `$yourapp/package.json`: | ||
|
||
```json | ||
"devDependencies": { | ||
// ... | ||
"ui5-task-copyright": "*" | ||
// ... | ||
} | ||
``` | ||
|
||
2. configure it in `$yourapp/ui5.yaml`: | ||
|
||
```yaml | ||
builder: | ||
customTasks: | ||
- name: ui5-task-copyright | ||
beforeTask: replaceCopyright | ||
configuration: | ||
copyright: "Copyright ${currentYear} UI5 Community" | ||
excludePatterns: | ||
- "thirdparty/" | ||
``` | ||
## How to obtain support | ||
Please use the GitHub bug tracking system to post questions, bug reports or to create pull requests. | ||
## Contributing | ||
Any type of contribution (code contributions, pull requests, issues) to this showcase will be equally appreciated. | ||
## License | ||
This work is [dual-licensed](../../LICENSE) under Apache 2.0 and the Derived Beer-ware License. The official license will be Apache 2.0 but finally you can choose between one of them if you use this work. |
31 changes: 31 additions & 0 deletions
31
packages/ui5-task-copyright/bin/uses-ui5-task-copyright.js
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,31 @@ | ||
#!/usr/bin/env node | ||
|
||
const path = require("path"); | ||
const fs = require("fs"); | ||
const yaml = require("js-yaml"); | ||
|
||
const ui5YamlPath = process.argv[2] || path.join(process.cwd(), "ui5.yaml"); | ||
if (!ui5YamlPath) { | ||
console.error("\x1b[31m[ERROR]\x1b[0m No ui5.yaml provided!"); | ||
process.exit(1); | ||
} | ||
if (!fs.existsSync(ui5YamlPath) || !fs.statSync(ui5YamlPath).isFile()) { | ||
console.error(`\x1b[31m[ERROR]\x1b[0m The ${ui5YamlPath} does not exist!`); | ||
process.exit(1); | ||
} | ||
|
||
try { | ||
const content = fs.readFileSync(ui5YamlPath, "utf-8"); | ||
const ui5Configs = yaml.loadAll(content); | ||
const notFound = (ui5Configs[0]?.builder?.customTasks?.findIndex((task) => task.name === "ui5-task-copyright") || -1) === -1; | ||
if (notFound) { | ||
console.error(`\x1b[31m[ERROR]\x1b[0m ui5-task-copyright is not registered in ${ui5YamlPath}!`); | ||
process.exit(1); | ||
} | ||
} catch (err) { | ||
if (err.name === "YAMLException") { | ||
console.error(`\x1b[31m[ERROR]\x1b[0m Failed to read ${ui5YamlPath}!`); | ||
process.exit(1); | ||
} | ||
throw err; | ||
} |
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,147 @@ | ||
const fs = require("fs"); | ||
|
||
const { parse } = require("@typescript-eslint/typescript-estree"); | ||
const { XMLParser } = require("fast-xml-parser"); | ||
|
||
/** | ||
* Task to append a copyright header for TypeScript, JavaScript and XML files | ||
* @param {object} parameters Parameters | ||
* @param {module:@ui5/logger/Logger} parameters.log Logger instance | ||
* @param {module:@ui5/fs.DuplexCollection} parameters.workspace DuplexCollection to read and write files | ||
* @param {object} parameters.options Options | ||
* @returns {Promise<undefined>} Promise resolving with undefined once data has been written | ||
*/ | ||
module.exports = async ({ log, workspace, options }) => { | ||
// disable task if no copyright is configured | ||
if (!options?.configuration?.copyright) { | ||
return Promise.resolve(); | ||
} | ||
|
||
// determine the copyright and current year placeholders | ||
const { copyrightPlaceholder, currentYearPlaceholder } = Object.assign( | ||
{ | ||
copyrightPlaceholder: "copyright", | ||
currentYearPlaceholder: "currentYear", | ||
}, | ||
options.configuration | ||
); | ||
|
||
// create regular expressions for the placeholders | ||
const copyrightRegExp = new RegExp(`(?:\\$\\{${copyrightPlaceholder}\\}|@${copyrightPlaceholder}@)`, "g"); | ||
const currentYearRegExp = new RegExp(`(?:\\$\\{${currentYearPlaceholder}\\}|@${currentYearPlaceholder}@)`, "g"); | ||
|
||
// determine the actual copyright or default it | ||
let { copyright, excludePatterns } = Object.assign( | ||
{ | ||
copyright: `\${${copyrightPlaceholder}}`, | ||
}, | ||
options.configuration | ||
); | ||
|
||
// check if the file exists (if copyright is a file path) | ||
if (fs.existsSync(copyright)) { | ||
log.verbose(`Reading copyright from file ${copyright}...`); | ||
copyright = fs.readFileSync(copyright, "utf-8").trim(); | ||
} | ||
|
||
// Replace optional placeholder ${currentYear} with the current year | ||
const copyrightString = copyright.replace(currentYearRegExp, new Date().getFullYear()); | ||
|
||
// process the script resources | ||
const scriptResources = await workspace.byGlob(`**/*.+(ts|js)`); | ||
if (scriptResources.length > 0) { | ||
await Promise.all( | ||
scriptResources.map(async (resource) => { | ||
const resourcePath = resource.getPath(); | ||
|
||
// check if the resource should be excluded | ||
if (excludePatterns && excludePatterns.some((pattern) => resourcePath.includes(pattern))) { | ||
return; | ||
} | ||
|
||
// detailed logging | ||
log.verbose("Processing file " + resourcePath); | ||
|
||
// read the resource and parse the code | ||
const code = await resource.getString(); | ||
const ast = parse(code, { | ||
filePath: resourcePath, | ||
loc: true, | ||
range: true, | ||
comment: true, | ||
}); | ||
|
||
// find the first comment that starts with "!" and has a copyright placeholder | ||
const copyrightComment = ast.comments.find((comment) => { | ||
return comment.type === "Block" && comment.value.startsWith("!") && copyrightRegExp.test(comment.value); | ||
}); | ||
|
||
// preprend the comment or replace the copyight placeholder | ||
const copyrightForJS = copyrightString | ||
.split(/\r?\n/) | ||
.map((line) => line.trimEnd()) | ||
.join("\n * "); | ||
if (!copyrightComment) { | ||
await resource.setString(`/*!\n * ${copyrightForJS}\n */\n${code}`); | ||
} else { | ||
await resource.setString(code.replace(copyrightRegExp, copyrightForJS)); | ||
} | ||
|
||
// write the resource | ||
await workspace.write(resource); | ||
}) | ||
); | ||
} | ||
|
||
// process the xml resources | ||
const xmlResources = await workspace.byGlob(`**/*.xml`); | ||
if (xmlResources.length > 0) { | ||
// use fast-xml-parser to parse the xml files (including comments) | ||
const parser = new XMLParser({ | ||
commentPropName: "#comment", | ||
}); | ||
await Promise.all( | ||
xmlResources.map(async (resource) => { | ||
const resourcePath = resource.getPath(); | ||
|
||
// check if the resource should be excluded | ||
if (excludePatterns && excludePatterns.some((pattern) => resourcePath.includes(pattern))) { | ||
return; | ||
} | ||
|
||
// detailed logging | ||
log.verbose("Processing file " + resourcePath); | ||
|
||
// read the resource and parse the xml | ||
const code = await resource.getString(); | ||
const xml = parser.parse(code); | ||
|
||
// preprend the comment or replace the copyight placeholder | ||
const copyrightForXML = copyrightString | ||
.split(/\r?\n/) | ||
.map((line) => line.trimEnd()) | ||
.join("\n "); | ||
if (!(xml["#comment"] && copyrightRegExp.test(xml["#comment"]))) { | ||
await resource.setString(`<!--\n ${copyrightForXML}\n-->\n${code}`); | ||
} else { | ||
await resource.setString(code.replace(copyrightRegExp, copyrightForXML)); | ||
} | ||
|
||
// write the resource | ||
await workspace.write(resource); | ||
}) | ||
); | ||
} | ||
}; | ||
|
||
/** | ||
* Callback function to define the list of required dependencies | ||
* @returns {Promise<Set>} | ||
* Promise resolving with a Set containing all dependencies | ||
* that should be made available to the task. | ||
* UI5 Tooling will ensure that those dependencies have been | ||
* built before executing the task. | ||
*/ | ||
module.exports.determineRequiredDependencies = async function () { | ||
return new Set(); | ||
}; |
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,38 @@ | ||
{ | ||
"name": "ui5-task-copyright", | ||
"version": "2.0.0", | ||
"description": "UI5 task for appending copyright headers for TypeScript, JavaScript and XML files", | ||
"author": "Peter Muessig", | ||
"license": "Apache-2.0", | ||
"homepage": "https://github.com/ui5-community/ui5-ecosystem-showcase/tree/main/packages/ui5-task-copyright#readme", | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/ui5-community/ui5-ecosystem-showcase.git", | ||
"directory": "packages/ui5-task-copyright" | ||
}, | ||
"bin": { | ||
"uses-ui5-task-copyright": "./bin/uses-ui5-task-copyright.js" | ||
}, | ||
"scripts": { | ||
"lint": "eslint lib", | ||
"test": "ava" | ||
}, | ||
"ava": { | ||
"files": [ | ||
"test/**/*", | ||
"!test/__assets__/**/*", | ||
"!test/__dist__/**/*" | ||
], | ||
"verbose": true, | ||
"timeout": "5m" | ||
}, | ||
"devDependencies": { | ||
"@ui5/cli": "^3.8.0", | ||
"ava": "^5.3.1" | ||
}, | ||
"dependencies": { | ||
"@typescript-eslint/typescript-estree": "^7.0.1", | ||
"fast-xml-parser": "^4.3.3", | ||
"js-yaml": "^4.1.0" | ||
} | ||
} |
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,24 @@ | ||
specVersion: "3.0" | ||
metadata: | ||
name: ui5.ecosystem.demo.tsapp | ||
type: application | ||
framework: | ||
name: OpenUI5 | ||
version: "1.120.1" | ||
libraries: | ||
- name: sap.m | ||
- name: sap.ui.core | ||
- name: sap.ui.unified | ||
- name: themelib_sap_horizon | ||
builder: | ||
customTasks: | ||
- name: ui5-tooling-transpile-task | ||
afterTask: replaceVersion | ||
configuration: | ||
generateDts: true | ||
generateTsInterfaces: true | ||
omitTSFromBuildResult: false | ||
- name: ui5-task-copyright | ||
beforeTask: replaceCopyright | ||
configuration: | ||
copyright: ./copyright.txt |
25 changes: 25 additions & 0 deletions
25
packages/ui5-task-copyright/test/__assets__/ui5.inline.yaml
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,25 @@ | ||
specVersion: "3.0" | ||
metadata: | ||
name: ui5.ecosystem.demo.tsapp | ||
type: application | ||
framework: | ||
name: OpenUI5 | ||
version: "1.120.1" | ||
libraries: | ||
- name: sap.m | ||
- name: sap.ui.core | ||
- name: sap.ui.unified | ||
- name: themelib_sap_horizon | ||
builder: | ||
customTasks: | ||
- name: ui5-tooling-transpile-task | ||
afterTask: replaceVersion | ||
configuration: | ||
generateDts: true | ||
generateTsInterfaces: true | ||
omitTSFromBuildResult: false | ||
- name: ui5-task-copyright | ||
beforeTask: replaceCopyright | ||
configuration: | ||
copyright: "Copyright ${currentYear} UI5 Community | ||
\nAll rights reserved." |
22 changes: 22 additions & 0 deletions
22
packages/ui5-task-copyright/test/__assets__/ui5.no.copyright.yaml
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,22 @@ | ||
specVersion: "3.0" | ||
metadata: | ||
name: ui5.ecosystem.demo.tsapp | ||
type: application | ||
framework: | ||
name: OpenUI5 | ||
version: "1.120.1" | ||
libraries: | ||
- name: sap.m | ||
- name: sap.ui.core | ||
- name: sap.ui.unified | ||
- name: themelib_sap_horizon | ||
builder: | ||
customTasks: | ||
- name: ui5-tooling-transpile-task | ||
afterTask: replaceVersion | ||
configuration: | ||
generateDts: true | ||
generateTsInterfaces: true | ||
omitTSFromBuildResult: false | ||
- name: ui5-task-copyright | ||
beforeTask: replaceCopyright |
Empty file.
Oops, something went wrong.