├── .npmignore
├── .npmrc
├── integration-test
├── wcmio-archetype-module
│ ├── .nvmrc
│ ├── .npmrc
│ ├── .gitignore
│ ├── expected-result
│ │ ├── myproject1.all
│ │ │ ├── css.txt
│ │ │ ├── js.txt
│ │ │ └── .content.xml
│ │ └── myproject1.app
│ │ │ ├── js.txt
│ │ │ ├── css.txt
│ │ │ ├── resources
│ │ │ └── img
│ │ │ │ └── favicon.ico
│ │ │ └── .content.xml
│ ├── src
│ │ ├── index.scss
│ │ ├── components
│ │ │ ├── image
│ │ │ │ └── image.scss
│ │ │ └── customcarousel
│ │ │ │ ├── customcarousel.js
│ │ │ │ └── customcarousel.hbs
│ │ ├── index.js
│ │ └── index.hbs
│ ├── config
│ │ ├── webpack
│ │ │ ├── base
│ │ │ │ ├── setup
│ │ │ │ │ ├── index.js
│ │ │ │ │ ├── entryConfig.js
│ │ │ │ │ └── outputConfig.js
│ │ │ │ ├── tasks
│ │ │ │ │ ├── index.js
│ │ │ │ │ ├── es6.js
│ │ │ │ │ ├── html.js
│ │ │ │ │ ├── clean.js
│ │ │ │ │ ├── handlebars.js
│ │ │ │ │ ├── copy.js
│ │ │ │ │ └── scss.js
│ │ │ │ └── index.js
│ │ │ ├── prod
│ │ │ │ └── index.js
│ │ │ └── dev
│ │ │ │ ├── server.js
│ │ │ │ └── index.js
│ │ └── path.config.js
│ ├── public
│ │ └── img
│ │ │ └── favicon.ico
│ ├── .babelrc
│ ├── README.md
│ ├── webpack.config.babel.js
│ ├── clientlib.config.js
│ ├── package.json
│ ├── compare-results.js
│ └── pom.xml
├── wcmio-archetype-commonjs
│ ├── .nvmrc
│ ├── .npmrc
│ ├── .gitignore
│ ├── expected-result
│ │ ├── myproject1.all
│ │ │ ├── js.txt
│ │ │ └── css.txt
│ │ ├── myproject1.app
│ │ │ ├── js.txt
│ │ │ ├── css.txt
│ │ │ └── resources
│ │ │ │ └── img
│ │ │ │ └── favicon.ico
│ │ ├── myproject1.app.json
│ │ └── myproject1.all.json
│ ├── src
│ │ ├── index.scss
│ │ ├── components
│ │ │ ├── image
│ │ │ │ └── image.scss
│ │ │ └── customcarousel
│ │ │ │ ├── customcarousel.js
│ │ │ │ └── customcarousel.hbs
│ │ ├── index.js
│ │ └── index.hbs
│ ├── config
│ │ ├── webpack
│ │ │ ├── base
│ │ │ │ ├── setup
│ │ │ │ │ ├── index.js
│ │ │ │ │ ├── entryConfig.js
│ │ │ │ │ └── outputConfig.js
│ │ │ │ ├── tasks
│ │ │ │ │ ├── index.js
│ │ │ │ │ ├── es6.js
│ │ │ │ │ ├── html.js
│ │ │ │ │ ├── clean.js
│ │ │ │ │ ├── handlebars.js
│ │ │ │ │ ├── copy.js
│ │ │ │ │ └── scss.js
│ │ │ │ └── index.js
│ │ │ ├── prod
│ │ │ │ └── index.js
│ │ │ └── dev
│ │ │ │ ├── server.js
│ │ │ │ └── index.js
│ │ └── path.config.js
│ ├── public
│ │ └── img
│ │ │ └── favicon.ico
│ ├── .babelrc
│ ├── README.md
│ ├── webpack.config.babel.js
│ ├── clientlib.config.js
│ ├── package.json
│ ├── compare-results.mjs
│ └── pom.xml
└── wcmio-archetype-module-cjs
│ ├── .nvmrc
│ ├── .npmrc
│ ├── .gitignore
│ ├── expected-result
│ ├── myproject1.all
│ │ ├── css.txt
│ │ ├── js.txt
│ │ └── .content.xml
│ └── myproject1.app
│ │ ├── css.txt
│ │ ├── js.txt
│ │ ├── resources
│ │ └── img
│ │ │ └── favicon.ico
│ │ └── .content.xml
│ ├── src
│ ├── index.scss
│ ├── components
│ │ ├── image
│ │ │ └── image.scss
│ │ └── customcarousel
│ │ │ ├── customcarousel.js
│ │ │ └── customcarousel.hbs
│ ├── index.js
│ └── index.hbs
│ ├── config
│ ├── webpack
│ │ ├── base
│ │ │ ├── setup
│ │ │ │ ├── index.js
│ │ │ │ ├── entryConfig.js
│ │ │ │ └── outputConfig.js
│ │ │ ├── tasks
│ │ │ │ ├── index.js
│ │ │ │ ├── es6.js
│ │ │ │ ├── html.js
│ │ │ │ ├── clean.js
│ │ │ │ ├── handlebars.js
│ │ │ │ ├── copy.js
│ │ │ │ └── scss.js
│ │ │ └── index.js
│ │ ├── prod
│ │ │ └── index.js
│ │ └── dev
│ │ │ ├── server.js
│ │ │ └── index.js
│ └── path.config.js
│ ├── public
│ └── img
│ │ └── favicon.ico
│ ├── .babelrc
│ ├── README.md
│ ├── webpack.config.babel.js
│ ├── clientlib.config.cjs
│ ├── package.json
│ ├── compare-results.js
│ └── pom.xml
├── test
├── src
│ └── frontend
│ │ ├── css
│ │ ├── grid.less
│ │ ├── styling.css
│ │ └── lib.css
│ │ ├── secondapp
│ │ ├── main.css
│ │ └── js
│ │ │ └── lib.js
│ │ ├── resources
│ │ ├── notice.txt
│ │ └── template.html
│ │ └── js
│ │ ├── app.js
│ │ └── libs
│ │ ├── mylib.min.js
│ │ ├── mylib.js
│ │ └── mylib.min.js.map
├── expected
│ └── clientlibs-root
│ │ ├── test.base.apps.five
│ │ ├── css.txt
│ │ ├── js.txt
│ │ ├── style
│ │ │ └── main.css
│ │ ├── js
│ │ │ └── secondapp-lib.js
│ │ └── resources
│ │ │ └── template.html
│ │ ├── redirectOutputTestWithXML
│ │ ├── css.txt
│ │ ├── js.txt
│ │ ├── style
│ │ │ └── main.css
│ │ ├── js
│ │ │ └── secondapp-lib.js
│ │ ├── resources
│ │ │ └── template.html
│ │ └── .content.xml
│ │ ├── test.base.apps.secondapp
│ │ ├── css.txt
│ │ ├── js.txt
│ │ ├── style
│ │ │ └── main.css
│ │ ├── js
│ │ │ └── secondapp-lib.js
│ │ └── resources
│ │ │ └── template.html
│ │ ├── test.base.apps.customProperties
│ │ ├── css.txt
│ │ ├── js.txt
│ │ ├── style
│ │ │ └── main.css
│ │ ├── js
│ │ │ └── secondapp-lib.js
│ │ ├── resources
│ │ │ └── template.html
│ │ └── .content.xml
│ │ ├── myPrestructuredLibrary
│ │ ├── css
│ │ │ ├── vendor
│ │ │ │ └── main.css
│ │ │ └── style
│ │ │ │ ├── styling.css
│ │ │ │ └── lib.css
│ │ ├── js.txt
│ │ ├── css.txt
│ │ └── js
│ │ │ ├── app.js
│ │ │ └── libs
│ │ │ ├── mylib.min.js
│ │ │ ├── mylib.js
│ │ │ └── mylib.min.js.map
│ │ ├── test.base.apps.fourth
│ │ ├── css
│ │ │ ├── vendor
│ │ │ │ └── main.css
│ │ │ └── style
│ │ │ │ ├── styling.css
│ │ │ │ └── lib.css
│ │ ├── js.txt
│ │ ├── css.txt
│ │ └── js
│ │ │ ├── app.js
│ │ │ └── libs
│ │ │ ├── mylib.min.js
│ │ │ ├── mylib.js
│ │ │ └── mylib.min.js.map
│ │ ├── test.base.apps.mainapp
│ │ ├── css.txt
│ │ ├── css
│ │ │ ├── styling.css
│ │ │ └── lib.css
│ │ ├── js.txt
│ │ └── js
│ │ │ ├── app.js
│ │ │ └── libs
│ │ │ ├── mylib.min.js
│ │ │ └── mylib.min.js.map
│ │ ├── test.base.apps.customPropertiesNotAllowed
│ │ ├── css.txt
│ │ ├── js.txt
│ │ ├── style
│ │ │ └── main.css
│ │ ├── js
│ │ │ └── secondapp-lib.js
│ │ ├── resources
│ │ │ └── template.html
│ │ └── .content.xml
│ │ ├── test.base.apps.ignoreOption
│ │ ├── js.txt
│ │ └── js
│ │ │ ├── app.js
│ │ │ └── libs
│ │ │ └── mylib.js
│ │ ├── test.base.apps.serializationFormatXML
│ │ ├── css.txt
│ │ ├── js.txt
│ │ ├── style
│ │ │ └── main.css
│ │ ├── js
│ │ │ └── secondapp-lib.js
│ │ ├── resources
│ │ │ └── template.html
│ │ └── .content.xml
│ │ ├── test.base.apps.withLessFiles
│ │ ├── css
│ │ │ ├── grid.less
│ │ │ ├── styling.css
│ │ │ └── lib.css
│ │ └── css.txt
│ │ ├── test.base.apps.serializationFormatSlingXML
│ │ ├── css.txt
│ │ ├── js.txt
│ │ ├── style
│ │ │ └── main.css
│ │ ├── js
│ │ │ └── secondapp-lib.js
│ │ └── resources
│ │ │ └── template.html
│ │ ├── test.base.apps.thirdapp
│ │ └── notice.txt
│ │ ├── test.base.apps.fourth.json
│ │ ├── test.base.apps.thirdapp.json
│ │ ├── test.base.apps.fourthWithOutputPath.json
│ │ ├── test.base.apps.secondapp.json
│ │ ├── test.base.apps.five.json
│ │ ├── test.base.apps.mainapp.json
│ │ └── test.base.apps.serializationFormatSlingXML.xml
├── TestCase.test.js
└── clientlib.config.js
├── .gitignore
├── .github
├── release-drafter.yml
├── workflows
│ ├── release-drafter.yml
│ ├── build.yml
│ ├── release.yml
│ └── integration-tests.yml
└── renovate.json
├── .gitattributes
├── package.json
├── bin
└── clientlib-cli.js
├── LICENSE
├── README.md
└── lib
└── clientlib.js
/.npmignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | npm*.log
3 |
--------------------------------------------------------------------------------
/.npmrc:
--------------------------------------------------------------------------------
1 | registry=https://registry.npmjs.org/
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-module/.nvmrc:
--------------------------------------------------------------------------------
1 | 24.11.0
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-commonjs/.nvmrc:
--------------------------------------------------------------------------------
1 | 24.11.0
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-module-cjs/.nvmrc:
--------------------------------------------------------------------------------
1 | 24.11.0
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-commonjs/.npmrc:
--------------------------------------------------------------------------------
1 | save-exact=true
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-module/.npmrc:
--------------------------------------------------------------------------------
1 | save-exact=true
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-module-cjs/.npmrc:
--------------------------------------------------------------------------------
1 | save-exact=true
--------------------------------------------------------------------------------
/test/src/frontend/css/grid.less:
--------------------------------------------------------------------------------
1 | .grid {
2 | display: flex;
3 | }
--------------------------------------------------------------------------------
/test/src/frontend/css/styling.css:
--------------------------------------------------------------------------------
1 | body {
2 | color: #000;
3 | }
--------------------------------------------------------------------------------
/test/src/frontend/secondapp/main.css:
--------------------------------------------------------------------------------
1 | body {
2 | color: #000;
3 | }
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-module/.gitignore:
--------------------------------------------------------------------------------
1 | dist/
2 | result/
3 | node/
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-commonjs/.gitignore:
--------------------------------------------------------------------------------
1 | dist/
2 | result/
3 | node/
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-module-cjs/.gitignore:
--------------------------------------------------------------------------------
1 | dist/
2 | result/
3 | node/
--------------------------------------------------------------------------------
/test/expected/clientlibs-root/test.base.apps.five/css.txt:
--------------------------------------------------------------------------------
1 | #base=style
2 |
3 | main.css
--------------------------------------------------------------------------------
/test/expected/clientlibs-root/redirectOutputTestWithXML/css.txt:
--------------------------------------------------------------------------------
1 | #base=style
2 |
3 | main.css
--------------------------------------------------------------------------------
/test/expected/clientlibs-root/test.base.apps.five/js.txt:
--------------------------------------------------------------------------------
1 | #base=js
2 |
3 | secondapp-lib.js
--------------------------------------------------------------------------------
/test/expected/clientlibs-root/test.base.apps.secondapp/css.txt:
--------------------------------------------------------------------------------
1 | #base=style
2 |
3 | main.css
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-commonjs/expected-result/myproject1.all/js.txt:
--------------------------------------------------------------------------------
1 | #base=js
2 |
3 |
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-module/expected-result/myproject1.all/css.txt:
--------------------------------------------------------------------------------
1 | #base=css
2 |
3 |
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-module/expected-result/myproject1.all/js.txt:
--------------------------------------------------------------------------------
1 | #base=js
2 |
3 |
--------------------------------------------------------------------------------
/test/expected/clientlibs-root/redirectOutputTestWithXML/js.txt:
--------------------------------------------------------------------------------
1 | #base=js
2 |
3 | secondapp-lib.js
--------------------------------------------------------------------------------
/test/expected/clientlibs-root/test.base.apps.customProperties/css.txt:
--------------------------------------------------------------------------------
1 | #base=style
2 |
3 | main.css
--------------------------------------------------------------------------------
/test/expected/clientlibs-root/test.base.apps.five/style/main.css:
--------------------------------------------------------------------------------
1 | body {
2 | color: #000;
3 | }
--------------------------------------------------------------------------------
/test/expected/clientlibs-root/test.base.apps.secondapp/js.txt:
--------------------------------------------------------------------------------
1 | #base=js
2 |
3 | secondapp-lib.js
--------------------------------------------------------------------------------
/test/src/frontend/css/lib.css:
--------------------------------------------------------------------------------
1 | /* lib styles here */
2 |
3 | .lib {
4 | font-size: 30px;
5 | }
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-commonjs/expected-result/myproject1.all/css.txt:
--------------------------------------------------------------------------------
1 | #base=css
2 |
3 |
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-commonjs/expected-result/myproject1.app/js.txt:
--------------------------------------------------------------------------------
1 | #base=js
2 |
3 | app.js
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-module-cjs/expected-result/myproject1.all/css.txt:
--------------------------------------------------------------------------------
1 | #base=css
2 |
3 |
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-module-cjs/expected-result/myproject1.all/js.txt:
--------------------------------------------------------------------------------
1 | #base=js
2 |
3 |
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-module/expected-result/myproject1.app/js.txt:
--------------------------------------------------------------------------------
1 | #base=js
2 |
3 | app.js
--------------------------------------------------------------------------------
/test/expected/clientlibs-root/myPrestructuredLibrary/css/vendor/main.css:
--------------------------------------------------------------------------------
1 | body {
2 | color: #000;
3 | }
--------------------------------------------------------------------------------
/test/expected/clientlibs-root/redirectOutputTestWithXML/style/main.css:
--------------------------------------------------------------------------------
1 | body {
2 | color: #000;
3 | }
--------------------------------------------------------------------------------
/test/expected/clientlibs-root/test.base.apps.customProperties/js.txt:
--------------------------------------------------------------------------------
1 | #base=js
2 |
3 | secondapp-lib.js
--------------------------------------------------------------------------------
/test/expected/clientlibs-root/test.base.apps.fourth/css/vendor/main.css:
--------------------------------------------------------------------------------
1 | body {
2 | color: #000;
3 | }
--------------------------------------------------------------------------------
/test/expected/clientlibs-root/test.base.apps.mainapp/css.txt:
--------------------------------------------------------------------------------
1 | #base=css
2 |
3 | styling.css
4 | lib.css
--------------------------------------------------------------------------------
/test/expected/clientlibs-root/test.base.apps.mainapp/css/styling.css:
--------------------------------------------------------------------------------
1 | body {
2 | color: #000;
3 | }
--------------------------------------------------------------------------------
/test/expected/clientlibs-root/test.base.apps.secondapp/style/main.css:
--------------------------------------------------------------------------------
1 | body {
2 | color: #000;
3 | }
--------------------------------------------------------------------------------
/test/src/frontend/resources/notice.txt:
--------------------------------------------------------------------------------
1 | This is a txt file and the content does not make any sense...
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-commonjs/expected-result/myproject1.app/css.txt:
--------------------------------------------------------------------------------
1 | #base=css
2 |
3 | app.css
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-module-cjs/expected-result/myproject1.app/css.txt:
--------------------------------------------------------------------------------
1 | #base=css
2 |
3 | app.css
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-module-cjs/expected-result/myproject1.app/js.txt:
--------------------------------------------------------------------------------
1 | #base=js
2 |
3 | app.js
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-module/expected-result/myproject1.app/css.txt:
--------------------------------------------------------------------------------
1 | #base=css
2 |
3 | app.css
--------------------------------------------------------------------------------
/test/expected/clientlibs-root/myPrestructuredLibrary/css/style/styling.css:
--------------------------------------------------------------------------------
1 | body {
2 | color: #000;
3 | }
--------------------------------------------------------------------------------
/test/expected/clientlibs-root/test.base.apps.customProperties/style/main.css:
--------------------------------------------------------------------------------
1 | body {
2 | color: #000;
3 | }
--------------------------------------------------------------------------------
/test/expected/clientlibs-root/test.base.apps.customPropertiesNotAllowed/css.txt:
--------------------------------------------------------------------------------
1 | #base=style
2 |
3 | main.css
--------------------------------------------------------------------------------
/test/expected/clientlibs-root/test.base.apps.fourth/css/style/styling.css:
--------------------------------------------------------------------------------
1 | body {
2 | color: #000;
3 | }
--------------------------------------------------------------------------------
/test/expected/clientlibs-root/test.base.apps.ignoreOption/js.txt:
--------------------------------------------------------------------------------
1 | #base=js
2 |
3 | app.js
4 | libs/mylib.js
--------------------------------------------------------------------------------
/test/expected/clientlibs-root/test.base.apps.mainapp/js.txt:
--------------------------------------------------------------------------------
1 | #base=js
2 |
3 | app.js
4 | libs/mylib.min.js
--------------------------------------------------------------------------------
/test/expected/clientlibs-root/test.base.apps.serializationFormatXML/css.txt:
--------------------------------------------------------------------------------
1 | #base=style
2 |
3 | main.css
--------------------------------------------------------------------------------
/test/expected/clientlibs-root/test.base.apps.serializationFormatXML/js.txt:
--------------------------------------------------------------------------------
1 | #base=js
2 |
3 | secondapp-lib.js
--------------------------------------------------------------------------------
/test/expected/clientlibs-root/test.base.apps.withLessFiles/css/grid.less:
--------------------------------------------------------------------------------
1 | .grid {
2 | display: flex;
3 | }
--------------------------------------------------------------------------------
/test/expected/clientlibs-root/test.base.apps.withLessFiles/css/styling.css:
--------------------------------------------------------------------------------
1 | body {
2 | color: #000;
3 | }
--------------------------------------------------------------------------------
/test/src/frontend/js/app.js:
--------------------------------------------------------------------------------
1 |
2 | "use strict";
3 | var Test = function() {
4 | this.test = "test";
5 | };
--------------------------------------------------------------------------------
/test/expected/clientlibs-root/test.base.apps.customPropertiesNotAllowed/js.txt:
--------------------------------------------------------------------------------
1 | #base=js
2 |
3 | secondapp-lib.js
--------------------------------------------------------------------------------
/test/expected/clientlibs-root/test.base.apps.serializationFormatSlingXML/css.txt:
--------------------------------------------------------------------------------
1 | #base=style
2 |
3 | main.css
--------------------------------------------------------------------------------
/test/expected/clientlibs-root/test.base.apps.serializationFormatSlingXML/js.txt:
--------------------------------------------------------------------------------
1 | #base=js
2 |
3 | secondapp-lib.js
--------------------------------------------------------------------------------
/test/expected/clientlibs-root/test.base.apps.serializationFormatXML/style/main.css:
--------------------------------------------------------------------------------
1 | body {
2 | color: #000;
3 | }
--------------------------------------------------------------------------------
/test/expected/clientlibs-root/test.base.apps.customPropertiesNotAllowed/style/main.css:
--------------------------------------------------------------------------------
1 | body {
2 | color: #000;
3 | }
--------------------------------------------------------------------------------
/test/expected/clientlibs-root/test.base.apps.serializationFormatSlingXML/style/main.css:
--------------------------------------------------------------------------------
1 | body {
2 | color: #000;
3 | }
--------------------------------------------------------------------------------
/test/src/frontend/secondapp/js/lib.js:
--------------------------------------------------------------------------------
1 |
2 | "use strict";
3 | var Test = function() {
4 | this.test = "test";
5 | };
--------------------------------------------------------------------------------
/test/expected/clientlibs-root/myPrestructuredLibrary/js.txt:
--------------------------------------------------------------------------------
1 | #base=js
2 |
3 | app.js
4 | libs/mylib.js
5 | libs/mylib.min.js
--------------------------------------------------------------------------------
/test/expected/clientlibs-root/test.base.apps.fourth/js.txt:
--------------------------------------------------------------------------------
1 | #base=js
2 |
3 | app.js
4 | libs/mylib.js
5 | libs/mylib.min.js
--------------------------------------------------------------------------------
/test/expected/clientlibs-root/test.base.apps.withLessFiles/css.txt:
--------------------------------------------------------------------------------
1 | #base=css
2 |
3 | grid.less
4 | styling.css
5 | lib.css
--------------------------------------------------------------------------------
/test/expected/clientlibs-root/test.base.apps.thirdapp/notice.txt:
--------------------------------------------------------------------------------
1 | This is a txt file and the content does not make any sense...
--------------------------------------------------------------------------------
/test/expected/clientlibs-root/test.base.apps.fourth/css.txt:
--------------------------------------------------------------------------------
1 | #base=css
2 |
3 | style/lib.css
4 | style/styling.css
5 | vendor/main.css
--------------------------------------------------------------------------------
/test/expected/clientlibs-root/test.base.apps.mainapp/css/lib.css:
--------------------------------------------------------------------------------
1 | /* lib styles here */
2 |
3 | .lib {
4 | font-size: 30px;
5 | }
--------------------------------------------------------------------------------
/test/src/frontend/js/libs/mylib.min.js:
--------------------------------------------------------------------------------
1 | "use strict";var MyLib=function(){this.test="MyLib"};
2 | //# sourceMappingURL=mylib.min.js.map
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-commonjs/src/index.scss:
--------------------------------------------------------------------------------
1 | // Externals
2 | @import "~bootstrap/scss/bootstrap";
3 |
4 | // Components
5 |
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-module/src/index.scss:
--------------------------------------------------------------------------------
1 | // Externals
2 | @import "~bootstrap/scss/bootstrap";
3 |
4 | // Components
5 |
--------------------------------------------------------------------------------
/test/expected/clientlibs-root/myPrestructuredLibrary/css.txt:
--------------------------------------------------------------------------------
1 | #base=css
2 |
3 | style/lib.css
4 | style/styling.css
5 | vendor/main.css
--------------------------------------------------------------------------------
/test/expected/clientlibs-root/myPrestructuredLibrary/css/style/lib.css:
--------------------------------------------------------------------------------
1 | /* lib styles here */
2 |
3 | .lib {
4 | font-size: 30px;
5 | }
--------------------------------------------------------------------------------
/test/expected/clientlibs-root/test.base.apps.fourth/css/style/lib.css:
--------------------------------------------------------------------------------
1 | /* lib styles here */
2 |
3 | .lib {
4 | font-size: 30px;
5 | }
--------------------------------------------------------------------------------
/test/expected/clientlibs-root/test.base.apps.withLessFiles/css/lib.css:
--------------------------------------------------------------------------------
1 | /* lib styles here */
2 |
3 | .lib {
4 | font-size: 30px;
5 | }
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-module-cjs/src/index.scss:
--------------------------------------------------------------------------------
1 | // Externals
2 | @import "~bootstrap/scss/bootstrap";
3 |
4 | // Components
5 |
--------------------------------------------------------------------------------
/test/expected/clientlibs-root/myPrestructuredLibrary/js/app.js:
--------------------------------------------------------------------------------
1 |
2 | "use strict";
3 | var Test = function() {
4 | this.test = "test";
5 | };
--------------------------------------------------------------------------------
/test/expected/clientlibs-root/test.base.apps.fourth/js/app.js:
--------------------------------------------------------------------------------
1 |
2 | "use strict";
3 | var Test = function() {
4 | this.test = "test";
5 | };
--------------------------------------------------------------------------------
/test/expected/clientlibs-root/test.base.apps.mainapp/js/app.js:
--------------------------------------------------------------------------------
1 |
2 | "use strict";
3 | var Test = function() {
4 | this.test = "test";
5 | };
--------------------------------------------------------------------------------
/test/expected/clientlibs-root/test.base.apps.five/js/secondapp-lib.js:
--------------------------------------------------------------------------------
1 |
2 | "use strict";
3 | var Test = function() {
4 | this.test = "test";
5 | };
--------------------------------------------------------------------------------
/test/expected/clientlibs-root/test.base.apps.ignoreOption/js/app.js:
--------------------------------------------------------------------------------
1 |
2 | "use strict";
3 | var Test = function() {
4 | this.test = "test";
5 | };
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-commonjs/config/webpack/base/setup/index.js:
--------------------------------------------------------------------------------
1 | export * from "./entryConfig.js";
2 | export * from "./outputConfig.js";
3 |
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-module/config/webpack/base/setup/index.js:
--------------------------------------------------------------------------------
1 | export * from "./entryConfig.js";
2 | export * from "./outputConfig.js";
3 |
--------------------------------------------------------------------------------
/test/expected/clientlibs-root/test.base.apps.secondapp/js/secondapp-lib.js:
--------------------------------------------------------------------------------
1 |
2 | "use strict";
3 | var Test = function() {
4 | this.test = "test";
5 | };
--------------------------------------------------------------------------------
/test/src/frontend/js/libs/mylib.js:
--------------------------------------------------------------------------------
1 |
2 | "use strict";
3 | var MyLib = function() {
4 | this.test = "MyLib";
5 | };
6 | //# sourceMappingURL=mylib.js.map
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-module-cjs/config/webpack/base/setup/index.js:
--------------------------------------------------------------------------------
1 | export * from "./entryConfig.js";
2 | export * from "./outputConfig.js";
3 |
--------------------------------------------------------------------------------
/test/expected/clientlibs-root/redirectOutputTestWithXML/js/secondapp-lib.js:
--------------------------------------------------------------------------------
1 |
2 | "use strict";
3 | var Test = function() {
4 | this.test = "test";
5 | };
--------------------------------------------------------------------------------
/test/expected/clientlibs-root/test.base.apps.customProperties/js/secondapp-lib.js:
--------------------------------------------------------------------------------
1 |
2 | "use strict";
3 | var Test = function() {
4 | this.test = "test";
5 | };
--------------------------------------------------------------------------------
/test/expected/clientlibs-root/myPrestructuredLibrary/js/libs/mylib.min.js:
--------------------------------------------------------------------------------
1 | "use strict";var MyLib=function(){this.test="MyLib"};
2 | //# sourceMappingURL=mylib.min.js.map
--------------------------------------------------------------------------------
/test/expected/clientlibs-root/test.base.apps.fourth/js/libs/mylib.min.js:
--------------------------------------------------------------------------------
1 | "use strict";var MyLib=function(){this.test="MyLib"};
2 | //# sourceMappingURL=mylib.min.js.map
--------------------------------------------------------------------------------
/test/expected/clientlibs-root/test.base.apps.mainapp/js/libs/mylib.min.js:
--------------------------------------------------------------------------------
1 | "use strict";var MyLib=function(){this.test="MyLib"};
2 | //# sourceMappingURL=mylib.min.js.map
--------------------------------------------------------------------------------
/test/expected/clientlibs-root/test.base.apps.serializationFormatXML/js/secondapp-lib.js:
--------------------------------------------------------------------------------
1 |
2 | "use strict";
3 | var Test = function() {
4 | this.test = "test";
5 | };
--------------------------------------------------------------------------------
/test/expected/clientlibs-root/test.base.apps.customPropertiesNotAllowed/js/secondapp-lib.js:
--------------------------------------------------------------------------------
1 |
2 | "use strict";
3 | var Test = function() {
4 | this.test = "test";
5 | };
--------------------------------------------------------------------------------
/test/expected/clientlibs-root/test.base.apps.serializationFormatSlingXML/js/secondapp-lib.js:
--------------------------------------------------------------------------------
1 |
2 | "use strict";
3 | var Test = function() {
4 | this.test = "test";
5 | };
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-commonjs/config/webpack/prod/index.js:
--------------------------------------------------------------------------------
1 | export const prodConfig = {
2 | devtool: "source-map",
3 | stats: "errors-only",
4 | bail: true
5 | };
6 |
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-module/config/webpack/prod/index.js:
--------------------------------------------------------------------------------
1 | export const prodConfig = {
2 | devtool: "source-map",
3 | stats: "errors-only",
4 | bail: true
5 | };
6 |
--------------------------------------------------------------------------------
/test/expected/clientlibs-root/test.base.apps.fourth.json:
--------------------------------------------------------------------------------
1 | {
2 | "jcr:primaryType": "cq:ClientLibraryFolder",
3 | "categories": [
4 | "test.base.apps.fourth"
5 | ]
6 | }
7 |
--------------------------------------------------------------------------------
/test/src/frontend/js/libs/mylib.min.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sources":["mylib.js"],"names":["MyLib","this","test"],"mappings":"AACA,YACA,IAAIA,OAAQ,WACVC,KAAKC,KAAO","file":"mylib.min.js"}
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-module-cjs/config/webpack/prod/index.js:
--------------------------------------------------------------------------------
1 | export const prodConfig = {
2 | devtool: "source-map",
3 | stats: "errors-only",
4 | bail: true
5 | };
6 |
--------------------------------------------------------------------------------
/test/expected/clientlibs-root/myPrestructuredLibrary/js/libs/mylib.js:
--------------------------------------------------------------------------------
1 |
2 | "use strict";
3 | var MyLib = function() {
4 | this.test = "MyLib";
5 | };
6 | //# sourceMappingURL=mylib.js.map
--------------------------------------------------------------------------------
/test/expected/clientlibs-root/test.base.apps.fourth/js/libs/mylib.js:
--------------------------------------------------------------------------------
1 |
2 | "use strict";
3 | var MyLib = function() {
4 | this.test = "MyLib";
5 | };
6 | //# sourceMappingURL=mylib.js.map
--------------------------------------------------------------------------------
/test/expected/clientlibs-root/test.base.apps.thirdapp.json:
--------------------------------------------------------------------------------
1 | {
2 | "jcr:primaryType": "cq:ClientLibraryFolder",
3 | "categories": [
4 | "test.base.apps.thirdapp"
5 | ]
6 | }
7 |
--------------------------------------------------------------------------------
/test/expected/clientlibs-root/test.base.apps.ignoreOption/js/libs/mylib.js:
--------------------------------------------------------------------------------
1 |
2 | "use strict";
3 | var MyLib = function() {
4 | this.test = "MyLib";
5 | };
6 | //# sourceMappingURL=mylib.js.map
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | npm*.log
3 | tmp
4 | .idea
5 | .DS_Store
6 | .project
7 | .sublime-*
8 | .project
9 | .settings
10 |
11 | # ignore result folder from mocha test
12 | result/
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-commonjs/public/img/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wcm-io-frontend/aem-clientlib-generator/HEAD/integration-test/wcmio-archetype-commonjs/public/img/favicon.ico
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-module/public/img/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wcm-io-frontend/aem-clientlib-generator/HEAD/integration-test/wcmio-archetype-module/public/img/favicon.ico
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-commonjs/config/webpack/dev/server.js:
--------------------------------------------------------------------------------
1 | export const devServer = {
2 | devServer: {
3 | compress: true,
4 | port: 9000,
5 | static: "./public"
6 | }
7 | };
8 |
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-module-cjs/config/webpack/dev/server.js:
--------------------------------------------------------------------------------
1 | export const devServer = {
2 | devServer: {
3 | compress: true,
4 | port: 9000,
5 | static: "./public"
6 | }
7 | };
8 |
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-module-cjs/public/img/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wcm-io-frontend/aem-clientlib-generator/HEAD/integration-test/wcmio-archetype-module-cjs/public/img/favicon.ico
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-module/config/webpack/dev/server.js:
--------------------------------------------------------------------------------
1 | export const devServer = {
2 | devServer: {
3 | compress: true,
4 | port: 9000,
5 | static: "./public"
6 | }
7 | };
8 |
--------------------------------------------------------------------------------
/test/expected/clientlibs-root/test.base.apps.fourthWithOutputPath.json:
--------------------------------------------------------------------------------
1 | {
2 | "jcr:primaryType": "cq:ClientLibraryFolder",
3 | "categories": [
4 | "test.base.apps.fourthWithOutputPath"
5 | ]
6 | }
7 |
--------------------------------------------------------------------------------
/test/expected/clientlibs-root/myPrestructuredLibrary/js/libs/mylib.min.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sources":["mylib.js"],"names":["MyLib","this","test"],"mappings":"AACA,YACA,IAAIA,OAAQ,WACVC,KAAKC,KAAO","file":"mylib.min.js"}
--------------------------------------------------------------------------------
/test/expected/clientlibs-root/test.base.apps.fourth/js/libs/mylib.min.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sources":["mylib.js"],"names":["MyLib","this","test"],"mappings":"AACA,YACA,IAAIA,OAAQ,WACVC,KAAKC,KAAO","file":"mylib.min.js"}
--------------------------------------------------------------------------------
/test/expected/clientlibs-root/test.base.apps.mainapp/js/libs/mylib.min.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sources":["mylib.js"],"names":["MyLib","this","test"],"mappings":"AACA,YACA,IAAIA,OAAQ,WACVC,KAAKC,KAAO","file":"mylib.min.js"}
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-commonjs/expected-result/myproject1.app.json:
--------------------------------------------------------------------------------
1 | {
2 | "jcr:primaryType": "cq:ClientLibraryFolder",
3 | "allowProxy": true,
4 | "categories": [
5 | "myproject1.app"
6 | ]
7 | }
8 |
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-module/config/webpack/base/setup/entryConfig.js:
--------------------------------------------------------------------------------
1 | import path from "path";
2 |
3 | export const entry = {
4 | app: [path.resolve("src/index.js"), path.resolve("src/index.scss")]
5 | };
6 |
--------------------------------------------------------------------------------
/test/src/frontend/resources/template.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Test file
9 |
10 |
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-commonjs/config/webpack/base/setup/entryConfig.js:
--------------------------------------------------------------------------------
1 | import path from "path";
2 |
3 | export const entry = {
4 | app: [path.resolve("src/index.js"), path.resolve("src/index.scss")]
5 | };
6 |
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-module-cjs/config/webpack/base/setup/entryConfig.js:
--------------------------------------------------------------------------------
1 | import path from "path";
2 |
3 | export const entry = {
4 | app: [path.resolve("src/index.js"), path.resolve("src/index.scss")]
5 | };
6 |
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-module/src/components/image/image.scss:
--------------------------------------------------------------------------------
1 | .cmp-image img {
2 | max-width: 100%;
3 | height: auto;
4 | }
5 |
6 | .cmp-image .cmp-image__title {
7 | display: block;
8 | margin: .75rem 0;
9 | }
10 |
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-commonjs/src/components/image/image.scss:
--------------------------------------------------------------------------------
1 | .cmp-image img {
2 | max-width: 100%;
3 | height: auto;
4 | }
5 |
6 | .cmp-image .cmp-image__title {
7 | display: block;
8 | margin: .75rem 0;
9 | }
10 |
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-module-cjs/src/components/image/image.scss:
--------------------------------------------------------------------------------
1 | .cmp-image img {
2 | max-width: 100%;
3 | height: auto;
4 | }
5 |
6 | .cmp-image .cmp-image__title {
7 | display: block;
8 | margin: .75rem 0;
9 | }
10 |
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-commonjs/src/index.js:
--------------------------------------------------------------------------------
1 | import CustomCarousel from "./components/customcarousel/customcarousel.js";
2 |
3 | // Document Ready
4 | document.addEventListener('DOMContentLoaded', () => {
5 | CustomCarousel();
6 | });
7 |
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-module-cjs/src/index.js:
--------------------------------------------------------------------------------
1 | import CustomCarousel from "./components/customcarousel/customcarousel.js";
2 |
3 | // Document Ready
4 | document.addEventListener('DOMContentLoaded', () => {
5 | CustomCarousel();
6 | });
7 |
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-module/src/index.js:
--------------------------------------------------------------------------------
1 | import CustomCarousel from "./components/customcarousel/customcarousel.js";
2 |
3 | // Document Ready
4 | document.addEventListener('DOMContentLoaded', () => {
5 | CustomCarousel();
6 | });
7 |
--------------------------------------------------------------------------------
/test/expected/clientlibs-root/test.base.apps.five/resources/template.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Test file
9 |
10 |
--------------------------------------------------------------------------------
/.github/release-drafter.yml:
--------------------------------------------------------------------------------
1 | name-template: 'Next Release'
2 | tag-template: 'next'
3 |
4 | exclude-labels:
5 | - integration-test
6 | exclude-contributors:
7 | - renovate
8 |
9 | template: |
10 | ## What’s Changed
11 |
12 | $CHANGES
13 |
--------------------------------------------------------------------------------
/test/expected/clientlibs-root/redirectOutputTestWithXML/resources/template.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Test file
9 |
10 |
--------------------------------------------------------------------------------
/test/expected/clientlibs-root/test.base.apps.secondapp/resources/template.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Test file
9 |
10 |
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-module/config/webpack/dev/index.js:
--------------------------------------------------------------------------------
1 | import { merge } from "webpack-merge";
2 | import { devServer } from "./server.js";
3 |
4 | export const devConfig = merge(devServer, {
5 | devtool: "source-map",
6 | bail: true
7 | });
8 |
--------------------------------------------------------------------------------
/test/expected/clientlibs-root/test.base.apps.customProperties/resources/template.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Test file
9 |
10 |
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-commonjs/config/webpack/base/tasks/index.js:
--------------------------------------------------------------------------------
1 | export * from "./es6.js";
2 | export * from "./handlebars.js";
3 | export * from "./scss.js";
4 | export * from "./html.js";
5 | export * from "./clean.js";
6 | export * from "./copy.js";
7 |
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-commonjs/config/webpack/dev/index.js:
--------------------------------------------------------------------------------
1 | import { merge } from "webpack-merge";
2 | import { devServer } from "./server.js";
3 |
4 | export const devConfig = merge(devServer, {
5 | devtool: "source-map",
6 | bail: true
7 | });
8 |
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-module-cjs/config/webpack/dev/index.js:
--------------------------------------------------------------------------------
1 | import { merge } from "webpack-merge";
2 | import { devServer } from "./server.js";
3 |
4 | export const devConfig = merge(devServer, {
5 | devtool: "source-map",
6 | bail: true
7 | });
8 |
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-module/config/webpack/base/tasks/index.js:
--------------------------------------------------------------------------------
1 | export * from "./es6.js";
2 | export * from "./handlebars.js";
3 | export * from "./scss.js";
4 | export * from "./html.js";
5 | export * from "./clean.js";
6 | export * from "./copy.js";
7 |
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-module/expected-result/myproject1.app/resources/img/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wcm-io-frontend/aem-clientlib-generator/HEAD/integration-test/wcmio-archetype-module/expected-result/myproject1.app/resources/img/favicon.ico
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-commonjs/expected-result/myproject1.app/resources/img/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wcm-io-frontend/aem-clientlib-generator/HEAD/integration-test/wcmio-archetype-commonjs/expected-result/myproject1.app/resources/img/favicon.ico
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-module-cjs/config/webpack/base/tasks/index.js:
--------------------------------------------------------------------------------
1 | export * from "./es6.js";
2 | export * from "./handlebars.js";
3 | export * from "./scss.js";
4 | export * from "./html.js";
5 | export * from "./clean.js";
6 | export * from "./copy.js";
7 |
--------------------------------------------------------------------------------
/test/expected/clientlibs-root/test.base.apps.customPropertiesNotAllowed/resources/template.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Test file
9 |
10 |
--------------------------------------------------------------------------------
/test/expected/clientlibs-root/test.base.apps.serializationFormatXML/resources/template.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Test file
9 |
10 |
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-module-cjs/expected-result/myproject1.app/resources/img/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wcm-io-frontend/aem-clientlib-generator/HEAD/integration-test/wcmio-archetype-module-cjs/expected-result/myproject1.app/resources/img/favicon.ico
--------------------------------------------------------------------------------
/test/expected/clientlibs-root/test.base.apps.serializationFormatSlingXML/resources/template.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Test file
9 |
10 |
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-commonjs/config/webpack/base/tasks/es6.js:
--------------------------------------------------------------------------------
1 | export const es6 = {
2 | module: {
3 | rules: [
4 | {
5 | test: /\.js$/,
6 | exclude: /node_modules/,
7 | loader: "babel-loader"
8 | }
9 | ]
10 | }
11 | };
12 |
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-module/config/webpack/base/tasks/es6.js:
--------------------------------------------------------------------------------
1 | export const es6 = {
2 | module: {
3 | rules: [
4 | {
5 | test: /\.js$/,
6 | exclude: /node_modules/,
7 | loader: "babel-loader"
8 | }
9 | ]
10 | }
11 | };
12 |
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-module-cjs/config/webpack/base/tasks/es6.js:
--------------------------------------------------------------------------------
1 | export const es6 = {
2 | module: {
3 | rules: [
4 | {
5 | test: /\.js$/,
6 | exclude: /node_modules/,
7 | loader: "babel-loader"
8 | }
9 | ]
10 | }
11 | };
12 |
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-module/expected-result/myproject1.app/.content.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-module-cjs/expected-result/myproject1.app/.content.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-module/config/webpack/base/tasks/html.js:
--------------------------------------------------------------------------------
1 | import HtmlWEbpackPlugin from "html-webpack-plugin";
2 |
3 | export const html = {
4 | plugins: [
5 | new HtmlWEbpackPlugin({
6 | template: "index.hbs",
7 | filename: "index.html"
8 | })
9 | ]
10 | };
11 |
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-commonjs/config/webpack/base/tasks/html.js:
--------------------------------------------------------------------------------
1 | import HtmlWEbpackPlugin from "html-webpack-plugin";
2 |
3 | export const html = {
4 | plugins: [
5 | new HtmlWEbpackPlugin({
6 | template: "index.hbs",
7 | filename: "index.html"
8 | })
9 | ]
10 | };
11 |
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-module-cjs/config/webpack/base/tasks/html.js:
--------------------------------------------------------------------------------
1 | import HtmlWEbpackPlugin from "html-webpack-plugin";
2 |
3 | export const html = {
4 | plugins: [
5 | new HtmlWEbpackPlugin({
6 | template: "index.hbs",
7 | filename: "index.html"
8 | })
9 | ]
10 | };
11 |
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-module/src/components/customcarousel/customcarousel.js:
--------------------------------------------------------------------------------
1 | import { Carousel } from "bootstrap";
2 |
3 | export default () => {
4 | // Initialize all carousels on the page
5 | document.querySelectorAll('.carousel').forEach(carouselEl => {
6 | new Carousel(carouselEl);
7 | });
8 | };
9 |
--------------------------------------------------------------------------------
/test/expected/clientlibs-root/test.base.apps.secondapp.json:
--------------------------------------------------------------------------------
1 | {
2 | "jcr:primaryType": "cq:ClientLibraryFolder",
3 | "categories": [
4 | "test.categorie.in.config"
5 | ],
6 | "dependencies": [
7 | "test.base.apps.mainapp"
8 | ],
9 | "embed": [
10 | "test.base.apps.thirdapp"
11 | ]
12 | }
13 |
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-commonjs/src/components/customcarousel/customcarousel.js:
--------------------------------------------------------------------------------
1 | import { Carousel } from "bootstrap";
2 |
3 | export default () => {
4 | // Initialize all carousels on the page
5 | document.querySelectorAll('.carousel').forEach(carouselEl => {
6 | new Carousel(carouselEl);
7 | });
8 | };
9 |
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-module-cjs/src/components/customcarousel/customcarousel.js:
--------------------------------------------------------------------------------
1 | import { Carousel } from "bootstrap";
2 |
3 | export default () => {
4 | // Initialize all carousels on the page
5 | document.querySelectorAll('.carousel').forEach(carouselEl => {
6 | new Carousel(carouselEl);
7 | });
8 | };
9 |
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-commonjs/config/path.config.js:
--------------------------------------------------------------------------------
1 | import path from "path";
2 |
3 | export const pathConfig = {
4 | paths: {
5 | src: path.resolve("src"),
6 | target: path.resolve("dist"),
7 | public: "public",
8 | styleTarget: "static/styles",
9 | jsTarget: "static/js"
10 | }
11 | };
12 |
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-module/config/path.config.js:
--------------------------------------------------------------------------------
1 | import path from "path";
2 |
3 | export const pathConfig = {
4 | paths: {
5 | src: path.resolve("src"),
6 | target: path.resolve("dist"),
7 | public: "public",
8 | styleTarget: "static/styles",
9 | jsTarget: "static/js"
10 | }
11 | };
12 |
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-module-cjs/config/path.config.js:
--------------------------------------------------------------------------------
1 | import path from "path";
2 |
3 | export const pathConfig = {
4 | paths: {
5 | src: path.resolve("src"),
6 | target: path.resolve("dist"),
7 | public: "public",
8 | styleTarget: "static/styles",
9 | jsTarget: "static/js"
10 | }
11 | };
12 |
--------------------------------------------------------------------------------
/test/expected/clientlibs-root/test.base.apps.five.json:
--------------------------------------------------------------------------------
1 | {
2 | "jcr:primaryType": "cq:ClientLibraryFolder",
3 | "categories": [
4 | "test.base.apps.five",
5 | "test.categorie.in.config"
6 | ],
7 | "dependencies": [
8 | "test.base.apps.mainapp"
9 | ],
10 | "embed": [
11 | "test.base.apps.thirdapp"
12 | ]
13 | }
14 |
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-commonjs/config/webpack/base/setup/outputConfig.js:
--------------------------------------------------------------------------------
1 | import path from "path";
2 | import { pathConfig } from "../../../path.config.js";
3 |
4 | export const output = {
5 | path: path.resolve(pathConfig.paths.target),
6 | filename: `${pathConfig.paths.jsTarget}/[name].js`,
7 | chunkFilename: `${pathConfig.paths.jsTarget}/[name].[hash].js`
8 | };
9 |
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-module/config/webpack/base/setup/outputConfig.js:
--------------------------------------------------------------------------------
1 | import path from "path";
2 | import { pathConfig } from "../../../path.config.js";
3 |
4 | export const output = {
5 | path: path.resolve(pathConfig.paths.target),
6 | filename: `${pathConfig.paths.jsTarget}/[name].js`,
7 | chunkFilename: `${pathConfig.paths.jsTarget}/[name].[hash].js`
8 | };
9 |
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-module-cjs/config/webpack/base/setup/outputConfig.js:
--------------------------------------------------------------------------------
1 | import path from "path";
2 | import { pathConfig } from "../../../path.config.js";
3 |
4 | export const output = {
5 | path: path.resolve(pathConfig.paths.target),
6 | filename: `${pathConfig.paths.jsTarget}/[name].js`,
7 | chunkFilename: `${pathConfig.paths.jsTarget}/[name].[hash].js`
8 | };
9 |
--------------------------------------------------------------------------------
/test/expected/clientlibs-root/redirectOutputTestWithXML/.content.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
--------------------------------------------------------------------------------
/test/expected/clientlibs-root/test.base.apps.serializationFormatXML/.content.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
--------------------------------------------------------------------------------
/test/expected/clientlibs-root/test.base.apps.customPropertiesNotAllowed/.content.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
--------------------------------------------------------------------------------
/test/expected/clientlibs-root/test.base.apps.mainapp.json:
--------------------------------------------------------------------------------
1 | {
2 | "jcr:primaryType": "cq:ClientLibraryFolder",
3 | "allowProxy": true,
4 | "categories": [
5 | "test.base.apps.mainapp"
6 | ],
7 | "cssProcessor": [
8 | "default:none",
9 | "min:none"
10 | ],
11 | "jsProcessor": [
12 | "default:none",
13 | "min:gcc"
14 | ],
15 | "longCacheKey": "${project.version}-${buildNumber}"
16 | }
17 |
--------------------------------------------------------------------------------
/test/expected/clientlibs-root/test.base.apps.customProperties/.content.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-commonjs/config/webpack/base/tasks/clean.js:
--------------------------------------------------------------------------------
1 | import path from "path";
2 | import { CleanWebpackPlugin } from "clean-webpack-plugin";
3 | import { pathConfig } from "../../../path.config.js";
4 |
5 | const pathsToClean = [pathConfig.paths.target];
6 |
7 | export const clean = {
8 | plugins: [new CleanWebpackPlugin({
9 | cleanOnceBeforeBuildPatterns: pathsToClean,
10 | verbose: false
11 | })]
12 | };
13 |
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-module-cjs/config/webpack/base/tasks/clean.js:
--------------------------------------------------------------------------------
1 | import path from "path";
2 | import { CleanWebpackPlugin } from "clean-webpack-plugin";
3 | import { pathConfig } from "../../../path.config.js";
4 |
5 | const pathsToClean = [pathConfig.paths.target];
6 |
7 | export const clean = {
8 | plugins: [new CleanWebpackPlugin({
9 | cleanOnceBeforeBuildPatterns: pathsToClean,
10 | verbose: false
11 | })]
12 | };
13 |
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-module/config/webpack/base/tasks/clean.js:
--------------------------------------------------------------------------------
1 | import path from "path";
2 | import { CleanWebpackPlugin } from "clean-webpack-plugin";
3 | import { pathConfig } from "../../../path.config.js";
4 |
5 | const pathsToClean = [pathConfig.paths.target];
6 |
7 | export const clean = {
8 | plugins: [new CleanWebpackPlugin({
9 | cleanOnceBeforeBuildPatterns: pathsToClean,
10 | verbose: false
11 | })]
12 | };
13 |
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-commonjs/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | [
4 | "@babel/preset-env",
5 | {
6 | "targets": {
7 | "browsers": [
8 | "last 2 versions",
9 | "not dead",
10 | "not op_mini all",
11 | "not < 1%"
12 | ]
13 | }
14 | }
15 | ]
16 | ],
17 | "plugins": ["transform-class-properties", "transform-es2015-arrow-functions"]
18 | }
19 |
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-module-cjs/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | [
4 | "@babel/preset-env",
5 | {
6 | "targets": {
7 | "browsers": [
8 | "last 2 versions",
9 | "not dead",
10 | "not op_mini all",
11 | "not < 1%"
12 | ]
13 | }
14 | }
15 | ]
16 | ],
17 | "plugins": ["transform-class-properties", "transform-es2015-arrow-functions"]
18 | }
19 |
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-module/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | [
4 | "@babel/preset-env",
5 | {
6 | "targets": {
7 | "browsers": [
8 | "last 2 versions",
9 | "not dead",
10 | "not op_mini all",
11 | "not < 1%"
12 | ]
13 | }
14 | }
15 | ]
16 | ],
17 | "plugins": ["transform-class-properties", "transform-es2015-arrow-functions"]
18 | }
19 |
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-module/config/webpack/base/index.js:
--------------------------------------------------------------------------------
1 | import path from "path";
2 | import { merge } from "webpack-merge";
3 |
4 | import { pathConfig } from "../../path.config.js";
5 | import { entry, output } from "./setup/index.js";
6 | import { clean, es6, scss, handlebars, html, copy } from "./tasks/index.js";
7 |
8 | export const baseConfig = merge(clean, es6, scss, handlebars, html, copy, {
9 | entry,
10 | output,
11 | context: path.resolve(pathConfig.paths.src)
12 | });
13 |
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-commonjs/config/webpack/base/index.js:
--------------------------------------------------------------------------------
1 | import path from "path";
2 | import { merge } from "webpack-merge";
3 |
4 | import { pathConfig } from "../../path.config.js";
5 | import { entry, output } from "./setup/index.js";
6 | import { clean, es6, scss, handlebars, html, copy } from "./tasks/index.js";
7 |
8 | export const baseConfig = merge(clean, es6, scss, handlebars, html, copy, {
9 | entry,
10 | output,
11 | context: path.resolve(pathConfig.paths.src)
12 | });
13 |
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-module-cjs/config/webpack/base/index.js:
--------------------------------------------------------------------------------
1 | import path from "path";
2 | import { merge } from "webpack-merge";
3 |
4 | import { pathConfig } from "../../path.config.js";
5 | import { entry, output } from "./setup/index.js";
6 | import { clean, es6, scss, handlebars, html, copy } from "./tasks/index.js";
7 |
8 | export const baseConfig = merge(clean, es6, scss, handlebars, html, copy, {
9 | entry,
10 | output,
11 | context: path.resolve(pathConfig.paths.src)
12 | });
13 |
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-module/config/webpack/base/tasks/handlebars.js:
--------------------------------------------------------------------------------
1 | import path from "path";
2 | import { pathConfig } from "../../../path.config.js";
3 |
4 | export const handlebars = {
5 | module: {
6 | rules: [
7 | {
8 | test: /\.hbs$/,
9 | use: [
10 | {
11 | loader: "handlebars-loader",
12 | options: {
13 | partialDirs: [path.resolve(pathConfig.paths.src)]
14 | }
15 | }
16 | ]
17 | }
18 | ]
19 | }
20 | };
21 |
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-commonjs/config/webpack/base/tasks/handlebars.js:
--------------------------------------------------------------------------------
1 | import path from "path";
2 | import { pathConfig } from "../../../path.config.js";
3 |
4 | export const handlebars = {
5 | module: {
6 | rules: [
7 | {
8 | test: /\.hbs$/,
9 | use: [
10 | {
11 | loader: "handlebars-loader",
12 | options: {
13 | partialDirs: [path.resolve(pathConfig.paths.src)]
14 | }
15 | }
16 | ]
17 | }
18 | ]
19 | }
20 | };
21 |
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-module-cjs/config/webpack/base/tasks/handlebars.js:
--------------------------------------------------------------------------------
1 | import path from "path";
2 | import { pathConfig } from "../../../path.config.js";
3 |
4 | export const handlebars = {
5 | module: {
6 | rules: [
7 | {
8 | test: /\.hbs$/,
9 | use: [
10 | {
11 | loader: "handlebars-loader",
12 | options: {
13 | partialDirs: [path.resolve(pathConfig.paths.src)]
14 | }
15 | }
16 | ]
17 | }
18 | ]
19 | }
20 | };
21 |
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-commonjs/config/webpack/base/tasks/copy.js:
--------------------------------------------------------------------------------
1 | import path from "path";
2 | import CopyWebpackPlugin from "copy-webpack-plugin";
3 | import { pathConfig } from "../../../path.config.js";
4 |
5 | export const copy = {
6 | plugins: [
7 | new CopyWebpackPlugin({
8 | patterns: [
9 | {
10 | from: `${path.resolve(pathConfig.paths.public)}/**/*.*`,
11 | to: `${pathConfig.paths.public}`,
12 | noErrorOnMissing: true,
13 | },
14 | ],
15 | }),
16 | ],
17 | };
18 |
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-commonjs/src/index.hbs:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | aem-fe-archetype Frontend
10 |
11 |
12 |
13 |
14 | {{> components/customcarousel/customcarousel}}
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-module-cjs/config/webpack/base/tasks/copy.js:
--------------------------------------------------------------------------------
1 | import path from "path";
2 | import CopyWebpackPlugin from "copy-webpack-plugin";
3 | import { pathConfig } from "../../../path.config.js";
4 |
5 | export const copy = {
6 | plugins: [
7 | new CopyWebpackPlugin({
8 | patterns: [
9 | {
10 | from: `${path.resolve(pathConfig.paths.public)}/**/*.*`,
11 | to: `${pathConfig.paths.public}`,
12 | noErrorOnMissing: true,
13 | },
14 | ],
15 | }),
16 | ],
17 | };
18 |
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-module-cjs/src/index.hbs:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | aem-fe-archetype Frontend
10 |
11 |
12 |
13 |
14 | {{> components/customcarousel/customcarousel}}
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-module/config/webpack/base/tasks/copy.js:
--------------------------------------------------------------------------------
1 | import path from "path";
2 | import CopyWebpackPlugin from "copy-webpack-plugin";
3 | import { pathConfig } from "../../../path.config.js";
4 |
5 | export const copy = {
6 | plugins: [
7 | new CopyWebpackPlugin({
8 | patterns: [
9 | {
10 | from: `${path.resolve(pathConfig.paths.public)}/**/*.*`,
11 | to: `${pathConfig.paths.public}`,
12 | noErrorOnMissing: true,
13 | },
14 | ],
15 | }),
16 | ],
17 | };
18 |
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-module/src/index.hbs:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | aem-fe-archetype Frontend
10 |
11 |
12 |
13 |
14 | {{> components/customcarousel/customcarousel}}
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-module/README.md:
--------------------------------------------------------------------------------
1 | Integration Test: wcmio-archetype
2 | =================================
3 |
4 | Maven-based Integration test derived from the type of frontend setup generated by [wcm.io Maven Archetype for AEM](https://wcm.io/tooling/maven/archetypes/aem/) 3.x.
5 |
6 | It uses `aem-clientlib-generator` directly from this project as file references in package.json.
7 |
8 | The generated client libraries in the `result` folder are compared against a predefined `existing-result` folder, with a diff-compare after as part of the integration test run.
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-commonjs/README.md:
--------------------------------------------------------------------------------
1 | Integration Test: wcmio-archetype
2 | =================================
3 |
4 | Maven-based Integration test derived from the type of frontend setup generated by [wcm.io Maven Archetype for AEM](https://wcm.io/tooling/maven/archetypes/aem/) 3.x.
5 |
6 | It uses `aem-clientlib-generator` directly from this project as file references in package.json.
7 |
8 | The generated client libraries in the `result` folder are compared against a predefined `existing-result` folder, with a diff-compare after as part of the integration test run.
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-module-cjs/README.md:
--------------------------------------------------------------------------------
1 | Integration Test: wcmio-archetype
2 | =================================
3 |
4 | Maven-based Integration test derived from the type of frontend setup generated by [wcm.io Maven Archetype for AEM](https://wcm.io/tooling/maven/archetypes/aem/) 3.x.
5 |
6 | It uses `aem-clientlib-generator` directly from this project as file references in package.json.
7 |
8 | The generated client libraries in the `result` folder are compared against a predefined `existing-result` folder, with a diff-compare after as part of the integration test run.
--------------------------------------------------------------------------------
/.github/workflows/release-drafter.yml:
--------------------------------------------------------------------------------
1 | name: Release Drafter
2 |
3 | on:
4 | push:
5 | branches:
6 | - master
7 |
8 | permissions:
9 | contents: read
10 |
11 | jobs:
12 | update_release_draft:
13 | permissions:
14 | contents: write
15 | pull-requests: read
16 | runs-on: ubuntu-latest
17 | steps:
18 | - if: ${{ github.repository_owner == 'wcm-io-frontend' }}
19 | uses: release-drafter/release-drafter@v6
20 | with:
21 | disable-autolabeler: true
22 | env:
23 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
24 |
--------------------------------------------------------------------------------
/.github/renovate.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json",
3 | "extends": [
4 | "github>wcm-io-frontend/renovate-config:npm"
5 | ],
6 | "enabledManagers": [
7 | "npm",
8 | "nvm",
9 | "maven"
10 | ],
11 | "packageRules": [
12 | {
13 | "matchUpdateTypes": ["major", "minor", "patch", "pin", "pinDigest", "digest", "lockFileMaintenance"],
14 | "groupName": "integration-test dependencies",
15 | "matchFileNames": ["integration-test/**"],
16 | "schedule": ["before 8am on the first day of the month"],
17 | "automerge": true,
18 | "addLabels": ["integration-test"]
19 | }
20 | ]
21 | }
22 |
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-module/expected-result/myproject1.all/.content.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-module-cjs/expected-result/myproject1.all/.content.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
--------------------------------------------------------------------------------
/.github/workflows/build.yml:
--------------------------------------------------------------------------------
1 | # Build validation
2 |
3 | name: Build
4 |
5 | on:
6 | push:
7 | branches:
8 | - master
9 | pull_request:
10 | workflow_dispatch:
11 |
12 | jobs:
13 | build:
14 | runs-on: ${{ matrix.os }}
15 | strategy:
16 | matrix:
17 | node-version: [lts/*]
18 | os: [ubuntu-latest,windows-latest,macos-latest]
19 | steps:
20 | - name: Checkout
21 | uses: actions/checkout@v5
22 | - name: Use Node.js ${{ matrix.node-version }}
23 | uses: actions/setup-node@v5
24 | with:
25 | node-version: ${{ matrix.node-version }}
26 | - name: npm ci
27 | run: npm ci
28 | - name: npm run test
29 | run: npm run test
30 |
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-commonjs/expected-result/myproject1.all.json:
--------------------------------------------------------------------------------
1 | {
2 | "jcr:primaryType": "cq:ClientLibraryFolder",
3 | "allowProxy": true,
4 | "categories": [
5 | "myproject1.all"
6 | ],
7 | "cssProcessor": [
8 | "default:none",
9 | "min:none"
10 | ],
11 | "embed": [
12 | "core.wcm.components.commons.datalayer.v1",
13 | "core.wcm.components.commons.site.container",
14 | "core.wcm.components.image.v2",
15 | "core.wcm.components.carousel.v1",
16 | "core.wcm.components.tabs.v1",
17 | "core.wcm.components.accordion.v1",
18 | "myproject1.app"
19 | ],
20 | "jsProcessor": [
21 | "default:none",
22 | "min:gcc;compilationLevel=whitespace;languageIn=ECMASCRIPT_2018;languageOut=ECMASCRIPT_2018"
23 | ]
24 | }
25 |
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-commonjs/config/webpack/base/tasks/scss.js:
--------------------------------------------------------------------------------
1 | import MiniCssExtractPlugin from "mini-css-extract-plugin";
2 | import { pathConfig } from "../../../path.config.js";
3 |
4 | export const scss = {
5 | plugins: [
6 | new MiniCssExtractPlugin({
7 | filename: `${pathConfig.paths.styleTarget}/[name].css`,
8 | chunkFilename: `${pathConfig.paths.styleTarget}/[id].css`
9 | })
10 | ],
11 | module: {
12 | rules: [
13 | {
14 | test: /\.(sa|sc|c)ss$/,
15 | use: [
16 | {
17 | loader: MiniCssExtractPlugin.loader
18 | },
19 | {
20 | loader: "css-loader",
21 | options: {
22 | sourceMap: true
23 | }
24 | },
25 | {
26 | loader: "sass-loader",
27 | options: {
28 | sourceMap: true
29 | }
30 | }
31 | ]
32 | }
33 | ]
34 | }
35 | };
36 |
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-module-cjs/config/webpack/base/tasks/scss.js:
--------------------------------------------------------------------------------
1 | import MiniCssExtractPlugin from "mini-css-extract-plugin";
2 | import { pathConfig } from "../../../path.config.js";
3 |
4 | export const scss = {
5 | plugins: [
6 | new MiniCssExtractPlugin({
7 | filename: `${pathConfig.paths.styleTarget}/[name].css`,
8 | chunkFilename: `${pathConfig.paths.styleTarget}/[id].css`
9 | })
10 | ],
11 | module: {
12 | rules: [
13 | {
14 | test: /\.(sa|sc|c)ss$/,
15 | use: [
16 | {
17 | loader: MiniCssExtractPlugin.loader
18 | },
19 | {
20 | loader: "css-loader",
21 | options: {
22 | sourceMap: true
23 | }
24 | },
25 | {
26 | loader: "sass-loader",
27 | options: {
28 | sourceMap: true
29 | }
30 | }
31 | ]
32 | }
33 | ]
34 | }
35 | };
36 |
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-module/config/webpack/base/tasks/scss.js:
--------------------------------------------------------------------------------
1 | import MiniCssExtractPlugin from "mini-css-extract-plugin";
2 | import { pathConfig } from "../../../path.config.js";
3 |
4 | export const scss = {
5 | plugins: [
6 | new MiniCssExtractPlugin({
7 | filename: `${pathConfig.paths.styleTarget}/[name].css`,
8 | chunkFilename: `${pathConfig.paths.styleTarget}/[id].css`
9 | })
10 | ],
11 | module: {
12 | rules: [
13 | {
14 | test: /\.(sa|sc|c)ss$/,
15 | use: [
16 | {
17 | loader: MiniCssExtractPlugin.loader
18 | },
19 | {
20 | loader: "css-loader",
21 | options: {
22 | sourceMap: true
23 | }
24 | },
25 | {
26 | loader: "sass-loader",
27 | options: {
28 | sourceMap: true
29 | }
30 | }
31 | ]
32 | }
33 | ]
34 | }
35 | };
36 |
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-commonjs/webpack.config.babel.js:
--------------------------------------------------------------------------------
1 | import { merge } from "webpack-merge";
2 |
3 | import { baseConfig } from "./config/webpack/base/index.js";
4 | import { devConfig } from "./config/webpack/dev/index.js";
5 | import { prodConfig } from "./config/webpack/prod/index.js";
6 |
7 | /**
8 | * Get the configuration file based on webpacks `mode` parameter.
9 | *
10 | * @param {String} runMode - Webpack mode (like: "development", "production", "test", "...");
11 | */
12 | const getConfig = runMode => {
13 | switch (runMode) {
14 | case "development":
15 | return devConfig;
16 | case "production":
17 | return prodConfig;
18 | default:
19 | return prodConfig;
20 | }
21 | };
22 |
23 | /**
24 | * Compose the webpack config
25 | */
26 | export default (_, argv) => {
27 | const runMode = argv.mode ? argv.mode : "production";
28 | const runModeConfig = getConfig(runMode);
29 |
30 | return merge(baseConfig, runModeConfig);
31 | };
32 |
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-module/webpack.config.babel.js:
--------------------------------------------------------------------------------
1 | import { merge } from "webpack-merge";
2 |
3 | import { baseConfig } from "./config/webpack/base/index.js";
4 | import { devConfig } from "./config/webpack/dev/index.js";
5 | import { prodConfig } from "./config/webpack/prod/index.js";
6 |
7 | /**
8 | * Get the configuration file based on webpacks `mode` parameter.
9 | *
10 | * @param {String} runMode - Webpack mode (like: "development", "production", "test", "...");
11 | */
12 | const getConfig = runMode => {
13 | switch (runMode) {
14 | case "development":
15 | return devConfig;
16 | case "production":
17 | return prodConfig;
18 | default:
19 | return prodConfig;
20 | }
21 | };
22 |
23 | /**
24 | * Compose the webpack config
25 | */
26 | export default (_, argv) => {
27 | const runMode = argv.mode ? argv.mode : "production";
28 | const runModeConfig = getConfig(runMode);
29 |
30 | return merge(baseConfig, runModeConfig);
31 | };
32 |
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-module-cjs/webpack.config.babel.js:
--------------------------------------------------------------------------------
1 | import { merge } from "webpack-merge";
2 |
3 | import { baseConfig } from "./config/webpack/base/index.js";
4 | import { devConfig } from "./config/webpack/dev/index.js";
5 | import { prodConfig } from "./config/webpack/prod/index.js";
6 |
7 | /**
8 | * Get the configuration file based on webpacks `mode` parameter.
9 | *
10 | * @param {String} runMode - Webpack mode (like: "development", "production", "test", "...");
11 | */
12 | const getConfig = runMode => {
13 | switch (runMode) {
14 | case "development":
15 | return devConfig;
16 | case "production":
17 | return prodConfig;
18 | default:
19 | return prodConfig;
20 | }
21 | };
22 |
23 | /**
24 | * Compose the webpack config
25 | */
26 | export default (_, argv) => {
27 | const runMode = argv.mode ? argv.mode : "production";
28 | const runModeConfig = getConfig(runMode);
29 |
30 | return merge(baseConfig, runModeConfig);
31 | };
32 |
--------------------------------------------------------------------------------
/test/expected/clientlibs-root/test.base.apps.serializationFormatSlingXML.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | test.base.apps.serializationFormatSlingXML
4 | cq:ClientLibraryFolder
5 |
6 | allowProxy
7 | true
8 | Boolean
9 |
10 |
11 | categories
12 |
13 | test.base.apps.six
14 | test.categorie.in.config
15 |
16 | String
17 |
18 |
19 | dependencies
20 |
21 | test.base.apps.mainapp
22 |
23 | String
24 |
25 |
26 | embed
27 |
28 | test.base.apps.thirdapp
29 |
30 | String
31 |
32 |
33 | longCacheKey
34 | ${project.version}-${buildNumber}
35 | String
36 |
37 |
38 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Declare text files with unix file ending
2 | *.conf text eol=lf
3 | *.config text eol=lf
4 | *.css text eol=lf
5 | *.dtd text eol=lf
6 | *.esp text eol=lf
7 | *.ecma text eol=lf
8 | *.groovy text eol=lf
9 | *.hbrs text eol=lf
10 | *.hbs text eol=lf
11 | *.htm text eol=lf
12 | *.html text eol=lf
13 | *.java text eol=lf
14 | *.jpage text eol=lf
15 | *.js text eol=lf
16 | *.json text eol=lf
17 | *.jsp text eol=lf
18 | *.mustache text eol=lf
19 | *.tld text eol=lf
20 | *.launch text eol=lf
21 | *.log text eol=lf
22 | *.php text eol=lf
23 | *.pl text eol=lf
24 | *.project text eol=lf
25 | *.properties text eol=lf
26 | *.props text eol=lf
27 | *.sass text eol=lf
28 | *.scss text eol=lf
29 | *.sh text eol=lf
30 | *.shtm text eol=lf
31 | *.shtml text eol=lf
32 | *.sql text eol=lf
33 | *.svg text eol=lf
34 | *.txt text eol=lf
35 | *.vm text eol=lf
36 | *.xml text eol=lf
37 | *.xsd text eol=lf
38 | *.xsl text eol=lf
39 | *.xslt text eol=lf
40 | *.yml text eol=lf
41 | *.yaml text eol=lf
42 |
43 |
44 | # Declare windows-specific text files with windows file ending
45 | *.asp text eol=crlf
46 | *.asax text eol=crlf
47 | *.asa text eol=crlf
48 | *.aspx text eol=crlf
49 | *.bat text eol=crlf
50 | *.cmd text eol=crlf
51 | *.cs text eol=crlf
52 | *.csproj text eol=crlf
53 | *.reg text eol=crlf
54 | *.sln text eol=crlf
55 |
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-commonjs/clientlib.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | // default working directory (can be changed per 'cwd' in every asset option)
3 | context: __dirname,
4 |
5 | // path to the clientlib root folder (output)
6 | clientLibRoot: "result",
7 |
8 | // define all clientlib options here as array... (multiple clientlibs)
9 | libs: [
10 | {
11 | name: "myproject1.app",
12 | serializationFormat: "json",
13 | allowProxy: true,
14 | assets: {
15 | js: ["dist/static/js/app.js", "dist/static/js/app.js.map"],
16 | css: ["dist/static/styles/app.css", "dist/static/styles/app.css.map"],
17 | resources: {
18 | cwd: "./public/",
19 | flatten: false,
20 | files: ["**/*.*"]
21 | }
22 | }
23 | },
24 | {
25 | name: "myproject1.all",
26 | serializationFormat: "json",
27 | embed: [
28 | "core.wcm.components.commons.datalayer.v1",
29 | "core.wcm.components.commons.site.container",
30 | "core.wcm.components.image.v2",
31 | "core.wcm.components.carousel.v1",
32 | "core.wcm.components.tabs.v1",
33 | "core.wcm.components.accordion.v1",
34 | "myproject1.app"
35 | ],
36 | jsProcessor: ["default:none", "min:gcc;compilationLevel=whitespace;languageIn=ECMASCRIPT_2018;languageOut=ECMASCRIPT_2018"],
37 | cssProcessor: ["default:none", "min:none"],
38 | allowProxy: true,
39 | assets: {
40 | js: [],
41 | css: []
42 | }
43 | }
44 | ]
45 | };
46 |
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-module-cjs/clientlib.config.cjs:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | // default working directory (can be changed per 'cwd' in every asset option)
3 | context: __dirname,
4 |
5 | // path to the clientlib root folder (output)
6 | clientLibRoot: "result",
7 |
8 | // define all clientlib options here as array... (multiple clientlibs)
9 | libs: [
10 | {
11 | name: "myproject1.app",
12 | serializationFormat: "xml",
13 | allowProxy: true,
14 | assets: {
15 | js: ["dist/static/js/app.js", "dist/static/js/app.js.map"],
16 | css: ["dist/static/styles/app.css", "dist/static/styles/app.css.map"],
17 | resources: {
18 | cwd: "./public/",
19 | flatten: false,
20 | files: ["**/*.*"]
21 | }
22 | }
23 | },
24 | {
25 | name: "myproject1.all",
26 | serializationFormat: "xml",
27 | embed: [
28 | "core.wcm.components.commons.datalayer.v1",
29 | "core.wcm.components.commons.site.container",
30 | "core.wcm.components.image.v2",
31 | "core.wcm.components.carousel.v1",
32 | "core.wcm.components.tabs.v1",
33 | "core.wcm.components.accordion.v1",
34 | "myproject1.app"
35 | ],
36 | jsProcessor: ["default:none", "min:gcc;compilationLevel=whitespace;languageIn=ECMASCRIPT_2018;languageOut=ECMASCRIPT_2018"],
37 | cssProcessor: ["default:none", "min:none"],
38 | allowProxy: true,
39 | assets: {
40 | js: [],
41 | css: []
42 | }
43 | }
44 | ]
45 | };
46 |
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-module/clientlib.config.js:
--------------------------------------------------------------------------------
1 | export default {
2 | // default working directory (can be changed per 'cwd' in every asset option)
3 | context: import.meta.dirname,
4 |
5 | // path to the clientlib root folder (output)
6 | clientLibRoot: "result",
7 |
8 | // define all clientlib options here as array... (multiple clientlibs)
9 | libs: [
10 | {
11 | name: "myproject1.app",
12 | serializationFormat: "xml",
13 | allowProxy: true,
14 | assets: {
15 | js: ["dist/static/js/app.js", "dist/static/js/app.js.map"],
16 | css: ["dist/static/styles/app.css", "dist/static/styles/app.css.map"],
17 | resources: {
18 | cwd: "./public/",
19 | flatten: false,
20 | files: ["**/*.*"]
21 | }
22 | }
23 | },
24 | {
25 | name: "myproject1.all",
26 | serializationFormat: "xml",
27 | embed: [
28 | "core.wcm.components.commons.datalayer.v1",
29 | "core.wcm.components.commons.site.container",
30 | "core.wcm.components.image.v2",
31 | "core.wcm.components.carousel.v1",
32 | "core.wcm.components.tabs.v1",
33 | "core.wcm.components.accordion.v1",
34 | "myproject1.app"
35 | ],
36 | jsProcessor: ["default:none", "min:gcc;compilationLevel=whitespace;languageIn=ECMASCRIPT_2018;languageOut=ECMASCRIPT_2018"],
37 | cssProcessor: ["default:none", "min:none"],
38 | allowProxy: true,
39 | assets: {
40 | js: [],
41 | css: []
42 | }
43 | }
44 | ]
45 | };
46 |
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-commonjs/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "private": true,
3 | "name": "myproject1-frontend",
4 | "version": "1.0.0",
5 | "description": "Frontend build pipeline for AEM projects",
6 | "main": "index.js",
7 | "scripts": {
8 | "start": "webpack-dev-server --mode development --open",
9 | "build:dev": "webpack --mode development",
10 | "build:prod": "webpack --mode production",
11 | "build:clientlibs": "npm run build:prod && node ../../bin/clientlib-cli.js",
12 | "test:compare-results": "node compare-results.mjs"
13 | },
14 | "dependencies": {
15 | "bootstrap": "5.3.8",
16 | "@popperjs/core": "2.11.8"
17 | },
18 | "devDependencies": {
19 | "dir-compare": "5.0.0",
20 | "diff": "8.0.2",
21 | "@babel/core": "7.28.5",
22 | "@babel/preset-env": "7.28.5",
23 | "@babel/register": "7.28.3",
24 | "aem-clientlib-generator": "file:../../..",
25 | "babel-loader": "10.0.0",
26 | "babel-plugin-transform-class-properties": "6.24.1",
27 | "babel-plugin-transform-es2015-arrow-functions": "6.22.0",
28 | "clean-webpack-plugin": "4.0.0",
29 | "copy-webpack-plugin": "13.0.1",
30 | "css-loader": "7.1.2",
31 | "handlebars": "4.7.8",
32 | "handlebars-loader": "1.7.3",
33 | "html-webpack-plugin": "5.6.4",
34 | "mini-css-extract-plugin": "2.9.4",
35 | "postcss-loader": "8.2.0",
36 | "sass": "1.93.2",
37 | "sass-loader": "16.0.6",
38 | "webpack": "5.102.1",
39 | "webpack-cli": "6.0.1",
40 | "webpack-dev-server": "5.2.2",
41 | "webpack-merge": "6.0.1"
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "aem-clientlib-generator",
3 | "version": "1.10.0",
4 | "description": "Creates configuration files for AEM ClientLibs and synchronizes assets.",
5 | "author": {
6 | "name": "wcm.io",
7 | "url": "https://wcm.io"
8 | },
9 | "type": "module",
10 | "contributors": [
11 | {
12 | "name": "Ingo Fahrentholz"
13 | },
14 | {
15 | "name": "Masoud Rozati"
16 | },
17 | {
18 | "name": "Mehran Behzad"
19 | },
20 | {
21 | "name": "Bert-Ulrich Baumann"
22 | }
23 | ],
24 | "homepage": "https://github.com/wcm-io-frontend/aem-clientlib-generator",
25 | "bugs": {
26 | "url": "https://github.com/wcm-io-frontend/aem-clientlib-generator/issues"
27 | },
28 | "repository": {
29 | "type": "git",
30 | "url": "git+https://github.com/wcm-io-frontend/aem-clientlib-generator.git"
31 | },
32 | "engines": {
33 | "node": ">=10.19.0"
34 | },
35 | "keywords": [
36 | "aem",
37 | "clientlib",
38 | "clientlibs",
39 | "generator",
40 | "sync"
41 | ],
42 | "main": "lib/clientlib.js",
43 | "bin": {
44 | "clientlib": "bin/clientlib-cli.js"
45 | },
46 | "dependencies": {
47 | "async": "^3.2.3",
48 | "fs-extra": "11.3.2",
49 | "glob": "7.2.3",
50 | "lodash": "4.17.21",
51 | "yargs": "^18.0.0"
52 | },
53 | "devDependencies": {
54 | "klaw": "4.1.0",
55 | "mocha": "11.7.5"
56 | },
57 | "license": "Apache-2.0",
58 | "scripts": {
59 | "test": "mocha",
60 | "build": "bin/clientlib-cli.js test/clientlib.config.js --verbose"
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-module/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "private": true,
3 | "name": "myproject1-frontend",
4 | "version": "1.0.0",
5 | "description": "Frontend build pipeline for AEM projects",
6 | "main": "index.js",
7 | "type": "module",
8 | "scripts": {
9 | "start": "webpack-dev-server --mode development --open",
10 | "build:dev": "webpack --mode development",
11 | "build:prod": "webpack --mode production",
12 | "build:clientlibs": "npm run build:prod && node ../../bin/clientlib-cli.js",
13 | "test:compare-results": "node compare-results.js"
14 | },
15 | "dependencies": {
16 | "bootstrap": "5.3.8",
17 | "@popperjs/core": "2.11.8"
18 | },
19 | "devDependencies": {
20 | "dir-compare": "5.0.0",
21 | "diff": "8.0.2",
22 | "@babel/core": "7.28.5",
23 | "@babel/preset-env": "7.28.5",
24 | "@babel/register": "7.28.3",
25 | "aem-clientlib-generator": "file:../../..",
26 | "babel-loader": "10.0.0",
27 | "babel-plugin-transform-class-properties": "6.24.1",
28 | "babel-plugin-transform-es2015-arrow-functions": "6.22.0",
29 | "clean-webpack-plugin": "4.0.0",
30 | "copy-webpack-plugin": "13.0.1",
31 | "css-loader": "7.1.2",
32 | "handlebars": "4.7.8",
33 | "handlebars-loader": "1.7.3",
34 | "html-webpack-plugin": "5.6.4",
35 | "mini-css-extract-plugin": "2.9.4",
36 | "postcss-loader": "8.2.0",
37 | "sass": "1.93.2",
38 | "sass-loader": "16.0.6",
39 | "webpack": "5.102.1",
40 | "webpack-cli": "6.0.1",
41 | "webpack-dev-server": "5.2.2",
42 | "webpack-merge": "6.0.1"
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-module-cjs/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "private": true,
3 | "name": "myproject1-frontend",
4 | "version": "1.0.0",
5 | "description": "Frontend build pipeline for AEM projects",
6 | "main": "index.js",
7 | "type": "module",
8 | "scripts": {
9 | "start": "webpack-dev-server --mode development --open",
10 | "build:dev": "webpack --mode development",
11 | "build:prod": "webpack --mode production",
12 | "build:clientlibs": "npm run build:prod && node ../../bin/clientlib-cli.js clientlib.config.cjs",
13 | "test:compare-results": "node compare-results.js"
14 | },
15 | "dependencies": {
16 | "bootstrap": "5.3.8",
17 | "@popperjs/core": "2.11.8"
18 | },
19 | "devDependencies": {
20 | "dir-compare": "5.0.0",
21 | "diff": "8.0.2",
22 | "@babel/core": "7.28.5",
23 | "@babel/preset-env": "7.28.5",
24 | "@babel/register": "7.28.3",
25 | "aem-clientlib-generator": "file:../../..",
26 | "babel-loader": "10.0.0",
27 | "babel-plugin-transform-class-properties": "6.24.1",
28 | "babel-plugin-transform-es2015-arrow-functions": "6.22.0",
29 | "clean-webpack-plugin": "4.0.0",
30 | "copy-webpack-plugin": "13.0.1",
31 | "css-loader": "7.1.2",
32 | "handlebars": "4.7.8",
33 | "handlebars-loader": "1.7.3",
34 | "html-webpack-plugin": "5.6.4",
35 | "mini-css-extract-plugin": "2.9.4",
36 | "postcss-loader": "8.2.0",
37 | "sass": "1.93.2",
38 | "sass-loader": "16.0.6",
39 | "webpack": "5.102.1",
40 | "webpack-cli": "6.0.1",
41 | "webpack-dev-server": "5.2.2",
42 | "webpack-merge": "6.0.1"
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-commonjs/src/components/customcarousel/customcarousel.hbs:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 | Previous
21 |
22 |
23 |
24 | Next
25 |
26 |
27 |
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-module-cjs/src/components/customcarousel/customcarousel.hbs:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 | Previous
21 |
22 |
23 |
24 | Next
25 |
26 |
27 |
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-module/src/components/customcarousel/customcarousel.hbs:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 | Previous
21 |
22 |
23 |
24 | Next
25 |
26 |
27 |
--------------------------------------------------------------------------------
/bin/clientlib-cli.js:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 |
3 | import url from 'node:url';
4 |
5 | var DEFAULT_FILE = "clientlib.config.js";
6 | import clientlib from "../lib/clientlib.js";
7 |
8 | import path from "node:path";
9 | import fs from "fs";
10 | import yargs from "yargs"
11 | import { hideBin } from "yargs/helpers"
12 |
13 | var argv = yargs(hideBin(process.argv))
14 | .usage("aem-clientlib-generator " + process.env.npm_package_version + "\n" +
15 | "Usage with config file: clientlib [path] [options]" + "\n\n" +
16 | "Default config path: " + DEFAULT_FILE)
17 | .help("help")
18 | .alias("help", "h")
19 | .version()
20 | .alias("version", "v")
21 | .options({
22 | "dry": {
23 | type: "boolean",
24 | describe: "'Dry run' without write operations."
25 | },
26 | "verbose": {
27 | type: "boolean",
28 | describe: "Prints more details"
29 | }
30 | }).argv;
31 |
32 | var configPath = path.resolve(process.cwd(), DEFAULT_FILE);
33 |
34 | if (argv._ && argv._.length > 0) {
35 | configPath = argv._[0];
36 | if (!path.isAbsolute(configPath)) {
37 | configPath = path.resolve(process.cwd(), configPath);
38 | }
39 | }
40 |
41 | if (!fs.existsSync(configPath)) {
42 | console.error("Could not find config file: " + configPath);
43 | process.exit(1);
44 | }
45 |
46 | import(path.isAbsolute(configPath) ? url.pathToFileURL(configPath).toString() : configPath ).then(conf => {
47 | var libs = [...conf.default.libs];
48 | var clientLibConf = conf.default;
49 | delete conf.default.libs;
50 | clientLibConf.dry = argv.dry;
51 | clientLibConf.verbose = argv.verbose || argv.dry;
52 |
53 | clientlib(libs, clientLibConf);
54 | }).catch(err => console.error(err));
55 |
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-commonjs/compare-results.mjs:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 | import dircompare from 'dir-compare';
3 | import path from 'path';
4 | import { fileURLToPath } from 'url';
5 | import fs from 'fs';
6 | import * as diff from 'diff';
7 |
8 | const __filename = fileURLToPath(import.meta.url);
9 | const __dirname = path.dirname(__filename);
10 |
11 | const resultDir = path.join(__dirname, 'result');
12 | const expectedDir = path.join(__dirname, 'expected-result');
13 |
14 | const options = { compareContent: true, excludeFilter: '.DS_Store' };
15 | const res = dircompare.compareSync(resultDir, expectedDir, options);
16 |
17 | if (!res.same) {
18 | console.error('Differences found:');
19 | for (const e of res.diffSet.filter(e => e.state !== 'equal')) {
20 | const name1 = e.name1 ? e.name1 : '';
21 | const name2 = e.name2 ? e.name2 : '';
22 | const relPath = e.relativePath;
23 | const file1 = path.join(resultDir, relPath, name1);
24 | const file2 = path.join(expectedDir, relPath, name2);
25 | if (e.type1 === 'missing') {
26 | console.error(`Only in expected-result: ${path.join(relPath, name2)}`);
27 | } else if (e.type2 === 'missing') {
28 | console.error(`Only in result: ${path.join(relPath, name1)}`);
29 | } else {
30 | console.error(`Diff: ${path.join(relPath, name1)}`);
31 | try {
32 | const a = fs.readFileSync(file1, 'utf8');
33 | const b = fs.readFileSync(file2, 'utf8');
34 | // Show unified diff
35 | const diffLines = diff.createPatch(name1, b, a, 'expected', 'result');
36 | console.error(diffLines);
37 | } catch (err) {
38 | console.error(' (Could not show file diff)', err.message);
39 | }
40 | }
41 | }
42 | process.exit(1);
43 | } else {
44 | console.log('All files match.');
45 | }
46 |
47 |
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-module/compare-results.js:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 | import dircompare from 'dir-compare';
3 | import path from 'path';
4 | import { fileURLToPath } from 'url';
5 | import fs from 'fs';
6 | import * as diff from 'diff';
7 |
8 | const __filename = fileURLToPath(import.meta.url);
9 | const __dirname = path.dirname(__filename);
10 |
11 | const resultDir = path.join(__dirname, 'result');
12 | const expectedDir = path.join(__dirname, 'expected-result');
13 |
14 | const options = { compareContent: true, excludeFilter: '.DS_Store' };
15 | const res = dircompare.compareSync(resultDir, expectedDir, options);
16 |
17 | if (!res.same) {
18 | console.error('Differences found:');
19 | for (const e of res.diffSet.filter(e => e.state !== 'equal')) {
20 | const name1 = e.name1 ? e.name1 : '';
21 | const name2 = e.name2 ? e.name2 : '';
22 | const relPath = e.relativePath;
23 | const file1 = path.join(resultDir, relPath, name1);
24 | const file2 = path.join(expectedDir, relPath, name2);
25 | if (e.type1 === 'missing') {
26 | console.error(`Only in expected-result: ${path.join(relPath, name2)}`);
27 | } else if (e.type2 === 'missing') {
28 | console.error(`Only in result: ${path.join(relPath, name1)}`);
29 | } else {
30 | console.error(`Diff: ${path.join(relPath, name1)}`);
31 | try {
32 | const a = fs.readFileSync(file1, 'utf8');
33 | const b = fs.readFileSync(file2, 'utf8');
34 | // Show unified diff
35 | const diffLines = diff.createPatch(name1, b, a, 'expected', 'result');
36 | console.error(diffLines);
37 | } catch (err) {
38 | console.error(' (Could not show file diff)', err.message);
39 | }
40 | }
41 | }
42 | process.exit(1);
43 | } else {
44 | console.log('All files match.');
45 | }
46 |
47 |
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-module-cjs/compare-results.js:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 | import dircompare from 'dir-compare';
3 | import path from 'path';
4 | import { fileURLToPath } from 'url';
5 | import fs from 'fs';
6 | import * as diff from 'diff';
7 |
8 | const __filename = fileURLToPath(import.meta.url);
9 | const __dirname = path.dirname(__filename);
10 |
11 | const resultDir = path.join(__dirname, 'result');
12 | const expectedDir = path.join(__dirname, 'expected-result');
13 |
14 | const options = { compareContent: true, excludeFilter: '.DS_Store' };
15 | const res = dircompare.compareSync(resultDir, expectedDir, options);
16 |
17 | if (!res.same) {
18 | console.error('Differences found:');
19 | for (const e of res.diffSet.filter(e => e.state !== 'equal')) {
20 | const name1 = e.name1 ? e.name1 : '';
21 | const name2 = e.name2 ? e.name2 : '';
22 | const relPath = e.relativePath;
23 | const file1 = path.join(resultDir, relPath, name1);
24 | const file2 = path.join(expectedDir, relPath, name2);
25 | if (e.type1 === 'missing') {
26 | console.error(`Only in expected-result: ${path.join(relPath, name2)}`);
27 | } else if (e.type2 === 'missing') {
28 | console.error(`Only in result: ${path.join(relPath, name1)}`);
29 | } else {
30 | console.error(`Diff: ${path.join(relPath, name1)}`);
31 | try {
32 | const a = fs.readFileSync(file1, 'utf8');
33 | const b = fs.readFileSync(file2, 'utf8');
34 | // Show unified diff
35 | const diffLines = diff.createPatch(name1, b, a, 'expected', 'result');
36 | console.error(diffLines);
37 | } catch (err) {
38 | console.error(' (Could not show file diff)', err.message);
39 | }
40 | }
41 | }
42 | process.exit(1);
43 | } else {
44 | console.log('All files match.');
45 | }
46 |
47 |
--------------------------------------------------------------------------------
/.github/workflows/release.yml:
--------------------------------------------------------------------------------
1 | name: Release and Publish
2 |
3 | on:
4 | workflow_dispatch:
5 | inputs:
6 | release_type:
7 | description: Type of release (e.g., patch, minor, major)
8 | required: true
9 | default: patch
10 |
11 | permissions:
12 | contents: read
13 |
14 | jobs:
15 | build:
16 | runs-on: ubuntu-latest
17 | steps:
18 | - uses: actions/checkout@v5
19 |
20 | - uses: actions/setup-node@v5
21 | with:
22 | node-version: lts/*
23 | cache: npm
24 |
25 | - run: npm ci
26 | - run: npm run test
27 |
28 | release-and-publish-npm-registry:
29 | needs: build
30 | runs-on: ubuntu-latest
31 |
32 | permissions:
33 | id-token: write
34 | contents: write
35 | pull-requests: read
36 |
37 | steps:
38 | - uses: actions/checkout@v5
39 | with:
40 | fetch-depth: 0
41 |
42 | - uses: actions/setup-node@v5
43 | with:
44 | node-version: lts/*
45 | cache: npm
46 | registry-url: https://registry.npmjs.org
47 |
48 | - name: set next version
49 | run: |
50 | git config user.name "GitHub Actions"
51 | git config user.email noreply@github.com
52 | npm version ${{ github.event.inputs.release_type }} -m "[npm] Release %s"
53 | git push
54 | shell: bash
55 |
56 | - run: npm ci
57 | - run: npm publish --provenance --access public
58 | env:
59 | NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
60 |
61 | - name: Read properties from package.json
62 | id: package_json
63 | uses: zoexx/github-action-json-file-properties@1.0.6
64 | with:
65 | file_path: package.json
66 |
67 | - uses: release-drafter/release-drafter@v6
68 | with:
69 | disable-autolabeler: true
70 | name: ${{ steps.package_json.outputs.version }}
71 | tag: ${{ steps.package_json.outputs.version }}
72 | version: ${{ steps.package_json.outputs.version }}
73 | publish: true
74 | env:
75 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
76 |
--------------------------------------------------------------------------------
/.github/workflows/integration-tests.yml:
--------------------------------------------------------------------------------
1 | # Integration Tests
2 |
3 | name: Integration Tests
4 |
5 | on:
6 | push:
7 | branches:
8 | - master
9 | pull_request:
10 | workflow_dispatch:
11 |
12 | jobs:
13 | integration-tests:
14 | runs-on: ${{ matrix.os }}
15 | strategy:
16 | matrix:
17 | java-version: [21]
18 | node-version: [lts/*]
19 | os: [ubuntu-latest,windows-latest,macos-latest]
20 | steps:
21 | - name: Checkout
22 | uses: actions/checkout@v5
23 | - name: Use Java ${{ matrix.java-version }}
24 | uses: actions/setup-java@v5
25 | with:
26 | distribution: temurin
27 | java-version: ${{ matrix.java-version }}
28 | cache: maven
29 | - name: Use Node.js ${{ matrix.node-version }}
30 | uses: actions/setup-node@v5
31 | with:
32 | node-version: ${{ matrix.node-version }}
33 | - name: npm ci
34 | run: npm ci
35 |
36 | - name: "Integration Test: wcmio-archetype-module"
37 | run: mvn clean verify
38 | working-directory: integration-test/wcmio-archetype-module
39 | - uses: actions/upload-artifact@v4
40 | if: always()
41 | with:
42 | name: wcmio-archetype-module-result-${{ matrix.os }}-java${{ matrix.java-version }}
43 | path: integration-test/wcmio-archetype-module/result/
44 | if-no-files-found: warn
45 | include-hidden-files: true
46 |
47 | - name: "Integration Test: wcmio-archetype-module-cjs"
48 | run: mvn clean verify
49 | working-directory: integration-test/wcmio-archetype-module-cjs
50 | - uses: actions/upload-artifact@v4
51 | if: always()
52 | with:
53 | name: wcmio-archetype-module-cjs-result-${{ matrix.os }}-java${{ matrix.java-version }}
54 | path: integration-test/wcmio-archetype-module-cjs/result/
55 | if-no-files-found: warn
56 | include-hidden-files: true
57 |
58 | - name: "Integration Test: wcmio-archetype-commonjs"
59 | run: mvn clean verify
60 | working-directory: integration-test/wcmio-archetype-commonjs
61 | - uses: actions/upload-artifact@v4
62 | if: always()
63 | with:
64 | name: wcmio-archetype-commonjs-result-${{ matrix.os }}-java${{ matrix.java-version }}
65 | path: integration-test/wcmio-archetype-commonjs/result/
66 | if-no-files-found: warn
67 | include-hidden-files: true
68 |
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-commonjs/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 4.0.0
4 |
5 |
6 | io.wcm.maven
7 | io.wcm.maven.aem-global-parent
8 | 2.2.2
9 |
10 |
11 |
12 | aem-clientlib-generator.it
13 | wcmio-archetype
14 | 1.0.0-SNAPSHOT
15 | pom
16 |
17 |
18 | v22.15.0
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 | com.github.eirslett
27 | frontend-maven-plugin
28 |
29 |
30 | install node and npm
31 |
32 | install-node-and-npm
33 |
34 | process-resources
35 |
36 | ${nodejs.version}
37 |
38 |
39 |
40 | npm install
41 |
42 | npm
43 |
44 | process-resources
45 |
46 | install
47 |
48 |
49 |
50 | npm build:clientlibs
51 |
52 | npm
53 |
54 | process-resources
55 |
56 | run build:clientlibs
57 |
58 |
59 |
60 | npm test:compare-results
61 |
62 | npm
63 |
64 | process-resources
65 |
66 | run test:compare-results
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-module/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 4.0.0
4 |
5 |
6 | io.wcm.maven
7 | io.wcm.maven.aem-global-parent
8 | 2.2.2
9 |
10 |
11 |
12 | aem-clientlib-generator.it
13 | wcmio-archetype
14 | 1.0.0-SNAPSHOT
15 | pom
16 |
17 |
18 | v22.15.0
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 | com.github.eirslett
27 | frontend-maven-plugin
28 |
29 |
30 | install node and npm
31 |
32 | install-node-and-npm
33 |
34 | process-resources
35 |
36 | ${nodejs.version}
37 |
38 |
39 |
40 | npm install
41 |
42 | npm
43 |
44 | process-resources
45 |
46 | install
47 |
48 |
49 |
50 | npm build:clientlibs
51 |
52 | npm
53 |
54 | process-resources
55 |
56 | run build:clientlibs
57 |
58 |
59 |
60 | npm test:compare-results
61 |
62 | npm
63 |
64 | process-resources
65 |
66 | run test:compare-results
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
--------------------------------------------------------------------------------
/integration-test/wcmio-archetype-module-cjs/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 4.0.0
4 |
5 |
6 | io.wcm.maven
7 | io.wcm.maven.aem-global-parent
8 | 2.2.2
9 |
10 |
11 |
12 | aem-clientlib-generator.it
13 | wcmio-archetype
14 | 1.0.0-SNAPSHOT
15 | pom
16 |
17 |
18 | v22.15.0
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 | com.github.eirslett
27 | frontend-maven-plugin
28 |
29 |
30 | install node and npm
31 |
32 | install-node-and-npm
33 |
34 | process-resources
35 |
36 | ${nodejs.version}
37 |
38 |
39 |
40 | npm install
41 |
42 | npm
43 |
44 | process-resources
45 |
46 | install
47 |
48 |
49 |
50 | npm build:clientlibs
51 |
52 | npm
53 |
54 | process-resources
55 |
56 | run build:clientlibs
57 |
58 |
59 |
60 | npm test:compare-results
61 |
62 | npm
63 |
64 | process-resources
65 |
66 | run test:compare-results
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
--------------------------------------------------------------------------------
/test/TestCase.test.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016 wcm.io and Contributors
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *
16 | */
17 |
18 | "use strict";
19 |
20 | import fs from "fs";
21 | import walk from "klaw";
22 | import fse from "fs-extra";
23 | import clientlib, { fileExists } from "../lib/clientlib.js";
24 | import path from "path";
25 | import { fileURLToPath } from "url";
26 | import assert from "assert";
27 |
28 | import clientLibConf from "./clientlib.config.js";
29 |
30 | const __filename = fileURLToPath(import.meta.url);
31 | const __dirname = path.dirname(__filename);
32 |
33 | var resultDir = path.join(__dirname, "result");
34 | var expectedDir = path.join(__dirname, "expected");
35 |
36 |
37 | describe("Test output", function() {
38 |
39 | // cleanup result folder
40 | beforeEach(function(){
41 | fse.removeSync(resultDir);
42 | fs.mkdirSync(resultDir);
43 | });
44 |
45 | it("should create files correctly", function(done) {
46 |
47 | var libs = clientLibConf.libs;
48 | delete clientLibConf.libs;
49 |
50 | clientlib(libs, clientLibConf, function() {
51 |
52 | var items = []; // files, directories, symlinks, etc
53 | walk(expectedDir)
54 | .on("data", function (item) {
55 | items.push(item.path)
56 | })
57 | .on("end", function () {
58 |
59 | items.forEach(function(expectedFile) {
60 | var subFilePath = path.relative(expectedDir, expectedFile);
61 | if (!subFilePath) {
62 | return;
63 | }
64 |
65 | var resultFile = path.join(resultDir, subFilePath);
66 |
67 | assert.ok(fileExists(resultFile), "file does not exist in result: " + subFilePath);
68 |
69 | if (!fs.lstatSync(expectedFile).isDirectory()) {
70 | var result = fs.readFileSync(resultFile, "utf-8").replace(/\r\n/g, "\n");
71 | var expected = fs.readFileSync(expectedFile, "utf-8").replace(/\r\n/g, "\n");
72 |
73 | assert.equal(result, expected, "content of " + subFilePath + " is not expected");
74 | }
75 |
76 | });
77 |
78 | done();
79 | });
80 | });
81 | });
82 | });
83 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 |
2 | Apache License
3 | Version 2.0, January 2004
4 | http://www.apache.org/licenses/
5 |
6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7 |
8 | 1. Definitions.
9 |
10 | "License" shall mean the terms and conditions for use, reproduction,
11 | and distribution as defined by Sections 1 through 9 of this document.
12 |
13 | "Licensor" shall mean the copyright owner or entity authorized by
14 | the copyright owner that is granting the License.
15 |
16 | "Legal Entity" shall mean the union of the acting entity and all
17 | other entities that control, are controlled by, or are under common
18 | control with that entity. For the purposes of this definition,
19 | "control" means (i) the power, direct or indirect, to cause the
20 | direction or management of such entity, whether by contract or
21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
22 | outstanding shares, or (iii) beneficial ownership of such entity.
23 |
24 | "You" (or "Your") shall mean an individual or Legal Entity
25 | exercising permissions granted by this License.
26 |
27 | "Source" form shall mean the preferred form for making modifications,
28 | including but not limited to software source code, documentation
29 | source, and configuration files.
30 |
31 | "Object" form shall mean any form resulting from mechanical
32 | transformation or translation of a Source form, including but
33 | not limited to compiled object code, generated documentation,
34 | and conversions to other media types.
35 |
36 | "Work" shall mean the work of authorship, whether in Source or
37 | Object form, made available under the License, as indicated by a
38 | copyright notice that is included in or attached to the work
39 | (an example is provided in the Appendix below).
40 |
41 | "Derivative Works" shall mean any work, whether in Source or Object
42 | form, that is based on (or derived from) the Work and for which the
43 | editorial revisions, annotations, elaborations, or other modifications
44 | represent, as a whole, an original work of authorship. For the purposes
45 | of this License, Derivative Works shall not include works that remain
46 | separable from, or merely link (or bind by name) to the interfaces of,
47 | the Work and Derivative Works thereof.
48 |
49 | "Contribution" shall mean any work of authorship, including
50 | the original version of the Work and any modifications or additions
51 | to that Work or Derivative Works thereof, that is intentionally
52 | submitted to Licensor for inclusion in the Work by the copyright owner
53 | or by an individual or Legal Entity authorized to submit on behalf of
54 | the copyright owner. For the purposes of this definition, "submitted"
55 | means any form of electronic, verbal, or written communication sent
56 | to the Licensor or its representatives, including but not limited to
57 | communication on electronic mailing lists, source code control systems,
58 | and issue tracking systems that are managed by, or on behalf of, the
59 | Licensor for the purpose of discussing and improving the Work, but
60 | excluding communication that is conspicuously marked or otherwise
61 | designated in writing by the copyright owner as "Not a Contribution."
62 |
63 | "Contributor" shall mean Licensor and any individual or Legal Entity
64 | on behalf of whom a Contribution has been received by Licensor and
65 | subsequently incorporated within the Work.
66 |
67 | 2. Grant of Copyright License. Subject to the terms and conditions of
68 | this License, each Contributor hereby grants to You a perpetual,
69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70 | copyright license to reproduce, prepare Derivative Works of,
71 | publicly display, publicly perform, sublicense, and distribute the
72 | Work and such Derivative Works in Source or Object form.
73 |
74 | 3. Grant of Patent License. Subject to the terms and conditions of
75 | this License, each Contributor hereby grants to You a perpetual,
76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77 | (except as stated in this section) patent license to make, have made,
78 | use, offer to sell, sell, import, and otherwise transfer the Work,
79 | where such license applies only to those patent claims licensable
80 | by such Contributor that are necessarily infringed by their
81 | Contribution(s) alone or by combination of their Contribution(s)
82 | with the Work to which such Contribution(s) was submitted. If You
83 | institute patent litigation against any entity (including a
84 | cross-claim or counterclaim in a lawsuit) alleging that the Work
85 | or a Contribution incorporated within the Work constitutes direct
86 | or contributory patent infringement, then any patent licenses
87 | granted to You under this License for that Work shall terminate
88 | as of the date such litigation is filed.
89 |
90 | 4. Redistribution. You may reproduce and distribute copies of the
91 | Work or Derivative Works thereof in any medium, with or without
92 | modifications, and in Source or Object form, provided that You
93 | meet the following conditions:
94 |
95 | (a) You must give any other recipients of the Work or
96 | Derivative Works a copy of this License; and
97 |
98 | (b) You must cause any modified files to carry prominent notices
99 | stating that You changed the files; and
100 |
101 | (c) You must retain, in the Source form of any Derivative Works
102 | that You distribute, all copyright, patent, trademark, and
103 | attribution notices from the Source form of the Work,
104 | excluding those notices that do not pertain to any part of
105 | the Derivative Works; and
106 |
107 | (d) If the Work includes a "NOTICE" text file as part of its
108 | distribution, then any Derivative Works that You distribute must
109 | include a readable copy of the attribution notices contained
110 | within such NOTICE file, excluding those notices that do not
111 | pertain to any part of the Derivative Works, in at least one
112 | of the following places: within a NOTICE text file distributed
113 | as part of the Derivative Works; within the Source form or
114 | documentation, if provided along with the Derivative Works; or,
115 | within a display generated by the Derivative Works, if and
116 | wherever such third-party notices normally appear. The contents
117 | of the NOTICE file are for informational purposes only and
118 | do not modify the License. You may add Your own attribution
119 | notices within Derivative Works that You distribute, alongside
120 | or as an addendum to the NOTICE text from the Work, provided
121 | that such additional attribution notices cannot be construed
122 | as modifying the License.
123 |
124 | You may add Your own copyright statement to Your modifications and
125 | may provide additional or different license terms and conditions
126 | for use, reproduction, or distribution of Your modifications, or
127 | for any such Derivative Works as a whole, provided Your use,
128 | reproduction, and distribution of the Work otherwise complies with
129 | the conditions stated in this License.
130 |
131 | 5. Submission of Contributions. Unless You explicitly state otherwise,
132 | any Contribution intentionally submitted for inclusion in the Work
133 | by You to the Licensor shall be under the terms and conditions of
134 | this License, without any additional terms or conditions.
135 | Notwithstanding the above, nothing herein shall supersede or modify
136 | the terms of any separate license agreement you may have executed
137 | with Licensor regarding such Contributions.
138 |
139 | 6. Trademarks. This License does not grant permission to use the trade
140 | names, trademarks, service marks, or product names of the Licensor,
141 | except as required for reasonable and customary use in describing the
142 | origin of the Work and reproducing the content of the NOTICE file.
143 |
144 | 7. Disclaimer of Warranty. Unless required by applicable law or
145 | agreed to in writing, Licensor provides the Work (and each
146 | Contributor provides its Contributions) on an "AS IS" BASIS,
147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148 | implied, including, without limitation, any warranties or conditions
149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150 | PARTICULAR PURPOSE. You are solely responsible for determining the
151 | appropriateness of using or redistributing the Work and assume any
152 | risks associated with Your exercise of permissions under this License.
153 |
154 | 8. Limitation of Liability. In no event and under no legal theory,
155 | whether in tort (including negligence), contract, or otherwise,
156 | unless required by applicable law (such as deliberate and grossly
157 | negligent acts) or agreed to in writing, shall any Contributor be
158 | liable to You for damages, including any direct, indirect, special,
159 | incidental, or consequential damages of any character arising as a
160 | result of this License or out of the use or inability to use the
161 | Work (including but not limited to damages for loss of goodwill,
162 | work stoppage, computer failure or malfunction, or any and all
163 | other commercial damages or losses), even if such Contributor
164 | has been advised of the possibility of such damages.
165 |
166 | 9. Accepting Warranty or Additional Liability. While redistributing
167 | the Work or Derivative Works thereof, You may choose to offer,
168 | and charge a fee for, acceptance of support, warranty, indemnity,
169 | or other liability obligations and/or rights consistent with this
170 | License. However, in accepting such obligations, You may act only
171 | on Your own behalf and on Your sole responsibility, not on behalf
172 | of any other Contributor, and only if You agree to indemnify,
173 | defend, and hold each Contributor harmless for any liability
174 | incurred by, or claims asserted against, such Contributor by reason
175 | of your accepting any such warranty or additional liability.
176 |
177 | END OF TERMS AND CONDITIONS
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | aem-clientlib-generator
2 | ======
3 | [](https://github.com/wcm-io-frontend/aem-clientlib-generator/actions?query=workflow%3ABuild)
4 | [](https://github.com/wcm-io-frontend/aem-clientlib-generator/issues)
5 |
6 | A node plugin that creates ClientLib configuration files (repository nodes) for
7 | [AEM Client Libraries](https://helpx.adobe.com/experience-manager/6-3/sites/developing/using/clientlibs.html),
8 | creates _Client Library Folders_ and synchronizes all assets.
9 |
10 | It supports both JSON file format (default) and FileVault XML file format (see `serializationFormat` parameter).
11 |
12 | ## Installation
13 |
14 | ```bash
15 | npm install aem-clientlib-generator
16 | ```
17 |
18 | ## Usage
19 |
20 | ### Command Line Interface
21 |
22 | The CLI `clientlib` is located in `./bin/clientlib-cli.js`.
23 | The command can be used without parameters, it loads the default configuration file `clientlib.config.js`.
24 | More options are described in help menu:
25 |
26 | ```text
27 | Options:
28 | --help, -h Show help [boolean]
29 | --version, -v Show version number [boolean]
30 | --dry 'Dry run' without write operations. [boolean]
31 | --verbose Prints more details [boolean]
32 | ```
33 |
34 | #### clientlib.config.js
35 |
36 | A clientlib configuration file is a simple exported module:
37 |
38 | ```js
39 | export default {
40 | // default working directory (can be changed per 'cwd' in every asset option)
41 | context: import.meta.dirname,
42 |
43 | // path to the clientlib root folder (output)
44 | clientLibRoot: "path/to/clientlib-root",
45 |
46 | // define all clientlib options here as array... (multiple clientlibs)
47 | libs: [
48 | {
49 | name: "test.base.apps.mainapp",
50 |
51 | // optional override path to write clientlib files to, by default files
52 | // are written to lib.name/
53 | outputPath: "explicit/path/to/lib/or/existing/lib/structure",
54 |
55 | assets: {
56 | js: [
57 | "src/frontend/js/app.js"
58 | ],
59 | css: [
60 | "src/frontend/css/styling.css"
61 | ]
62 | }
63 | },
64 | ...// next clientlibs
65 | ],
66 |
67 | // or as object (single clientlib)
68 | libs: {
69 | name: "test.base.apps.mainapp",
70 | assets: {
71 | js: [
72 | "src/frontend/js/app.js"
73 | ],
74 | css: [
75 | "src/frontend/css/styling.css"
76 | ]
77 | }
78 | }
79 | };
80 | ```
81 |
82 | #### npm scripts
83 |
84 | The CLI can be used in a project as local module via npm scripts (defined in `package.json`).
85 |
86 | ```js
87 | // package.json file:
88 |
89 | "scripts": {
90 | "test": "mocha",
91 | "build": "clientlib --verbose"
92 | }
93 | ```
94 |
95 | In this case `npm run build` tries to load the default clientlib configuration file
96 | `clientlib.config.js` (same directory like package.json) and generates all clientslib
97 | as defined.
98 |
99 | ### Module: clientlib(arrProps | props, [options], callback)
100 |
101 | Import the module into a JavaScript file and run the module as a function:
102 |
103 | ```js
104 | var clientlib = require("aem-clientlib-generator");
105 | clientlib(arrProps, { verbose: true }, function () {
106 | console.log("generator has finished");
107 | });
108 | ```
109 |
110 | **Important:** Due to many write operations, the `clientlib` function is **asynchronous**!
111 |
112 | - `arrProps` `{Array}` Array of Clientlib configuration properties (see below)
113 | - `props` `{Object}` Clientlib configuration properties
114 |
115 | - `path` `{String}` Clientlib root path (optional if `options.clientLibRoot` is set)
116 | - `outputPath` `{String}` Clientlib destination path (optional, overrides default behavior of writing to the above path or options.clientLibRoot, useful to supply your own directory naming convention or if you are clientlib-ifying an existing directory)
117 | - `name` `{String}` Clientlib name (required)
118 | - `serializationFormat` `{String}` Type of the target archive for which the resources must be generated [json|xml] (optional, default=json)
119 | - `embed` `{Array}` other Clientlib names that should be embedded (optional)
120 | - `dependencies` `{Array}` other Clientlib names that should be included (optional)
121 | - `categories` `{Array}` to set a category for the clientLib (optional), ovrrides the default that uses the name as category
122 | - `customProperties` `{Array}` by default only a set of known properties will be copied over the clientlib, using this field custom properties can be added
123 | - `cssProcessor` `{Array}` configuration for the clientlib CSS processor, requires AEM 6.2 (optional)
124 | - `jsProcessor` `{Array}` configuration for the clientlib JS processor, requires AEM 6.2 (optional)
125 | - `replaces` `{String}` Path to the library that is replaced by 'this' one
126 | - `disableIfReplacing` `{boolean}` Disable this library if it would replace the old one
127 | - `assets` `{Object}` content that should be copied to the clientlib folder, more details below (required)
128 | - `allowProxy` `{Boolean}` allow for Clientlib creation under `/apps/myapp/clientLibs` but enable proxy to `/etc.clientlibs/myapp/clientlibs/mylib` See [AEM 6.3 Documentation](https://docs.adobe.com/docs/en/aem/6-3/develop/the-basics/clientlibs.html#Locating%20a%20Client%20Library%20Folder%20and%20Using%20the%20Proxy%20Client%20Libraries%20Servlet)
129 | - `longCacheKey` `{String}` optional string with placeholders to use with URL Fingerprinting, eq. `"${project.version}-${buildNumber}"`. This requires the [build-helper-maven-plugin](http://www.mojohaus.org/build-helper-maven-plugin/usage.html) to be configured, see [wcm-io-samples - Clientlibs](https://github.com/wcm-io/wcm-io-samples/blob/develop/bundles/clientlibs/pom.xml#L56).
130 |
131 | - `options` `{Object}` global options to be used for all clientlib definitions (optional)
132 | - `clientLibRoot` {String} Clientlib root path
133 | - `context` {String} changes the current working directory (via `process.chdir()`)
134 | - `cwd` {String} alias for `context`
135 | - `verbose` {Boolean} prints detailed information during generation
136 | - `dry` {Boolean} dry run without file write operations (sets automatically verbose to true)
137 |
138 | * `callback` `{Function}` to be called if clientlib() has finished
139 |
140 | ### The `assets` Object
141 |
142 | The `assets` object determine the content that should be pushed into the clientlib folder. The key stands for
143 | the content type, `js` for JavaScript files, `css` for styles and `resources` for other content such as
144 | fonts or images.
145 |
146 | ```javascript
147 | {
148 | js: {
149 | // JavaScript files to be copied and used for `js.txt` - a clientlib JS configuration file
150 | },
151 | css: {
152 | // CSS files to be copied and used for `css.txt` - a clientlib CSS configuration file
153 | },
154 | resources: {
155 | // other resources that should be copied
156 | }
157 | }
158 | ```
159 |
160 | Each property can be an object of deeper configuration options (`assetConfig`) or an array of files (simple way, see example below).
161 | The following can be configured:
162 |
163 | - `assetConfig` `{Object}` Configuration object for an asset type
164 | - `base` `{String}` path within the clientlib folder where the data should be copied to (optional), default: asset key, e.g. for "js" is the base "js"
165 | - Hint: Using "." copies the files into the clientlib folder instead of the subfolder
166 | - `files` `{Array}` array of file paths (sources) or a src-dest key value map (required)
167 | - Important: The order of JS or CSS files in this property defines the merging/bundling order in AEM clientlib.
168 | - file object contains:
169 | - `src` {String} - source file relative to the current working directory or the global `cwd` option, if set
170 | - `dest` {String} - destination relative to the clientlib folder including base
171 | - `cwd` {String} - change working directory (relative to the context / global `cwd` option); only available with glob pattern
172 | - `flatten` {Boolean} - using file's basename instead of folder hierarchy; default true; only available with glob pattern
173 | - `ignore` `{String|Array}` - glob pattern or array of glob patterns for matches to exclude
174 |
175 | For an glob example see example section below.
176 |
177 | ```javascript
178 | // simple version
179 | js: ["pth/to/file.js", { src: "pth/to/lib/file.js", dest: "lib/file.js" }];
180 | // will be transformed to:
181 | js: {
182 | base: "js";
183 | files: [
184 | { src: "pth/to/file.js", dest: "file.js" },
185 | { src: "pth/to/lib/file.js", dest: "lib/file.js" },
186 | ];
187 | }
188 | ```
189 |
190 | ### Example
191 |
192 | ```javascript
193 | var clientlib = require("aem-clientlib-generator");
194 | clientlib(
195 | [
196 | {
197 | name: "test.base.apps.mainapp",
198 | // the name will be used as subfolder in clientlibs root and for the AEM repository node
199 | // in this example it creates:
200 | // the subfoler: path/to/clientlibs-root/test.base.apps.mainapp/
201 | // repository node: path/to/clientlibs-root/test.base.apps.mainapp.json
202 |
203 | // new in AEM 6.2: configure the clientlib processor by yourself:
204 | // An example to disable minification for CSS:
205 | cssProcessor: ["default:none", "min:none"],
206 |
207 | // using google closure compiler for minification instead of YUI
208 | jsProcessor: ["default:none", "min:gcc;compilationLevel=whitespace"],
209 |
210 | // new in AEM 6.3: create clientLibs in /apps/myapp/clientlibs and proxy to /etc.clientlibs/myapp
211 | allowProxy: true,
212 |
213 | // will copy over the allowed properties and their values to the clientlib
214 | customProperties: [
215 | "customProperty"
216 | ],
217 | customProperty: "customValue",
218 |
219 | // allow URL Fingerprinting via placeholder
220 | longCacheKey: "${project.version}-${buildNumber}",
221 |
222 | assets: {
223 | // creates the JS configuration file:
224 | // path/to/clientlibs-root/test.base.apps.mainapp/js.txt
225 | // which lists all JavaScript files from the ClientLib.
226 | // and copies all files into a js subfolder (default base):
227 | // path/to/clientlibs-root/test.base.apps.mainapp/js/
228 | js: [
229 | // file will be copied to:
230 | // path/to/clientlibs-root/test.base.apps.mainapp/js/app.js
231 | { src: "src/frontend/js/app.js", dest: "app.js" },
232 |
233 | // file will be copied to:
234 | // path/to/clientlibs-root/test.base.apps.mainapp/js/libs/mylib.min.js
235 | {
236 | src: "src/frontend/js/libs/mylib.min.js",
237 | dest: "libs/mylib.min.js",
238 | },
239 |
240 | // copy source map files as well
241 | {
242 | src: "src/frontend/js/libs/mylib.min.js.map",
243 | dest: "libs/mylib.min.js.map",
244 | },
245 | ],
246 |
247 | // creates the CSS configuration file:
248 | // path/to/clientlibs-root/test.base.apps.mainapp/css.txt
249 | css: ["src/frontend/css/styling.css", "src/frontend/css/lib.css"],
250 | },
251 | },
252 | {
253 | name: "test.base.apps.secondapp",
254 | embed: [
255 | "test.base.apps.thirdapp", // this clientlib will be auto embedded in AEM (kind of `merging`)
256 | ],
257 | dependencies: [
258 | "test.base.apps.mainapp", // define clientlib dependency
259 | ],
260 | assets: {
261 | js: {
262 | base: "js", // by default the `base` is the asset key property
263 | files: [
264 | {
265 | src: "src/frontend/secondapp/js/lib.js",
266 | dest: "secondapp-lib.js",
267 | },
268 | ],
269 | },
270 |
271 | // creates the CSS configuration file:
272 | // path/to/clientlibs-root/test.base.apps.secondapp/css.txt
273 | // that lists all CSS files from the ClientLib.
274 | // All files defined below will be copied into the defined base:
275 | // path/to/clientlibs-root/test.base.apps.secondapp/style/
276 | css: {
277 | base: "style", // changes the `base` from `css` (default) to `style`
278 | files: ["src/frontend/secondapp/main.css"],
279 | },
280 | resources: ["src/frontend/resources/template.html"],
281 | },
282 | },
283 | {
284 | name: "test.base.apps.thirdapp",
285 | assets: {
286 | // copy all files into the clientlib subfolder, because `base` is changed:
287 | // path/to/clientlibs-root/test.base.apps.thirdapp/
288 | resources: {
289 | base: ".", // copy the file into `test.base.apps.thirdapp` (root) instead of `test.base.apps.thirdapp/resources`
290 | files: ["src/frontend/resources/notice.txt"],
291 | },
292 | },
293 | },
294 | {
295 | name: "test.base.apps.fourth",
296 | assets: {
297 | js: {
298 | // "flatten" is true by default and using file's basename instead of path for destination
299 | // set to false to keep the folder hierarchy below "cwd"
300 | flatten: false, // remove this option if you like a flat list of files in your clientlib
301 | cwd: "src/frontend/js/", // change working directory (will be stripped from destination)
302 | files: [
303 | "**/*.js", // match all js files recursively
304 | "**/*.js.map",
305 | ],
306 | },
307 | css: [
308 | // all css will copied to destination folder "style" (in base folder css)
309 | { src: "src/frontend/css/*.css", dest: "style/" },
310 |
311 | // all css will copied to destination folder "vendor" (in base folder css)
312 | { src: "src/frontend/secondapp/*.css", dest: "vendor/" },
313 | ],
314 | },
315 | },
316 | {
317 | name: "test.base.apps.myExistingAssetOrganization",
318 | outputPath: path.join(__dirname, "libs", "collectionOne"),
319 | assets: {
320 | // uses existing files at ./libs/collectionOne, since base is set to '.'
321 | js: {
322 | base: ".", // copy the file into `./libs/collectionOne` (outputPath) instead of `{path}/test.base.apps.myExistingAssetOrganization/js`
323 | files: ["libs/collectionOne/index.js"],
324 | },
325 | },
326 | },
327 | ],
328 | {
329 | cwd: __dirname, // using folder of the file as current working directory
330 | clientLibRoot: path.join(__dirname, "path/to/clientlibs-root"),
331 | },
332 | function () {
333 | console.log("clientlibs created");
334 | }
335 | );
336 | ```
337 |
338 | ### Deploying to AEM:
339 |
340 | The generated client library can be deployed to AEM via [Sling Content Loading](https://sling.apache.org/documentation/bundles/content-loading-jcr-contentloader.html). Take a look at the [wcm.io Sample Application](https://github.com/wcm-io/wcm-io-samples/tree/develop/bundles/clientlibs).
341 |
342 | If you've switched the `serializationFormat` to "xml" you can deploy the client library as part of an AEM content package.
343 |
--------------------------------------------------------------------------------
/test/clientlib.config.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016 wcm.io and Contributors
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *
16 | */
17 |
18 | "use strict";
19 |
20 | import path from 'path';
21 | import { fileURLToPath } from 'url';
22 | const __filename = fileURLToPath(import.meta.url);
23 | const __dirname = path.dirname(__filename);
24 |
25 | export default {
26 |
27 | context: __dirname,
28 | clientLibRoot: path.resolve(__dirname, "result", "clientlibs-root"),
29 |
30 | libs: [{
31 | name: "test.base.apps.mainapp",
32 | cssProcessor: ["default:none", "min:none"], // disable minification for CSS
33 | jsProcessor: ["default:none", "min:gcc"], // using google closure compiler instead of YUI,
34 | allowProxy: true,
35 | longCacheKey: "${project.version}-${buildNumber}",
36 | assets: {
37 | js: [{
38 | src: "src/frontend/js/app.js",
39 | dest: "app.js"
40 | },
41 | {
42 | src: "src/frontend/js/libs/mylib.min.js",
43 | dest: "libs/mylib.min.js"
44 | },
45 | {
46 | src: "src/frontend/js/libs/mylib.min.js.map",
47 | dest: "libs/mylib.min.js.map"
48 | }
49 | ],
50 | css: [
51 | "src/frontend/css/styling.css",
52 | "src/frontend/css/lib.css"
53 | ]
54 | }
55 | },
56 | {
57 | name: "test.base.apps.secondapp",
58 | categories: [
59 | "test.categorie.in.config"
60 | ],
61 | embed: [
62 | "test.base.apps.thirdapp" // this clientlib will be auto embedded in AEM (kind of `merging`)
63 | ],
64 | dependencies: [
65 | "test.base.apps.mainapp" // define clientlib dependency
66 | ],
67 | assets: {
68 | js: {
69 | base: "js", // by default the `base` is the asset key property
70 | files: [{
71 | src: "src/frontend/secondapp/js/lib.js",
72 | dest: "secondapp-lib.js"
73 | }]
74 | },
75 | css: {
76 | base: "style", // changes the `base` from `css` (default) to `style`
77 | files: [
78 | "src/frontend/secondapp/main.css"
79 | ]
80 | },
81 | resources: [
82 | "src/frontend/resources/template.html"
83 | ]
84 | }
85 | },
86 | {
87 | name: "test.base.apps.thirdapp",
88 | assets: {
89 | resources: {
90 | base: ".", // copy the file into `test.base.apps.thirdapp` (root) instead of `test.base.apps.thirdapp/resources`
91 | files: [
92 | "src/frontend/resources/notice.txt"
93 | ]
94 | }
95 | }
96 | },
97 | {
98 | name: "test.base.apps.fourth",
99 | assets: {
100 | js: {
101 | // "flatten" is true by default and using file's basename instead of path for destination
102 | // set to false to keep the folder hierarchy below "cwd"
103 | flatten: false, // remove this option if you like a flat list of files in your clientlib
104 | cwd: "src/frontend/js/", // change working directory (will be stripped from destination)
105 | files: [
106 | "**/app.js", // this file should be included only once
107 | "**/*.js", // match all js files recursively
108 | "**/*.js.map"
109 | ]
110 | },
111 | css: [
112 | // all css will copied to destination folder "style" (in base folder css)
113 | {
114 | src: "src/frontend/css/*.css",
115 | dest: "style/"
116 | },
117 | // all css will copied to destination folder "vendor" (in base folder css)
118 | {
119 | src: "src/frontend/secondapp/*.css",
120 | dest: "vendor/"
121 | }
122 | ]
123 | }
124 | },
125 | {
126 | name: "test.base.apps.five",
127 | categories: [
128 | "test.base.apps.five",
129 | "test.categorie.in.config"
130 | ],
131 | embed: [
132 | "test.base.apps.thirdapp" // this clientlib will be auto embedded in AEM (kind of `merging`)
133 | ],
134 | dependencies: [
135 | "test.base.apps.mainapp" // define clientlib dependency
136 | ],
137 | assets: {
138 | js: {
139 | base: "js", // by default the `base` is the asset key property
140 | files: [{
141 | src: "src/frontend/secondapp/js/lib.js",
142 | dest: "secondapp-lib.js"
143 | }]
144 | },
145 | css: {
146 | base: "style", // changes the `base` from `css` (default) to `style`
147 | files: [
148 | "src/frontend/secondapp/main.css"
149 | ]
150 | },
151 | resources: [
152 | "src/frontend/resources/template.html"
153 | ]
154 | }
155 | },
156 | {
157 | name: "test.base.apps.serializationFormatXML",
158 | serializationFormat: "xml",
159 | allowProxy: true,
160 | categories: [
161 | "test.base.apps.six",
162 | "test.categorie.in.config"
163 | ],
164 | embed: [
165 | "test.base.apps.thirdapp" // this clientlib will be auto embedded in AEM (kind of `merging`)
166 | ],
167 | dependencies: "test.base.apps.mainapp",
168 | assets: {
169 | js: {
170 | base: "js", // by default the `base` is the asset key property
171 | files: [{
172 | src: "src/frontend/secondapp/js/lib.js",
173 | dest: "secondapp-lib.js"
174 | }]
175 | },
176 | css: {
177 | base: "style", // changes the `base` from `css` (default) to `style`
178 | files: [
179 | "src/frontend/secondapp/main.css"
180 | ]
181 | },
182 | resources: [
183 | "src/frontend/resources/template.html"
184 | ]
185 | }
186 | },
187 | {
188 | name: "test.base.apps.fourthWithOutputPath",
189 | outputPath: 'result/clientlibs-root/myPrestructuredLibrary',
190 | assets: {
191 | js: {
192 | // "flatten" is true by default and using file's basename instead of path for destination
193 | // set to false to keep the folder hierarchy below "cwd"
194 | flatten: false, // remove this option if you like a flat list of files in your clientlib
195 | cwd: "src/frontend/js/", // change working directory (will be stripped from destination)
196 | files: [
197 | "**/*.js", // match all js files recursively
198 | "**/*.js.map"
199 | ]
200 | },
201 | css: [
202 | // all css will copied to destination folder "style" (in base folder css)
203 | {
204 | src: "src/frontend/css/*.css",
205 | dest: "style/"
206 | },
207 | // all css will copied to destination folder "vendor" (in base folder css)
208 | {
209 | src: "src/frontend/secondapp/*.css",
210 | dest: "vendor/"
211 | }
212 | ]
213 | }
214 | },
215 | {
216 | name: "test.base.apps.customProperties",
217 | serializationFormat: "xml",
218 | outputPath: "result/clientlibs-root/test.base.apps.customProperties",
219 | customProperties: [
220 | "customProperty"
221 | ],
222 | customProperty: "customValue",
223 | allowProxy: true,
224 | categories: [
225 | "test.base.apps.six",
226 | "test.categorie.in.config"
227 | ],
228 | embed: [
229 | "test.base.apps.thirdapp" // this clientlib will be auto embedded in AEM (kind of `merging`)
230 | ],
231 | dependencies: "test.base.apps.mainapp",
232 | assets: {
233 | js: {
234 | base: "js", // by default the `base` is the asset key property
235 | files: [{
236 | src: "src/frontend/secondapp/js/lib.js",
237 | dest: "secondapp-lib.js"
238 | }]
239 | },
240 | css: {
241 | base: "style", // changes the `base` from `css` (default) to `style`
242 | files: [
243 | "src/frontend/secondapp/main.css"
244 | ]
245 | },
246 | resources: [
247 | "src/frontend/resources/template.html"
248 | ]
249 | }
250 | },
251 | {
252 | name: "test.base.apps.customPropertiesNotAllowed",
253 | serializationFormat: "xml",
254 | outputPath: "result/clientlibs-root/test.base.apps.customPropertiesNotAllowed",
255 | customProperty: "customValue",
256 | allowProxy: true,
257 | categories: [
258 | "test.base.apps.six",
259 | "test.categorie.in.config"
260 | ],
261 | embed: [
262 | "test.base.apps.thirdapp" // this clientlib will be auto embedded in AEM (kind of `merging`)
263 | ],
264 | dependencies: "test.base.apps.mainapp",
265 | assets: {
266 | js: {
267 | base: "js", // by default the `base` is the asset key property
268 | files: [{
269 | src: "src/frontend/secondapp/js/lib.js",
270 | dest: "secondapp-lib.js"
271 | }]
272 | },
273 | css: {
274 | base: "style", // changes the `base` from `css` (default) to `style`
275 | files: [
276 | "src/frontend/secondapp/main.css"
277 | ]
278 | },
279 | resources: [
280 | "src/frontend/resources/template.html"
281 | ]
282 | }
283 | },
284 | {
285 | name: "test.base.apps.serializationFormatXMLCustomOutput",
286 | serializationFormat: "xml",
287 | outputPath: 'result/clientlibs-root/redirectOutputTestWithXML',
288 | allowProxy: true,
289 | categories: [
290 | "test.base.apps.six",
291 | "test.categorie.in.config"
292 | ],
293 | embed: [
294 | "test.base.apps.thirdapp" // this clientlib will be auto embedded in AEM (kind of `merging`)
295 | ],
296 | dependencies: "test.base.apps.mainapp",
297 | assets: {
298 | js: {
299 | base: "js", // by default the `base` is the asset key property
300 | files: [{
301 | src: "src/frontend/secondapp/js/lib.js",
302 | dest: "secondapp-lib.js"
303 | }]
304 | },
305 | css: {
306 | base: "style", // changes the `base` from `css` (default) to `style`
307 | files: [
308 | "src/frontend/secondapp/main.css"
309 | ]
310 | },
311 | resources: [
312 | "src/frontend/resources/template.html"
313 | ]
314 | }
315 | },
316 | {
317 | name: "test.base.apps.serializationFormatSlingXML",
318 | serializationFormat: "slingxml",
319 | allowProxy: true,
320 | longCacheKey: "${project.version}-${buildNumber}",
321 | categories: [
322 | "test.base.apps.six",
323 | "test.categorie.in.config"
324 | ],
325 | embed: [
326 | "test.base.apps.thirdapp" // this clientlib will be auto embedded in AEM (kind of `merging`)
327 | ],
328 | dependencies: [
329 | "test.base.apps.mainapp"
330 | ],
331 | assets: {
332 | js: {
333 | base: "js", // by default the `base` is the asset key property
334 | files: [{
335 | src: "src/frontend/secondapp/js/lib.js",
336 | dest: "secondapp-lib.js"
337 | }]
338 | },
339 | css: {
340 | base: "style", // changes the `base` from `css` (default) to `style`
341 | files: [
342 | "src/frontend/secondapp/main.css"
343 | ]
344 | },
345 | resources: [
346 | "src/frontend/resources/template.html"
347 | ]
348 | }
349 | },
350 | {
351 | name: "test.base.apps.ignoreOption",
352 | assets: {
353 | js: {
354 | cwd: "src/frontend/js",
355 | flatten: false,
356 | files: ["**/*"],
357 | ignore: ["**/*.min.js", "**/*.min.js.map"]
358 | }
359 | }
360 | },
361 | {
362 | // client lib with a combination of .css and .less files
363 | name: "test.base.apps.withLessFiles",
364 | assets: {
365 | css: [
366 | "src/frontend/css/grid.less",
367 | "src/frontend/css/styling.css",
368 | "src/frontend/css/lib.css",
369 | ]
370 | }
371 | }
372 | ]
373 | };
374 |
--------------------------------------------------------------------------------
/lib/clientlib.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016 wcm.io and Contributors
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *
16 | */
17 |
18 | "use strict";
19 |
20 | import async from "async";
21 | import path from "path";
22 | import _ from "lodash";
23 | import fs from "fs";
24 | import fse from "fs-extra";
25 | import glob from "glob";
26 |
27 | /**
28 | * JSON serialization format
29 | *
30 | * @type {string}
31 | */
32 | var SERIALIZATION_FORMAT_JSON = "json";
33 |
34 | /**
35 | * XML serialization format for File Vault
36 | *
37 | * @type {string}
38 | */
39 | var SERIALIZATION_FORMAT_XML = "xml";
40 |
41 | /**
42 | * XML serialization format for Sling Initial Content
43 | *
44 | * @type {string}
45 | */
46 | var SERIALIZATION_FORMAT_SLING_XML = "slingxml";
47 |
48 | /**
49 | * List of fields to be evaluated for being added to the {@code cq:ClientLibraryFolder} file descriptor
50 | * @type {String[]}
51 | */
52 | var defaultClientLibDirectoryFields = ["embed", "dependencies", "cssProcessor", "jsProcessor", "allowProxy", "longCacheKey", "replaces", "disableIfReplacing", "guideComponentType"];
53 | var clientLibDirectoryFields = [];
54 |
55 | /**
56 | * List of source file extensions which AEM is able to merge and provide as `.js` or `.css` client-side library
57 | * @type {Object}
58 | */
59 | var ALLOWED_EXTENSIONS = {
60 | css: [".css", ".less"],
61 | js: [".js"]
62 | }
63 |
64 | /**
65 | * @typedef {Object} ClientLibItem
66 | * @property {String} path - Clientlib root path (optional if `options.clientLibRoot` is set)
67 | * @property {String} name - Clientlib name
68 | * @property {String} [serializationFormat=json] - Type of the target archive for which the resources must be generated [json|xml|slingxml] (optional, default=json)
69 | * @property {boolean} [allowProxy] - Is the Clientlib meant to be used as a proxy
70 | * @property {Array} [embed] - other Clientlib names that should be embedded
71 | * @property {Array} [dependencies] - other Clientlib names that should be included
72 | * @property {Array} [categories] - to set a category for the clientLib (optional), ovrrides the default that uses the name as category
73 | * @property {Array} [customProperties] - by default only a set of known properties will be copied over the clientlib, using this field custom properties can be added
74 | * @property {Array} [cssProcessor] - Clientlib processor specification for CSS
75 | * @property {Array} [jsProcessor] - Clientlib processor specification for JS
76 | * @property {Array} assets - content that should be copied to the clientlib folder, more details below
77 | * @property {String} guideComponentType - property added for adaptive forms
78 |
79 | */
80 |
81 | /**
82 | * Check if the given file exists
83 | * @param file
84 | * @returns {boolean}
85 | */
86 | function fileExists(file) {
87 | try {
88 | fs.accessSync(file);
89 | return true;
90 | } catch (e) {
91 | return false;
92 | }
93 | }
94 |
95 | /**
96 | * Removes clientlib folder and configuration file (JSON) for the given
97 | * clientlib item.
98 | * @param {ClientLibItem} item - clientlib properties
99 | * @param {Object} [options] - further options
100 | * @param {Function} done - callback to be invoked after
101 | */
102 | function removeClientLib(item, options, done) {
103 | var configJson = path.join(item.path, item.name + ".json");
104 | var clientLibPath = path.join(item.path, item.name);
105 | var files = [];
106 |
107 | if (_.isFunction(options)) {
108 | done = options;
109 | options = {};
110 | }
111 | if (fileExists(configJson)) {
112 | files.push(configJson);
113 | }
114 | if (fileExists(clientLibPath)) {
115 | files.push(clientLibPath);
116 | }
117 |
118 | if (files.length === 0) {
119 | return done();
120 | }
121 |
122 | options.verbose && console.log("remove clientlib from " + clientLibPath);
123 | if (options.dry) {
124 | return done();
125 | }
126 | async.eachSeries(files, function (file, doneClean) {
127 | fse.remove(file, doneClean);
128 | }, done);
129 | }
130 |
131 | /**
132 | * Write the clientlib asset TXT file (js or css) that describes the
133 | * base and contains all resource paths.
134 | * @param {String} clientLibPath - path to the clientlib folder
135 | * @param {Object} asset - asset object
136 | */
137 | function writeAssetTxt(clientLibPath, asset, options) {
138 |
139 | if (!asset || !asset.type || !_.isArray(asset.files)) {
140 | return;
141 | }
142 | var outputFile = path.join(clientLibPath, asset.type + ".txt");
143 | var basePath = path.posix.join(clientLibPath, asset.base);
144 |
145 | // determines file path relative to the base
146 | var filenames = [];
147 |
148 | options.verbose && console.log("write clientlib asset txt file (type: " + asset.type + "): " + outputFile);
149 |
150 | asset.files.forEach(function (file) {
151 |
152 | // inject only files that correspondents to the asset type
153 | if (ALLOWED_EXTENSIONS[asset.type].indexOf(path.extname(file.dest)) !== -1) {
154 | var rel = path.posix.relative(basePath, file.dest);
155 | filenames.push(rel);
156 | }
157 | });
158 |
159 | var content = "#base=" + asset.base + "\n\n" + filenames.join("\n");
160 | content.trim();
161 |
162 | if (!options.dry) {
163 | fs.writeFileSync(outputFile, content);
164 | }
165 | }
166 |
167 | /**
168 | * Write a configuration JSON file for a clientlib
169 | * with the given properties in `item`
170 | * @param {ClientLibItem} item - clientlib configuration properties
171 | * @param {Array} properties - sorted list of properties to write
172 | * @param {Object} options - further options
173 | */
174 | function writeClientLibJson(item, properties, options) {
175 | var content = {
176 | 'jcr:primaryType': 'cq:ClientLibraryFolder'
177 | };
178 |
179 | properties.forEach(function (property) {
180 | content[property.key] = property.value;
181 | });
182 |
183 | var jsonFile = path.join(item.path, item.name + ".json");
184 | options.verbose && console.log("write clientlib json file: " + jsonFile);
185 | if (!options.dry) {
186 | fse.writeJsonSync(jsonFile, content, {spaces: 2});
187 | }
188 | }
189 |
190 | /**
191 | * Write a configuration FileVault XML file for a clientlib
192 | * with the given properties in `item`
193 | * @param {ClientLibItem} item - clientlib configuration properties
194 | * @param {Array} properties - sorted list of properties to write
195 | * @param {Object} options - further options
196 | */
197 | function writeClientLibXml(item, properties, options) {
198 | var content = '' +
199 | '\n \n";
217 | var contentXml = getXmlOutputFile(item, SERIALIZATION_FORMAT_XML);
218 |
219 | options.verbose && console.log("write clientlib json file: " + contentXml);
220 |
221 | if (!options.dry) {
222 | fse.writeFileSync(contentXml, content);
223 | }
224 | }
225 |
226 | /**
227 | * Write a configuration Sling-Initial-Content XML file for a clientlib
228 | * with the given properties in `item`
229 | * @param {ClientLibItem} item - clientlib configuration properties
230 | * @param {Array} properties - sorted list of properties to write
231 | * @param {Object} options - further options
232 | */
233 | function writeClientLibSlingXml(item, properties, options) {
234 | var content = '' +
235 | '\n' +
236 | '\n ' + item.name + ' ' +
237 | '\n cq:ClientLibraryFolder ';
238 |
239 | properties.forEach(function (property) {
240 | content += '\n \n ' + property.key + ' ';
241 | if (typeof property.value === 'boolean') {
242 | // Boolean value
243 | content +=
244 | '\n ' + property.value + ' ' +
245 | '\n Boolean ';
246 | } else if (Array.isArray(property.value)) {
247 | // Array of strings
248 | content += '\n ';
249 | property.value.forEach(value => {
250 | content += '\n ' + value + ' ';
251 | });
252 | content += '\n \n String ';
253 | } else if (typeof property.value === 'string') {
254 | // String value
255 | content +=
256 | '\n ' + property.value + ' ' +
257 | '\n String ';
258 | }
259 | content += '\n ';
260 | });
261 | content += '\n \n'
262 |
263 | var contentXml = getXmlOutputFile(item, SERIALIZATION_FORMAT_SLING_XML);
264 |
265 | options.verbose && console.log("write clientlib Sling-Initial-Content XML file: " + contentXml);
266 |
267 | if (!options.dry) {
268 | fse.writeFileSync(contentXml, content);
269 | }
270 | }
271 |
272 | /**
273 | * Get the output file name and path for the specified XML serialization format
274 | * @param {ClientLibItem} item - clientlib configuration properties
275 | * @param {String} serializationFormat serialization format (xml|slingxml)
276 | */
277 | function getXmlOutputFile(item, serializationFormat) {
278 |
279 | // Sling initial content: .xml
280 | if (serializationFormat === SERIALIZATION_FORMAT_SLING_XML) {
281 | return item.outputPath || path.join(item.path, item.name + ".xml")
282 | }
283 |
284 | // FileVault: a folder with a .content.xml file in it
285 | var outputPath = item.outputPath || path.join(item.path, item.name);
286 | return path.join(outputPath + "/.content.xml");
287 | }
288 |
289 | /**
290 | * Iterate through the given array of clientlib configuration objects and
291 | * process them asynchronously.
292 | * @param {Array} itemList - array of clientlib configuration items
293 | * @param {Object} [options] - global configuration options
294 | * @param {Function} done - to be called if everything is done
295 | */
296 | function start(itemList, options, done) {
297 |
298 | if (_.isFunction(options)) {
299 | done = options;
300 | options = {};
301 | }
302 |
303 | if (!_.isArray(itemList)) {
304 | itemList = [itemList];
305 | }
306 |
307 | if (options.context || options.cwd) {
308 | options.cwd = options.context || options.cwd;
309 | process.chdir(options.cwd);
310 | }
311 |
312 | if (options.verbose) {
313 | console.log("\nstart aem-clientlib-generator");
314 | console.log(" working directory: " + process.cwd());
315 | }
316 | options.dry && console.log("\nDRY MODE - without write options!");
317 |
318 | async.eachSeries(itemList, function (item, processItemDone) {
319 | processItem(item, options, processItemDone);
320 | }, done);
321 | }
322 |
323 | /**
324 | * Normalize different asset configuration options.
325 | * @param {String} clientLibPath - clientlib subfolder
326 | * @param {Object} assets - asset configuration object
327 | * @returns {*}
328 | */
329 | function normalizeAssets(clientLibPath, assets) {
330 |
331 | var list = assets;
332 |
333 | // transform object to array
334 | if (!_.isArray(assets)) {
335 | list = [];
336 | _.keys(assets).forEach(function (assetKey) {
337 | var assetItem = assets[assetKey];
338 |
339 | // check/transform short version
340 | if (_.isArray(assetItem)) {
341 | assetItem = {
342 | files: assetItem
343 | };
344 | }
345 | if (!assetItem.base) {
346 | assetItem.base = assetKey;
347 | }
348 | assetItem.type = assetKey;
349 | list.push(assetItem);
350 | });
351 | }
352 |
353 | // transform files to scr-dest mapping
354 | list.forEach(function (asset) {
355 |
356 | var mapping = [];
357 | var flatName = typeof asset.flatten !== "boolean" ? true : asset.flatten;
358 | var assetPath = path.posix.join(clientLibPath, asset.base);
359 | var globOptions = {};
360 | if (asset.cwd) {
361 | globOptions.cwd = asset.cwd;
362 | }
363 | if (asset.ignore) {
364 | globOptions.ignore = asset.ignore;
365 | }
366 |
367 | asset.files.forEach(function (file) {
368 | var fileItem = file;
369 |
370 | // convert simple syntax to object
371 | if (_.isString(file)) {
372 | fileItem = {
373 | src: file
374 | };
375 | }
376 |
377 | // no magic pattern -> default behaviour
378 | if (!glob.hasMagic(fileItem.src)) {
379 |
380 | // determine default dest
381 | if (!fileItem.dest) {
382 | fileItem.dest = path.posix.basename(file);
383 | }
384 |
385 | // generate full path
386 | fileItem.dest = path.posix.join(assetPath, fileItem.dest);
387 | mapping.push(fileItem);
388 | }
389 |
390 | // resolve magic pattern
391 | else {
392 | var files = glob.sync(fileItem.src, globOptions);
393 | var hasCwd = !!globOptions.cwd;
394 | var dest = fileItem.dest ? path.posix.join(assetPath, fileItem.dest) : assetPath;
395 |
396 | files.forEach(function (resolvedFile) {
397 |
398 | // check 'flatten' option -> strip dir name
399 | var destFile = flatName ? path.posix.basename(resolvedFile) : resolvedFile;
400 |
401 | var item = {
402 | src: resolvedFile,
403 | dest: path.posix.join(dest, destFile)
404 | };
405 |
406 | // check "cwd" option -> rebuild path, because it was stripped by glob.sync()
407 | if (hasCwd) {
408 | item.src = path.posix.join(globOptions.cwd, resolvedFile);
409 | }
410 |
411 | mapping.push(item);
412 | });
413 | }
414 | });
415 |
416 | mapping = removeDuplicates(mapping, 'src');
417 |
418 | asset.files = mapping;
419 | });
420 |
421 | return list;
422 | }
423 |
424 | /**
425 | * Removes duplicates in array of Objects based on the provided key
426 | * From: https://firstclassjs.com/remove-duplicate-objects-from-javascript-array-how-to-performance-comparison/
427 | * @param {Array} array - array of Objects that will be filtered
428 | * @param {String} key - key that will be used for filter comparison
429 | */
430 | function removeDuplicates(array, key) {
431 | let lookup = new Set();
432 | return array.filter(obj => !lookup.has(obj[key]) && lookup.add(obj[key]));
433 | }
434 |
435 | /**
436 | * Prepares a sorted list of all properties that should be written to the clientlib descriptor.
437 | */
438 | function prepareSortedProperties(item) {
439 | var properties = [];
440 |
441 | // if categories is a config entry append the values to the array, else use item.name
442 | if (item.hasOwnProperty('categories')) {
443 | properties.push({key: 'categories', value: item['categories']});
444 | } else {
445 | properties.push({key: 'categories', value: [item.name]});
446 | }
447 |
448 | clientLibDirectoryFields.forEach(function (nodeKey) {
449 | if (item.hasOwnProperty(nodeKey)) {
450 | properties.push({key: nodeKey, value: item[nodeKey]});
451 | }
452 | });
453 |
454 | // sort properties by key
455 | properties.sort(function (a, b) {
456 | if (a.key < b.key) {
457 | return -1;
458 | }
459 | if (a.key > b.key) {
460 | return 1;
461 | }
462 | return 0;
463 | });
464 |
465 | return properties;
466 | }
467 |
468 | /**
469 | * Process the given clientlib configuration object.
470 | * @param {ClientLibItem} item - clientlib configuration object
471 | * @param {Object} options - configuration options
472 | * @param {Function} processDone - to be called if everything is done
473 | */
474 | function processItem(item, options, processDone) {
475 |
476 | if (!item.path) {
477 | item.path = options.clientLibRoot;
478 | }
479 |
480 | clientLibDirectoryFields.length = 0;
481 | clientLibDirectoryFields = defaultClientLibDirectoryFields.concat(item.customProperties);
482 |
483 | options.verbose && console.log("\n\nprocessing clientlib: " + item.name);
484 |
485 | // remove current files if exists
486 | removeClientLib(item, function (err) {
487 |
488 | var clientLibPath = item.outputPath || path.join(item.path, item.name);
489 |
490 | // create clientlib directory
491 | fse.mkdirsSync(clientLibPath);
492 |
493 | var serializationFormat = item.serializationFormat || SERIALIZATION_FORMAT_JSON;
494 |
495 | options.verbose && console.log("Write node configuration using serialization format: " + serializationFormat);
496 |
497 | var properties = prepareSortedProperties(item);
498 | if (serializationFormat === SERIALIZATION_FORMAT_JSON) {
499 | // write configuration JSON
500 | writeClientLibJson(item, properties, options);
501 | } else if (serializationFormat === SERIALIZATION_FORMAT_SLING_XML) {
502 | // write Sling-Initial-Content configuration
503 | writeClientLibSlingXml(item, properties, options);
504 | } else {
505 | // write FileVault XML configuration
506 | writeClientLibXml(item, properties, options);
507 | }
508 |
509 | var assetList = normalizeAssets(clientLibPath, item.assets);
510 |
511 | // iterate through assets
512 | async.eachSeries(assetList, function (asset, assetDone) {
513 |
514 | // write clientlib creator files
515 | if (asset.type === "js" || asset.type === "css") {
516 | options.verbose && console.log("");
517 | writeAssetTxt(clientLibPath, asset, options);
518 | }
519 |
520 | // copy files for given asset
521 | async.eachSeries(asset.files, function (fileItem, copyDone) {
522 | if (fileItem.src == fileItem.dest) {
523 | options.verbose && console.log(`${fileItem.src} already in output directory`);
524 | return copyDone();
525 | }
526 | options.verbose && console.log("copy:", fileItem.src, fileItem.dest);
527 | if (options.dry) {
528 | return copyDone();
529 | }
530 |
531 | // create directories separately or it will be copied recursively
532 | if (fs.lstatSync(fileItem.src).isDirectory()) {
533 | fs.mkdir(fileItem.dest, { recursive: true }, copyDone);
534 | } else {
535 | fse.copy(fileItem.src, fileItem.dest, copyDone);
536 | }
537 | }, assetDone);
538 |
539 | }, processDone);
540 | });
541 | }
542 |
543 | export default start;
544 |
545 | export {
546 | removeClientLib,
547 | fileExists
548 | };
549 |
--------------------------------------------------------------------------------