diff --git a/.eslintignore b/.eslintignore index 43ccf84..8878297 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,6 +1,8 @@ **/node_modules +**/playground **/public **/build **/config **/scripts **/xsl +**/__tests__ diff --git a/.eslintrc b/.eslintrc index 4add00b..59916a8 100644 --- a/.eslintrc +++ b/.eslintrc @@ -1,503 +1,9 @@ { - "root": true, - "extends": ["react-app", "airbnb"], - "parser": "babel-eslint", - "plugins": [ - "babel", - "react", - "jsx-a11y", - "import", - "react-hooks" - ], - "env": { - "browser": true, - "es6": true, - "commonjs": true, - "node": true - }, - "parserOptions": { - "ecmaFeatures": { - "jsx": true - }, - "ecmaVersion": 12, - "sourceType": "module" - }, + "extends": ["@uncinc/eslint-config"], "globals": { "strapi": true }, "rules": { - "template-curly-spacing" : "off", - - "indent" : "off", - - "react/jsx-props-no-spreading": "off", - - "react-hooks/rules-of-hooks": "error", - - "react-hooks/exhaustive-deps": "off", - - "react/no-unused-prop-types": "warn", - - "react/jsx-no-target-blank": "error", - - "no-invalid-this": "off", - - "babel/no-invalid-this": "error", - - "arrow-spacing": "warn", - - "implicit-arrow-linebreak": "warn", - - "react/no-unused-state": "warn", - - "react/boolean-prop-naming": "off", - - "react/destructuring-assignment": ["warn", "always", { "ignoreClassFields": true }], - - "react/no-access-state-in-setstate": "warn", - - "operator-linebreak": "warn", - - "no-useless-constructor": "warn", - - "react/no-danger": "off", - - "react/jsx-indent-props": "warn", - - "react/jsx-curly-brace-presence": "warn", - - "react/jsx-key": "error", - - "react/jsx-boolean-value": "warn", - - "react/jsx-closing-tag-location": "warn", - - "import/extensions": "error", - - "newline-per-chained-call": "warn", - - "prefer-arrow-callback": "warn", - - "block-spacing": "warn", - - "one-var-declaration-per-line": "warn", - - "prefer-const": "warn", - - "import/first": "off", - - "react/jsx-max-props-per-line": 1, - - "react/jsx-first-prop-new-line": "warn", - - "react/jsx-equals-spacing": "warn", - - "react/jsx-indent": "warn", - - "react/jsx-closing-bracket-location": "off", - - "import/no-mutable-exports": "error", - - "import/no-extraneous-dependencies": "off", - - "object-shorthand": ["off", "never"], - - "object-curly-newline": "off", - - "arrow-body-style": "off", - - "comma-dangle": ["warn", "always-multiline"], - - "import/prefer-default-export": "off", - - "no-cond-assign": "warn", - - "no-console": "off", - - "no-constant-condition": "warn", - - "no-control-regex": "warn", - - "no-continue": "warn", - - "react/forbid-prop-types": "warn", - - "no-debugger": "warn", - - "no-dupe-args": "error", - - "no-dupe-keys": "error", - - "no-duplicate-case": "error", - - "no-empty": "warn", - - "no-empty-character-class": "error", - - "no-ex-assign": "error", - - "no-extra-boolean-cast": "warn", - - "no-extra-semi": "warn", - - "no-func-assign": "error", - - "no-inner-declarations": "error", - - "no-invalid-regexp": "error", - - "no-mixed-operators": "off", - - "no-irregular-whitespace": "error", - - "no-negated-in-lhs": "error", - - "no-obj-calls": "error", - - "no-regex-spaces": "warn", - - "no-sparse-arrays": "error", - - "no-unreachable": "warn", - - "use-isnan": "error", - - "valid-jsdoc": "warn", - - "valid-typeof": "error", - - "array-callback-return": "off", - - "block-scoped-var": "off", - - "prefer-destructuring": "warn", - - "complexity": "off", - - "consistent-return": "off", - - "curly": "warn", - - "default-case": "warn", - - "dot-notation": "off", - - "eqeqeq": "warn", - - "guard-for-in": "off", - - "no-alert": "warn", - - "no-caller": "error", - - "no-div-regex": "off", - - "no-else-return": "off", - - "no-eq-null": "error", - - "no-eval": "error", - - "no-extend-native": "error", - - "no-extra-bind": "error", - - "no-fallthrough": "error", - - "no-floating-decimal": "error", - - "no-implied-eval": "error", - - "no-iterator": "error", - - "no-labels": "off", - - "no-lone-blocks": "warn", - - "no-loop-func": "error", - - "no-multi-spaces": "warn", - - "no-multi-str": "error", - - "no-native-reassign": "error", - - "no-new": "warn", - - "no-new-func": "error", - - "no-new-wrappers": "error", - - "no-octal": "error", - - "no-octal-escape": "error", - - "no-param-reassign": "off", - - "no-process-env": "off", - - "no-proto": "error", - - "no-redeclare": "error", - - "no-return-assign": "off", - - "arrow-parens": ["warn", "always", { "requireForBlockBody": false }], - - "no-script-url": "error", - - "no-self-compare": "error", - - "no-sequences": "error", - - "no-throw-literal": "error", - - "no-unused-expressions": "warn", - - "no-void": "error", - - "no-with": "error", - - "radix": "off", - - "vars-on-top": "off", - - "wrap-iife": "error", - - "yoda": "warn", - - "strict": "off", - - "no-catch-shadow": "error", - - "no-delete-var": "error", - - "no-label-var": "error", - - "no-shadow": "warn", - - "no-shadow-restricted-names": "error", - - "no-undef": "error", - - "no-undef-init": "error", - - "no-multi-assign": "warn", - - "no-undefined": "error", - - "no-unused-vars": ["warn", { "args": "none", "ignoreRestSiblings": true }], - - "no-use-before-define": [ - "error", - { "functions": false, "classes": true, "variables": true } - ], - - "no-restricted-properties": "warn", - - "no-restricted-syntax": "warn", - - "brace-style": "off", - - "camelcase": "warn", - - "comma-spacing": ["warn", { "before": false, "after": true }], - - "comma-style": ["warn", "last"], - - "consistent-this": ["off", "_this"], - - "eol-last": "warn", - - "func-names": "off", - - "func-style": ["warn", "declaration", { "allowArrowFunctions": true }], - - "key-spacing": ["warn", { "beforeColon": false, "afterColon": true }], - - "max-nested-callbacks": ["warn", 5], - - "new-cap": ["warn", { "newIsCap": true, "capIsNew": false }], - - "new-parens": "warn", - - "newline-after-var": "off", - - "no-array-constructor": "off", - - "no-inline-comments": "off", - - "no-lonely-if": "warn", - - "no-mixed-spaces-and-tabs": "warn", - - "no-multiple-empty-lines": ["warn", { "max": 2 }], - - "no-nested-ternary": "warn", - - "no-new-object": "off", - - "no-spaced-func": "warn", - - "no-ternary": "off", - - "no-trailing-spaces": "warn", - - "no-underscore-dangle": "off", - - "no-extra-parens": "off", - - "padding-line-between-statements": "off", - - "one-var": ["warn", "never"], - - "operator-assignment": ["off", "never"], - - "class-methods-use-this": "off", - - "padded-blocks": ["off", "never"], - - "lines-between-class-members": ["warn", "always"], - - "quote-props": ["warn", "as-needed"], - - "quotes": ["off", "single"], - - "semi": ["warn", "always"], - - "semi-spacing": ["warn", { "before": false, "after": true }], - - "sort-vars": "off", - - "keyword-spacing": ["warn", { "before": true, "after": true }], - - "space-before-blocks": ["warn", "always"], - - "function-paren-newline": "off", - - "space-before-function-paren": ["warn", { "anonymous": "never", "named": "never" }], - - "object-curly-spacing": ["warn", "always"], - - "array-bracket-spacing": ["warn", "never"], - - "computed-property-spacing": ["warn", "never"], - - "space-in-parens": ["warn", "never"], - - "space-infix-ops": "warn", - - "space-unary-ops": ["warn", { "words": true, "nonwords": false }], - - "spaced-comment": ["warn", "always"], - - "wrap-regex": "off", - - "no-var": "error", - - "generator-star-spacing": ["error", "before"], - - "max-depth": ["warn", 4], - - "max-len": ["off", 80, 2], - - "max-params": ["off", 99], - - "max-statements": "off", - - "no-bitwise": "off", - - "no-plusplus": "off", - - "react/display-name": "off", - - "react/jsx-tag-spacing": "warn", - - "jsx-quotes": ["warn", "prefer-double"], - - "react/jsx-no-undef": "error", - - "react/jsx-sort-props": "off", - - "react/jsx-uses-react": "error", - - "react/prefer-stateless-function": "warn", - - "react/jsx-uses-vars": "error", - - "react/jsx-no-bind": "error", - - "react/no-did-mount-set-state": "warn", - - "react/no-will-update-set-state": "warn", - - "react/no-did-update-set-state": "warn", - - "react/no-multi-comp": "off", - - "react/no-unknown-property": "warn", - - "react/prop-types": "off", - - "react/react-in-jsx-scope": "error", - - "react/self-closing-comp": "warn", - - "react/jsx-wrap-multilines": "warn", - - "react/no-array-index-key": "warn", - - "react/no-unescaped-entities": "warn", - - "react/sort-comp": "off", - - "jsx-a11y/no-static-element-interactions": "off", - - "jsx-a11y/click-events-have-key-events": "off", - - "jsx-a11y/no-noninteractive-element-interactions": "off", - - "react/jsx-one-expression-per-line": "off", - - "jsx-a11y/anchor-is-valid": "off", - - "jsx-a11y/alt-text": "warn", - - "jsx-a11y/label-has-for": [ - "warn", - { - "required": { - "some": ["nesting", "id"] - } - } - ], - - "jsx-a11y/img-redundant-alt": "warn", - - "jsx-a11y/no-autofocus": "off", - - "jsx-a11y/iframe-has-title": "warn", - - "jsx-a11y/anchor-has-content": "off", - - "jsx-a11y/label-has-associated-control": "warn", - - "jsx-a11y/mouse-events-have-key-events": "off", - - "jsx-a11y/interactive-supports-focus": "off", - - "jsx-a11y/no-distracting-elements": "warn", - - "jsx-a11y/heading-has-content": "warn", - - "jsx-a11y/html-has-lang": "warn", - - "jsx-a11y/href-no-hash": "off", - - "react/jsx-filename-extension": "off", - - "jsx-a11y/no-noninteractive-tabindex": "warn", - - "jsx-a11y/media-has-caption": "off" + "react-hooks/exhaustive-deps": "off" } } diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index c19de9a..1d054a4 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -4,8 +4,10 @@ on: push: branches: - master - - develop pull_request: + branches: + - master + - develop jobs: lint: @@ -21,15 +23,18 @@ jobs: node-version: ${{ matrix.node }} cache: 'yarn' - name: Install dependencies - run: yarn --ignore-scripts --frozen-lockfile + run: yarn --frozen-lockfile + - name: Make build + run: yarn run build - name: Run eslint run: yarn run eslint - - name: Yaml lint - uses: ibiqlik/action-yamllint@v3 + - name: Upload plugin build + uses: actions/upload-artifact@v3 with: - config_file: .yamllint.yml - unit: - name: 'unit' + name: plugin-build + path: build + test: + name: 'test' needs: [lint] runs-on: ubuntu-latest strategy: @@ -41,14 +46,20 @@ jobs: with: node-version: ${{ matrix.node }} cache: 'yarn' - - name: Install dependencies - run: yarn --ignore-scripts --frozen-lockfile - - name: Run test - run: yarn run -s test:unit - - name: Upload coverage to Codecov - uses: codecov/codecov-action@v2 + - name: Download plugin build + uses: actions/download-artifact@v3 with: - token: ${{ secrets.CODECOV }} - flags: unit - verbose: true - fail_ci_if_error: true + name: plugin-build + path: build + - name: Install plugin dependencies + run: yarn build:install + - name: Install playground dependencies + run: yarn playground:install --frozen-lockfile --unsafe-perm + - name: Install plugin into playground + run: yarn playground:install-plugin + - name: Install testing libraries + run: yarn test:install + - name: Run unit tests + run: NODE_ENV=ci yarn test:unit + - name: Run integration tests + run: NODE_ENV=ci yarn test:integration diff --git a/.gitignore b/.gitignore index afe256b..4ef286b 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,9 @@ package-lock.json .DS_Store npm-debug.log .idea + +# Strapi +.strapi-updater.json + +# Production build +build diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 5ad2e06..1157d74 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -4,8 +4,7 @@ We want this community to be friendly and respectful to each other. Please follo ## Development Workflow -To get started with the project, make sure you have a local instance of Strapi running. -See the [Strapi docs](https://github.com/strapi/strapi#getting-started) on how to setup a Strapi project. +This plugin provides a local development instance of Strapi to develop it's features. We call this instance `playground` and it can be found in the playground folder in the root of the project. For that reason it is not needed to have your own Strapi instance running to work on this plugin. Just clone the repo and you're ready to go! #### 1. Fork the [repository](https://github.com/boazpoolman/strapi-plugin-sitemap) @@ -14,8 +13,7 @@ See the [Strapi docs](https://github.com/strapi/strapi#getting-started) on how t #### 2. Clone from your repository into the plugins folder ```bash -cd YOUR_STRAPI_PROJECT/src/plugins -git clone git@github.com:YOUR_USERNAME/strapi-plugin-sitemap.git sitemap +git clone git@github.com:YOUR_USERNAME/strapi-plugin-sitemap.git ``` #### 3. Install the dependencies @@ -23,41 +21,38 @@ git clone git@github.com:YOUR_USERNAME/strapi-plugin-sitemap.git sitemap Go to the plugin and install it's dependencies. ```bash -cd YOUR_STRAPI_PROJECT/src/plugins/sitemap/ && yarn plugin:install +cd strapi-plugin-sitemap && yarn install ``` -#### 4. Enable the plugin +#### 4. Install the dependencies of the playground instance -Add the following lines to the `config/plugins.js` file in your Strapi project. +Run the following command -``` -const path = require('path'); -// ... -{ - 'sitemap': { - enabled: true, - resolve: path.resolve(__dirname, '../src/plugins/sitemap'), - }, -} +```bash +yarn playground:install ``` -#### 5. Rebuild your Strapi project +#### 5. Run the typescript compiler of the plugin -Rebuild your strapi project to build the admin part of the plugin. +As the plugin is written using Typescript you will have to run the typescript compiler during development. Run the following command: ```bash -cd YOUR_STRAPI_PROJECT && yarn build +yarn develop ``` -#### 6. Running the administration panel in development mode +#### 6. Start the playground instance -**Start the administration panel server for development** +Leave the typescript compiler running, open up a new terminal window and browse back to the root of the plugin repo. Run the following command: ```bash -cd YOUR_STRAPI_PROJECT && yarn develop --watch-admin +yarn playground:develop ``` -The administration panel will be available at http://localhost:8080/admin +This will start the playground instance that will have the plugin installed by default. Browse to http://localhost:1337 and create a test admin user to log in to the playground. + +#### 7. Start your contribution! + +You can now start working on your contribution. With the typescript compiler on every change to the plugin should lead to a reload of the Strapi instance in which you can then test your change. If you had trouble setting up this testing environment please feel free to report an issue on Github. ### Commit message convention @@ -73,10 +68,8 @@ We follow the [conventional commits specification](https://www.conventionalcommi ### Linting and tests [ESLint](https://eslint.org/) -[Yamllint](https://github.com/adrienverge/yamllint) -[Jest](https://jestjs.io/) -We use [ESLint](https://eslint.org/) for linting and formatting js code, [Yamllint](https://github.com/adrienverge/yamllint) for linting and formatting yaml code, and [Jest](https://jestjs.io/) for testing. +We use [ESLint](https://eslint.org/) for linting and formatting the code, and [Jest](https://jestjs.io/) for testing. ### Scripts @@ -85,6 +78,7 @@ The `package.json` file contains various scripts for common tasks: - `yarn eslint`: lint files with ESLint. - `yarn eslint:fix`: auto-fix ESLint issues. - `yarn test:unit`: run unit tests with Jest. +- `yarn test:integration`: run integration tests with Jest. ### Sending a pull request diff --git a/LICENSE.md b/LICENSE.md index c5554ea..b73f3b5 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,7 +1,7 @@ -Copyright (c) 2020 Boaz Poolman. +Copyright (c) 2020 - 2023 Boaz Poolman. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file +THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/admin/src/components/CMEditViewExclude/index.js b/admin/src/components/CMEditViewExclude/index.jsx similarity index 100% rename from admin/src/components/CMEditViewExclude/index.js rename to admin/src/components/CMEditViewExclude/index.jsx diff --git a/admin/src/components/Header/index.js b/admin/src/components/Header/index.jsx similarity index 97% rename from admin/src/components/Header/index.js rename to admin/src/components/Header/index.jsx index c71d78a..095eeda 100644 --- a/admin/src/components/Header/index.js +++ b/admin/src/components/Header/index.jsx @@ -33,7 +33,7 @@ const Header = () => { +