diff --git a/.editorconfig b/.editorconfig index 7d23593..720cbaf 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,6 +1,6 @@ # For more information about the properties used in this file, # please see the EditorConfig documentation: -# http://editorconfig.org +# https://editorconfig.org/ [*] charset = utf-8 @@ -10,9 +10,11 @@ indent_style = space insert_final_newline = true trim_trailing_whitespace = true -[{*.yml,package.json,*.js,*.scss}] +[*.md] +trim_trailing_whitespace = false + +[*.{yml,js,json,css,scss}] indent_size = 2 -indent_style = space -# The indent size used in the package.json file cannot be changed: -# https://github.com/npm/npm/pull/3180#issuecomment-16336516 +[composer.json] +indent_size = 4 diff --git a/.gitattributes b/.gitattributes index d3a448e..4718dc9 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,5 +1,5 @@ /tests export-ignore /client/src export-ignore /.gitattributes export-ignore -/.travis.yml export-ignore -/.scrutinizer.yml export-ignore +/.gitignore export-ignore +/.github export-ignore diff --git a/.github/workflows/README.md b/.github/workflows/README.md new file mode 100644 index 0000000..f02d8a9 --- /dev/null +++ b/.github/workflows/README.md @@ -0,0 +1,9 @@ +# CI + +The `ci.yml` file uses [`silverstripe/gha-ci`](https://github.com/silverstripe/gha-ci/) which does its best to identify which types of tests need to be run for your project, against which version of `silverstripe/installer`, with which PHP versions. + +If you find it isn't quite getting it right, there are configuration options available for you to define exactly what jobs you want to be run. See the readme of the gha-ci repository for more information. + +It is recommended that you make this run on a cron, referred to in GitHub Actions as a "schedule". See [the GitHub Actions documentation](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#schedule) for details. + +Make sure to remove this readme in your actual module! diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..bf02210 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,11 @@ +name: CI + +on: + push: + pull_request: + workflow_dispatch: + +jobs: + ci: + name: CI + uses: silverstripe/gha-ci/.github/workflows/ci.yml@v1 diff --git a/.gitignore b/.gitignore index 526870a..5f51392 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,7 @@ -node_modules +node_modules/ /vendor/ .DS_Store - +composer.lock +*.js.map +*.css.map +yarn-error.log diff --git a/.nvmrc b/.nvmrc index f599e28..3c03207 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -10 +18 diff --git a/.scrutinizer.yml b/.scrutinizer.yml deleted file mode 100644 index 051ef9a..0000000 --- a/.scrutinizer.yml +++ /dev/null @@ -1,15 +0,0 @@ -inherit: true - -build: - nodes: - analysis: - tests: - override: [php-scrutinizer-run] - -checks: - php: - code_rating: true - duplication: true - -filter: - paths: [src/*, tests/*] diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 62ae7e8..0000000 --- a/.travis.yml +++ /dev/null @@ -1,43 +0,0 @@ -language: php - -env: - global: - - TRAVIS_NODE_VERSION="10" - -matrix: - include: - - php: 5.6 - env: DB=MYSQL RECIPE_VERSION=1.1.x-dev PHPUNIT_COVERAGE_TEST=1 - - php: 7.0 - env: DB=PGSQL RECIPE_VERSION=4.2.x-dev PHPUNIT_TEST=1 - - php: 7.1 - env: DB=MYSQL RECIPE_VERSION=4.3.x-dev NPM_TEST=1 - - php: 7.2 - env: DB=PGSQL RECIPE_VERSION=4.4.x-dev PHPUNIT_TEST=1 - - php: 7.3 - env: DB=MYSQL RECIPE_VERSION=4.x-dev PHPUNIT_TEST=1 - -before_script: - - phpenv rehash - - phpenv config-rm xdebug.ini - - - composer validate - - composer require --no-update silverstripe/recipe-cms:"$RECIPE_VERSION" - - if [[ $DB == PGSQL ]]; then composer require --no-update silverstripe/postgresql:2.1.x-dev; fi - - composer install --prefer-source --no-interaction --no-progress --no-suggest --optimize-autoloader --verbose --profile - - # Install NPM dependencies - - if [[ $NPM_TEST ]]; then nvm install $TRAVIS_NODE_VERSION && nvm use $TRAVIS_NODE_VERSION && npm install -g yarn && yarn install --network-concurrency 1 && (cd vendor/silverstripe/admin && yarn install --network-concurrency 1) && yarn run build; fi - -script: - - if [[ $PHPUNIT_TEST ]]; then vendor/bin/phpunit; fi - - if [[ $PHPUNIT_COVERAGE_TEST ]]; then phpdbg -qrr vendor/bin/phpunit --coverage-clover=coverage.xml; fi - - if [[ $PHPCS_TEST ]]; then vendor/bin/phpcs src/ tests/ *.php; fi - - if [[ $NPM_TEST ]]; then git diff-files --quiet -w --relative=client; fi - - if [[ $NPM_TEST ]]; then git diff --name-status --relative=client; fi - - if [[ $NPM_TEST ]]; then yarn coverage; fi - - if [[ $NPM_TEST ]]; then yarn lint; fi - -after_success: - - if [[ $PHPUNIT_COVERAGE_TEST ]]; then bash <(curl -s https://codecov.io/bash) -f coverage.xml -F php; fi - - if [[ $NPM_TEST ]]; then bash <(curl -s https://codecov.io/bash) -F js; fi diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 5cef4de..b576a73 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,14 +1,15 @@ # Contributing + - Maintenance on this module is a shared effort of those who use it - To contribute improvements to the code, ensure you raise a pull request and discuss with the module maintainers -- Please follow the SilverStripe [code contribution guidelines](https://docs.silverstripe.org/en/contributing/code/) and [Module Standard](https://docs.silverstripe.org/en/developer_guides/extending/modules/#module-standard) +- Please follow the Silverstripe CMS [code contribution guidelines](https://docs.silverstripe.org/en/contributing/code/) and [Module Standard](https://docs.silverstripe.org/en/developer_guides/extending/modules/#module-standard) - Supply documentation that follows the [GitHub Flavored Markdown](https://help.github.com/articles/markdown-basics/) conventions -- When having discussions about this module in issues or pull request please adhere to the [SilverStripe Community Code of Conduct](https://docs.silverstripe.org/en/contributing/code_of_conduct/) - +- When having discussions about this module in issues or pull request please adhere to the [Silverstripe CMS Community Code of Conduct](https://docs.silverstripe.org/en/project_governance/code_of_conduct/) ## Contributor license agreement -By supplying code to this module in patches, tickets and pull requests, you agree to assign copyright -of that code to MODULE_COPYRIGHT_HOLDER_HERE., on the condition that these code changes are released under the -same BSD license as the original module. We ask for this so that the ownership in the license is clear -and unambiguous. By releasing this code under a permissive license such as BSD, this copyright assignment + +By supplying code to this module in patches, tickets and pull requests, you agree to assign copyright +of that code to MODULE_COPYRIGHT_HOLDER_HERE., on the condition that these code changes are released under the +same BSD license as the original module. We ask for this so that the ownership in the license is clear +and unambiguous. By releasing this code under a permissive license such as BSD, this copyright assignment won't prevent you from using the code in any way you see fit. diff --git a/README.md b/README.md index a7c5603..13e0b8d 100644 --- a/README.md +++ b/README.md @@ -1,109 +1,88 @@ -# SilverStripe supported module skeleton +# Silverstripe CMS supported module skeleton -A useful skeleton to more easily create a [Silverstripe Module](https://docs.silverstripe.org/en/4/developer_guides/extending/modules/) that conform to the +A useful skeleton to more easily create a [Silverstripe CMS Module](https://docs.silverstripe.org/en/developer_guides/extending/modules/) that conform to the [Module Standard](https://docs.silverstripe.org/en/developer_guides/extending/modules/#module-standard). -This readme contains descriptions of the parts of this module base you should customise to meet you own module needs. +This README contains descriptions of the parts of this module base you should customise to meet you own module needs. For example, the module name in the H1 above should be you own module name, and the description text you are reading now is where you should provide a good short explanation of what your module does. -Where possible we have included default text that can be included as is into your module and indicated in +Where possible we have included default text that can be included as is into your module and indicated in other places where you need to customise it -Below is a template of the sections of your readme.md you should ideally include to met the Module Standard +Below is a template of the sections of your `README.md` you should ideally include to met the Module Standard and help others make use of your modules. -### Steps to prepare this module for your own use: +## Steps to prepare this module for your own use + +Ensure you read the +['publishing a module'](https://docs.silverstripe.org/en/developer_guides/extending/how_tos/publish_a_module/) guide +and update your module's `composer.json` to designate your code as a Silversripe CMS module. - Clone this repository into a folder - Add your name/organisation to `LICENSE.md` -- Update this readme with information about your module. Ensure sections that aren't relevant are deleted and +- Update this README with information about your module. Ensure sections that aren't relevant are deleted and placeholders are edited where relevant -- Review the README files in the various provided directories. You should replace these with `.gitkeep` or delete the -directories +- Review the README files in the various provided directories. You should ultimately delete these README files when you have added your code - Update the module's `composer.json` with your requirements and package name -- Update (or remove) `package.json` with your requirements and package name. Run `yarn` (or remove `yarn.lock`) to +- Update (or remove) `package.json` with your requirements and package name. Run `yarn install` (or remove `yarn.lock`) to ensure dependencies resolve correctly - Clear the git history by running `rm -rf .git && git init` - Add and push to a VCS repository - Either [publish](https://getcomposer.org/doc/02-libraries.md#publishing-to-packagist) the module on packagist.org, or add a [custom repository](https://getcomposer.org/doc/02-libraries.md#publishing-to-a-vcs) to your main `composer.json` - Require the module in your main `composer.json` -- If you need to build a JS client - - Ensure that `vendor/silverstripe/admin` is installed with `composer install --prefer-source` instead of the default `--prefer-dist`. You may need to first remove the module from the vendor folder. - - Install third party dependencies in your module AND in `vendor/silverstripe/admin` by running `yarn install` in both locations +- If you need to build your css or js and are using components, injector, scss variables, etc from `silverstripe/admin`: + - Ensure that `silverstripe/admin` is installed with `composer install --prefer-source` instead of the default `--prefer-dist` (you can use `composer reinstall silverstripe/admin --prefer-source` if you already installed it) + - If you are relying on additional dependencies from `silverstripe/admin` instead of adding them as dependencies in your `package.json` file, you need to install third party dependencies in `silverstripe/admin` by running `yarn install` in the `vendor/silverstripe/admin/` directory. - Start developing your module! -## Requirements +## License + +See [License](LICENSE.md) + +This module template defaults to using the "BSD-3-Clause" license. The BSD-3 license is one of the most +permissive open-source license and is used by most Silverstripe CMS module. -* SilverStripe ^4.0 -* [Yarn](https://yarnpkg.com/lang/en/), [NodeJS](https://nodejs.org/en/) (6.x) and [npm](https://npmjs.com) (for building - frontend assets) -* Other module -* Other server requirement -* Etc +To publish your module under a different license: + +- update the [`license.md`](LICENSE.md) file +- update the `license' key in your [`composer.json`](composer.json). + +You can use [choosealicense.com](https://choosealicense.com) to help you pick a suitable license for your project. + +You do not need to keep this section in your README file - the `LICENSE.md` file is sufficient. ## Installation -Add some installation instructions here, having a 1 line composer copy and paste is useful. -Here is a composer command to create a new module project. Ensure you read the -['publishing a module'](https://docs.silverstripe.org/en/developer_guides/extending/how_tos/publish_a_module/) guide -and update your module's composer.json to designate your code as a SilverStripe module. -``` -composer require silverstripe-module/skeleton 4.x-dev +Replace `silverstripe-module/skeleton` in the command below with the composer name of your module. + +```sh +composer require silverstripe-module/skeleton ``` **Note:** When you have completed your module, submit it to Packagist or add it as a VCS repository to your project's composer.json, pointing to the private repository URL. -## License -See [License](license.md) - -We have included a 3-clause BSD license you can use as a default. We advocate for the BSD license as -it is one of the most permissive and open licenses. - -Feel free to alter the [license.md](license.md) to suit if you wan to use an alternative license. -You can use [choosealicense.com](http://choosealicense.com) to help pick a suitable license for your project. - ## Documentation - * [Documentation readme](docs/en/readme.md) -Add links into your docs/ folder here unless your module only requires minimal documentation +- [Documentation readme](docs/en/README.md) + +Add links into your `docs/` folder here unless your module only requires minimal documentation in that case, add here and remove the docs folder. You might use this as a quick table of content if you mhave multiple documentation pages. -## Example configuration (optional) -If your module makes use of the config API in SilverStripe it's a good idea to provide an example config - here that will get the module working out of the box and expose the user to the possible configuration options. +## Example configuration -Provide a yaml code example where possible. +If your module makes use of the config API in Silverstripe CMS it's a good idea to provide an example config +here that will get the module working out of the box and expose the user to the possible configuration options. +Though note that in many cases simply linking to the documentation is enough. -```yaml +Provide a syntax-highlighted code examples where possible. +```yaml Page: config_option: true another_config: - item1 - item2 - ``` - -## Maintainers - * Person here - * Another maintainer - -## Bugtracker -Bugs are tracked in the issues section of this repository. Before submitting an issue please read over -existing issues to ensure yours is unique. - -If the issue does look like a new bug: - - - Create a new issue - - Describe the steps required to reproduce your issue, and the expected outcome. Unit tests, screenshots - and screencasts can help here. - - Describe your environment as detailed as possible: SilverStripe version, Browser, PHP version, - Operating System, any installed SilverStripe modules. - -Please report security issues to the module maintainers directly. Please don't file security issues in the bugtracker. - -## Development and contribution -If you would like to make contributions to the module please ensure you raise a pull request and discuss with the module maintainers. diff --git a/_config/config.yml b/_config/config.yml index e69de29..0a5bbcc 100644 --- a/_config/config.yml +++ b/_config/config.yml @@ -0,0 +1 @@ +# see https://docs.silverstripe.org/en/developer_guides/configuration/configuration/ diff --git a/client/dist/js/bundle.js b/client/dist/js/bundle.js index e4d57c6..eb373e9 100644 --- a/client/dist/js/bundle.js +++ b/client/dist/js/bundle.js @@ -1 +1 @@ -!function(e){function t(r){if(n[r])return n[r].exports;var o=n[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,t),o.l=!0,o.exports}var n={};t.m=e,t.c=n,t.i=function(e){return e},t.d=function(e,n,r){t.o(e,n)||Object.defineProperty(e,n,{configurable:!1,enumerable:!0,get:r})},t.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(n,"a",n),n},t.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},t.p="",t(t.s="./client/src/bundles/bundle.js")}({"./client/src/boot/index.js":function(e,t,n){"use strict";var r=n("./client/src/boot/registerComponents.js"),o=function(e){return e&&e.__esModule?e:{default:e}}(r);window.document.addEventListener("DOMContentLoaded",function(){(0,o.default)()})},"./client/src/boot/registerComponents.js":function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=n(0),o=function(e){return e&&e.__esModule?e:{default:e}}(r);t.default=function(){o.default.component.registerMany({})}},"./client/src/bundles/bundle.js":function(e,t,n){"use strict";n("./client/src/boot/index.js")},0:function(e,t){e.exports=Injector}}); \ No newline at end of file +!function(){"use strict";var e={274:function(e,t,n){var o,u=(o=n(521))&&o.__esModule?o:{default:o};window.document.addEventListener("DOMContentLoaded",(()=>{(0,u.default)()}))},521:function(e,t,n){Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var o=a(n(648)),u=a(n(64));function a(e){return e&&e.__esModule?e:{default:e}}t.default=()=>{o.default.component.registerMany({ExampleComponent:u.default})}},64:function(e,t,n){Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var o,u=(o=n(363))&&o.__esModule?o:{default:o};var a=()=>u.default.createElement("div",{className:"example-component"},"This is an example");t.default=a},708:function(e,t,n){var o=n(311);o(document).ready((()=>{}))},648:function(e){e.exports=Injector},363:function(e){e.exports=React},311:function(e){e.exports=jQuery}},t={};function n(o){var u=t[o];if(void 0!==u)return u.exports;var a=t[o]={exports:{}};return e[o](a,a.exports,n),a.exports}n(708),n(274)}(); \ No newline at end of file diff --git a/client/dist/js/bundle.js.map b/client/dist/js/bundle.js.map deleted file mode 100644 index f66bd8d..0000000 --- a/client/dist/js/bundle.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"sources":["webpack:///webpack/bootstrap d951c975427fd65d0b1b","webpack:///./client/src/boot/index.js","webpack:///./client/src/boot/registerComponents.js","webpack:///./client/src/bundles/bundle.js","webpack:///external \"Injector\""],"names":["window","document","addEventListener","Injector","component","registerMany","require"],"mappings":";AAAA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;;AAGA;AACA;;AAEA;AACA;;AAEA;AACA,mDAA2C,cAAc;;AAEzD;AACA;AACA;AACA;AACA;AACA;AACA;AACA,aAAK;AACL;AACA;;AAEA;AACA;AACA;AACA,mCAA2B,0BAA0B,EAAE;AACvD,yCAAiC,eAAe;AAChD;AACA;AACA;;AAEA;AACA,8DAAsD,+DAA+D;;AAErH;AACA;;AAEA;AACA;;;;;;;;;;;AC/DA;;;;;;AAEAA,OAAOC,QAAP,CAAgBC,gBAAhB,CAAiC,kBAAjC,EAAqD,YAAM;AACvD;AACH,CAFD,E;;;;;;;;;;;;;;ACHA;;;;;;kBAEe,YAAM;AACjBC,uBAASC,SAAT,CAAmBC,YAAnB,CAAgC,EAAhC;AAGH,C;;;;;;;;;;ACHDC,mBAAOA,CAAC,4BAAR,E;;;;;;;ACHA,0B","file":"js/bundle.js","sourcesContent":[" \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// identity function for calling harmony imports with the correct context\n \t__webpack_require__.i = function(value) { return value; };\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, {\n \t\t\t\tconfigurable: false,\n \t\t\t\tenumerable: true,\n \t\t\t\tget: getter\n \t\t\t});\n \t\t}\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = \"./client/src/bundles/bundle.js\");\n\n\n\n// WEBPACK FOOTER //\n// webpack/bootstrap d951c975427fd65d0b1b","/* global window */\nimport registerComponents from 'boot/registerComponents';\n\nwindow.document.addEventListener('DOMContentLoaded', () => {\n registerComponents();\n});\n\n\n\n// WEBPACK FOOTER //\n// ./client/src/boot/index.js","import Injector from 'lib/Injector';\n\nexport default () => {\n Injector.component.registerMany({\n // List your React components here so Injector is aware of them\n });\n};\n\n\n\n// WEBPACK FOOTER //\n// ./client/src/boot/registerComponents.js","// Include any legacy Entwine wrappers\n\n// Include boot entrypoint\nrequire('boot');\n\n\n\n// WEBPACK FOOTER //\n// ./client/src/bundles/bundle.js","module.exports = Injector;\n\n\n//////////////////\n// WEBPACK FOOTER\n// external \"Injector\"\n// module id = 0\n// module chunks = 0"],"sourceRoot":""} \ No newline at end of file diff --git a/client/dist/styles/bundle.css b/client/dist/styles/bundle.css index e69de29..8f2da17 100644 --- a/client/dist/styles/bundle.css +++ b/client/dist/styles/bundle.css @@ -0,0 +1 @@ +.example-component{display:block} diff --git a/client/dist/styles/bundle.css.map b/client/dist/styles/bundle.css.map deleted file mode 100644 index 9bcffb6..0000000 --- a/client/dist/styles/bundle.css.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"sources":[],"names":[],"mappings":"","file":"styles/bundle.css","sourceRoot":""} \ No newline at end of file diff --git a/client/src/boot/README.md b/client/src/boot/README.md index 09cbf11..ffe0f6e 100644 --- a/client/src/boot/README.md +++ b/client/src/boot/README.md @@ -2,4 +2,6 @@ Put your initialisation scripts in here. +See the [Silverstripe CMS javascript documentation](https://docs.silverstripe.org/en/developer_guides/customising_the_admin_interface/javascript_development/) + Make sure to remove this readme in your actual module! diff --git a/client/src/boot/registerComponents.js b/client/src/boot/registerComponents.js index 11e877e..0ac4e4d 100644 --- a/client/src/boot/registerComponents.js +++ b/client/src/boot/registerComponents.js @@ -1,7 +1,9 @@ import Injector from 'lib/Injector'; +import ExampleComponent from 'components/ExampleComponent/ExampleComponent'; export default () => { Injector.component.registerMany({ // List your React components here so Injector is aware of them + ExampleComponent }); }; diff --git a/client/src/bundles/README.md b/client/src/bundles/README.md index 59dde4f..68f9ea2 100644 --- a/client/src/bundles/README.md +++ b/client/src/bundles/README.md @@ -2,4 +2,6 @@ Put your bundle.js file here, pointing to your boot files and legacy scripts. +See the [Silverstripe CMS javascript documentation](https://docs.silverstripe.org/en/developer_guides/customising_the_admin_interface/javascript_development/) + Make sure to remove this readme in your actual module! diff --git a/client/src/bundles/bundle.js b/client/src/bundles/bundle.js index 88fe59a..7802ae4 100644 --- a/client/src/bundles/bundle.js +++ b/client/src/bundles/bundle.js @@ -1,4 +1,5 @@ // Include any legacy Entwine wrappers +import 'entwine/example-file'; // Include boot entrypoint -require('boot'); +import 'boot'; diff --git a/client/src/bundles/bundle.scss b/client/src/bundles/bundle.scss deleted file mode 100644 index 694175c..0000000 --- a/client/src/bundles/bundle.scss +++ /dev/null @@ -1,8 +0,0 @@ -// Import core variables from silverstripe/admin -@import "variables"; - -// Import all of your SCSS stylesheets using relative paths from "components" -// e.g. @import '../components/MyComponent/MyComponent.scss'; - -// Import any legacy SCSS stylesheets -// e.g. @import '../styles/MyComponent-ModelAdmin-legacy.scss diff --git a/client/src/components/ExampleComponent/ExampleComponent.js b/client/src/components/ExampleComponent/ExampleComponent.js new file mode 100644 index 0000000..a9661ed --- /dev/null +++ b/client/src/components/ExampleComponent/ExampleComponent.js @@ -0,0 +1,7 @@ +import React from 'react'; + +const ExampleComponent = () => ( +
This is an example
+); + +export default ExampleComponent; diff --git a/client/src/components/ExampleComponent/ExampleComponent.scss b/client/src/components/ExampleComponent/ExampleComponent.scss new file mode 100644 index 0000000..f2a5156 --- /dev/null +++ b/client/src/components/ExampleComponent/ExampleComponent.scss @@ -0,0 +1,3 @@ +.example-component { + display: block; +} diff --git a/client/src/components/ExampleComponent/tests/ExampleComponent-test.js b/client/src/components/ExampleComponent/tests/ExampleComponent-test.js new file mode 100644 index 0000000..1e061db --- /dev/null +++ b/client/src/components/ExampleComponent/tests/ExampleComponent-test.js @@ -0,0 +1,12 @@ + +/* global jest, test, expect */ + +import React from 'react'; +import ExampleComponent from '../ExampleComponent'; +import { render } from '@testing-library/react'; + +test('ExampleComponent renders', async () => { + const { container } = render(); + const options = container.querySelectorAll('.example-component'); + expect(options).toHaveLength(1); +}); diff --git a/client/src/components/README.md b/client/src/components/README.md index 4800675..d1477c0 100644 --- a/client/src/components/README.md +++ b/client/src/components/README.md @@ -1,3 +1,7 @@ # React components Put any React components in here. + +See the [Silverstripe CMS react documentation](https://docs.silverstripe.org/en/developer_guides/customising_the_admin_interface/reactjs_redux_and_graphql/) + +Make sure to remove this readme in your actual module! diff --git a/client/src/entwine/README.md b/client/src/entwine/README.md new file mode 100644 index 0000000..9a6c530 --- /dev/null +++ b/client/src/entwine/README.md @@ -0,0 +1,8 @@ +# Entwine wrappers + +Put any Entwine wrappers in here to render React components in non-React controlled areas, or +to interact with parts of the Silverstripe CMS that are not React driven yet. + +See the [Silverstripe CMS enwtine documentation](https://docs.silverstripe.org/en/developer_guides/customising_the_admin_interface/jquery_entwine/) + +Make sure to remove this readme in your actual module! diff --git a/client/src/entwine/example-file.js b/client/src/entwine/example-file.js new file mode 100644 index 0000000..6668e6b --- /dev/null +++ b/client/src/entwine/example-file.js @@ -0,0 +1,8 @@ + +/* global jQuery */ + +(function ($) { + $(document).ready(() => { + // your code here. + }); +}(jQuery)); diff --git a/client/src/legacy/entwine/README.md b/client/src/legacy/entwine/README.md deleted file mode 100644 index 21abe26..0000000 --- a/client/src/legacy/entwine/README.md +++ /dev/null @@ -1,6 +0,0 @@ -# Legacy Entwine wrappers - -Put any Entwine wrappers in here to render React components in non-React controlled areas, or -to interact with parts of the SilverStripe admin that are not React driven yet (e.g. the CMS). - -Make sure to remove this readme in your actual module! diff --git a/client/src/styles/admin/pages/_pages.scss b/client/src/styles/admin/pages/_pages.scss new file mode 100644 index 0000000..f65e978 --- /dev/null +++ b/client/src/styles/admin/pages/_pages.scss @@ -0,0 +1 @@ +// There would be some css changes relevant to something in the CMS pages admin diff --git a/client/src/styles/bundle.scss b/client/src/styles/bundle.scss new file mode 100644 index 0000000..5d59feb --- /dev/null +++ b/client/src/styles/bundle.scss @@ -0,0 +1,8 @@ +// Import core variables from silverstripe/admin +@import 'variables'; + +// Import your SCSS stylesheets using relative paths from "components" +@import '../components/ExampleComponent/ExampleComponent.scss'; + +// Import other legacy SCSS stylesheets that don't relate to react components +@import 'admin/pages/pages'; diff --git a/code-of-conduct.md b/code-of-conduct.md deleted file mode 100644 index 53bf39c..0000000 --- a/code-of-conduct.md +++ /dev/null @@ -1 +0,0 @@ -When having discussions about this module in issues or pull request please adhere to the [SilverStripe Community Code of Conduct](https://docs.silverstripe.org/en/contributing/code_of_conduct). diff --git a/composer.json b/composer.json index c654b81..6abd10a 100644 --- a/composer.json +++ b/composer.json @@ -1,6 +1,6 @@ { "name": "silverstripe-module/skeleton", - "description": "A skeleton for SilverStripe modules.", + "description": "A skeleton for Silverstripe CMS modules.", "type": "silverstripe-vendormodule", "keywords": [ "silverstripe", @@ -8,23 +8,20 @@ ], "license": "BSD-3-Clause", "require": { - "silverstripe/framework": "^4.0", - "silverstripe/admin": "^1.0" + "silverstripe/framework": "^5.0", + "silverstripe/admin": "^2.0" }, "require-dev": { - "phpunit/phpunit": "^5.7", - "squizlabs/php_codesniffer": "^3.0" + "phpunit/phpunit": "^9.5", + "squizlabs/php_codesniffer": "^3.7" }, "autoload": { "psr-4": { "SilverStripeModule\\Skeleton\\": "src/", - "SilverStripeModule\\Skeleton\\Tests\\": "tests/" + "SilverStripeModule\\Skeleton\\Tests\\": "tests/php/" } }, "extra": { - "branch-alias": { - "dev-master": "2.x-dev" - }, "expose": [ "client/dist" ] diff --git a/docs/en/README.md b/docs/en/README.md new file mode 100644 index 0000000..0f14222 --- /dev/null +++ b/docs/en/README.md @@ -0,0 +1,8 @@ +# Documentation + +Add your documentation in the `docs/en/` folder as markdown. Note the "en/" part of the path refers to the language (English in this case) used in the documentation you provide. +If your documentation is vast, you can split it into many markdown files and sub folders. + +Look over the [guidance on documentation](https://docs.silverstripe.org/en/contributing/documentation/) + +Make sure to remove this readme in your actual module! diff --git a/docs/en/readme.md b/docs/en/readme.md deleted file mode 100644 index 47c81fc..0000000 --- a/docs/en/readme.md +++ /dev/null @@ -1,7 +0,0 @@ -# Documentation -Add your documentation in the docs/en folder as markdown. Note the "en" refers to the langugae used in the documentation you provide. -If you documentation is vast, you can split it into many markdown files and sub folders. - -Look over the [guidance on documentation](https://docs.silverstripe.org/en/contributing/documentation/) - -Make sure to remove this readme in your actual module! \ No newline at end of file diff --git a/package.json b/package.json index b589d1d..d207927 100644 --- a/package.json +++ b/package.json @@ -1,51 +1,48 @@ { "name": "silverstripe-module-skeleton", - "description": "Description of your module", - "main": "./client/src/boot/index.js", - "author": "You", "engines": { - "node": ">=10.x" + "node": ">=18.x" }, "scripts": { - "build": "yarn && yarn lint && NODE_ENV=production webpack -p --bail --progress", + "build": "yarn && yarn lint && yarn test && rm -rf client/dist/* && NODE_ENV=production webpack --mode production --bail --progress", "dev": "NODE_ENV=development webpack --progress", "watch": "NODE_ENV=development webpack --watch --progress", "css": "WEBPACK_CHILD=css npm run build", "test": "jest", "coverage": "jest --coverage", - "lock": "npm-shrinkwrap --dev", - "lint": "eslint client/src && sass-lint client/src", + "lint": "yarn lint-js && yarn lint-sass", "lint-js": "eslint client/src", "lint-js-fix": "eslint client/src --fix", "lint-sass": "sass-lint client/src" }, "dependencies": { - "babel-polyfill": "6.7.4", - "react": "^16.8.3" + "core-js": "^3.26.0", + "react": "^18.2.0" }, "devDependencies": { - "@silverstripe/eslint-config": "^0.0.5", - "@silverstripe/webpack-config": "^1.0.0", - "babel-jest": "^23.6.0", - "enzyme": "^3.3.0", - "enzyme-adapter-react-16": "^1.10.0", - "jest-cli": "^23.6.0" - }, - "babel": { - "presets": [ - "env", - "react" - ], - "plugins": [ - "transform-object-rest-spread" - ] + "@babel/runtime": "^7.20.0", + "@silverstripe/eslint-config": "^1.0.0", + "@silverstripe/webpack-config": "^2.0.0", + "@testing-library/react": "^14.0.0", + "eslint": "^8.0.0", + "eslint-plugin-react-hooks": "^4.3.0", + "jest-cli": "^29.2.2", + "jest-environment-jsdom": "^29.3.1", + "react-dom": "^18.0.0", + "webpack": "^5.74.0", + "webpack-cli": "^5.0.0" }, + "browserslist": [ + "defaults" + ], "jest": { + "testEnvironment": "jsdom", "roots": [ "client/src" ], - "modulePaths": [ + "moduleDirectories": [ "client/src", + "node_modules", "../admin/client/src", "../admin/node_modules", "../silverstripe/admin/client/src", @@ -53,21 +50,17 @@ "../../silverstripe/admin/client/src", "../../silverstripe/admin/node_modules" ], - "collectCoverageFrom": [ - "**/*.{js,jsx}", - "!**/node_modules/**", - "!**/boot/**", - "!**/bundles/**", - "!**/legacy/**", - "!**/vendor/**", - "!**/*-test.{js,jsx}", - "!**/*-story.{js,jsx}" - ], "testMatch": [ "**/tests/**/*-test.js?(x)" ], "transform": { ".*": "babel-jest" } + }, + "babel": { + "presets": [ + "@babel/preset-env", + "@babel/preset-react" + ] } } diff --git a/phpcs.xml.dist b/phpcs.xml.dist index fe58f6f..488aba4 100644 --- a/phpcs.xml.dist +++ b/phpcs.xml.dist @@ -1,11 +1,13 @@ - - CodeSniffer ruleset for SilverStripe coding conventions. + + CodeSniffer ruleset for Silverstripe coding conventions. + + src + tests - - + diff --git a/phpunit.xml.dist b/phpunit.xml.dist index a5ec7a1..3801dc3 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,13 +1,8 @@ - - - tests/ - - - - src/ - - tests/ - - - + + + + + tests/php + + diff --git a/src/readme.md b/src/readme.md index 450f544..1d016c4 100644 --- a/src/readme.md +++ b/src/readme.md @@ -1,4 +1,5 @@ # Code + Look over the [Developer Docs](https://docs.silverstripe.org) -Make sure to remove this readme in your actual module! \ No newline at end of file +Make sure to remove this readme in your actual module! diff --git a/templates/README.md b/templates/README.md new file mode 100644 index 0000000..f4aa8fc --- /dev/null +++ b/templates/README.md @@ -0,0 +1,7 @@ +# Templates + +Any templates your module uses should be put in here. + +See the [templates and views documentation](https://docs.silverstripe.org/en/developer_guides/templates/) + +Make sure to remove this readme in your actual module! diff --git a/tests/README.md b/tests/README.md new file mode 100644 index 0000000..e0e6f88 --- /dev/null +++ b/tests/README.md @@ -0,0 +1,5 @@ +# Tests + +Look over the [testing documentation](https://docs.silverstripe.org/en/developer_guides/testing/) + +Make sure to remove this readme in your actual module! diff --git a/tests/endtoend/README.md b/tests/endtoend/README.md new file mode 100644 index 0000000..8e25944 --- /dev/null +++ b/tests/endtoend/README.md @@ -0,0 +1,5 @@ +# End-to-end tests + +The supported modules use behat for end-to-end testing, but other options such as Cypress also work well. + +Make sure to remove this readme in your actual module! diff --git a/tests/php/README.md b/tests/php/README.md new file mode 100644 index 0000000..946fcba --- /dev/null +++ b/tests/php/README.md @@ -0,0 +1,5 @@ +# Unit and functional tests + +Look over the [unit testing](https://docs.silverstripe.org/en/developer_guides/testing/unit_testing/) and [functional testing](https://docs.silverstripe.org/en/developer_guides/testing/functional_testing/) documentation. + +Make sure to remove this readme in your actual module! diff --git a/tests/readme.md b/tests/readme.md deleted file mode 100644 index a58dc60..0000000 --- a/tests/readme.md +++ /dev/null @@ -1,4 +0,0 @@ -# Tests -Look over the [Testing documentation](https://docs.silverstripe.org/en/developer_guides/testing/) - -Make sure to remove this readme in your actual module! \ No newline at end of file diff --git a/webpack.config.js b/webpack.config.js index 7bf4440..36f6a71 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -1,58 +1,27 @@ const Path = require('path'); -const webpackConfig = require('@silverstripe/webpack-config'); -const { - resolveJS, - externalJS, - moduleJS, - pluginJS, - moduleCSS, - pluginCSS, -} = webpackConfig; +const { JavascriptWebpackConfig, CssWebpackConfig } = require('@silverstripe/webpack-config'); -const ENV = process.env.NODE_ENV; const PATHS = { - MODULES: 'node_modules', - FILES_PATH: '../', ROOT: Path.resolve(), SRC: Path.resolve('client/src'), - DIST: Path.resolve('client/dist'), }; -const externals = externalJS(ENV, PATHS); -delete externals.reactstrap; - const config = [ - { - name: 'js', - entry: { + // main JS bundle + new JavascriptWebpackConfig('js', PATHS) + .setEntry({ bundle: `${PATHS.SRC}/bundles/bundle.js`, - }, - output: { - path: PATHS.DIST, - filename: 'js/[name].js', - }, - devtool: (ENV !== 'production') ? 'source-map' : '', - resolve: resolveJS(ENV, PATHS), - externals, - module: moduleJS(ENV, PATHS), - plugins: pluginJS(ENV, PATHS), - }, - { - name: 'css', - entry: { - bundle: `${PATHS.SRC}/bundles/bundle.scss`, - }, - output: { - path: PATHS.DIST, - filename: 'styles/[name].css', - }, - devtool: (ENV !== 'production') ? 'source-map' : '', - module: moduleCSS(ENV, PATHS), - plugins: pluginCSS(ENV, PATHS), - }, + }) + .getConfig(), + // sass to css + new CssWebpackConfig('css', PATHS) + .setEntry({ + bundle: `${PATHS.SRC}/styles/bundle.scss`, + }) + .getConfig(), ]; // Use WEBPACK_CHILD=js or WEBPACK_CHILD=css env var to run a single config module.exports = (process.env.WEBPACK_CHILD) ? config.find((entry) => entry.name === process.env.WEBPACK_CHILD) - : module.exports = config; + : config;