From e1a1d9ff45e203d79fa94b578ec82d7debd714a4 Mon Sep 17 00:00:00 2001 From: attackant Date: Tue, 23 Jan 2024 01:53:16 +0000 Subject: [PATCH] Built changes for v2.4.4 from develop 87723c203a8f9f5c2ad7f57ca9e9870200aa2673 --- .deployignore | 52 - .distignore | 53 - .editorconfig | 21 - .eslintignore | 15 - .eslintrc.json | 34 - .gitignore | 14 - .phpcs.xml | 73 - README.md | 84 - assets/js/pluginsidebar/index.jsx | 11 - .../js/pluginsidebar/panels/cover-image.jsx | 41 - .../pluginsidebar/panels/maturity-rating.jsx | 34 - assets/js/pluginsidebar/panels/metadata.jsx | 149 - .../pluginsidebar/panels/publish-controls.jsx | 83 - .../js/pluginsidebar/panels/publish-info.jsx | 48 - assets/js/pluginsidebar/panels/pull-quote.jsx | 47 - assets/js/pluginsidebar/panels/sections.jsx | 66 - assets/js/pluginsidebar/panels/slug.jsx | 31 - assets/js/pluginsidebar/sidebar.jsx | 294 - .../services/hooks/use-site-options/README.md | 19 - .../services/hooks/use-taxonomies/README.md | 11 - .../services/hooks/use-term-cache/README.md | 14 - assets/js/util/delete-at-index.js | 10 - assets/js/util/delete-at-index.test.js | 8 - assets/js/util/safe-json-parse-array.js | 21 - assets/js/util/safe-json-parse-array.test.js | 16 - assets/js/util/safe-json-parse-object.js | 25 - assets/js/util/safe-json-parse-object.test.js | 16 - assets/js/util/safe-json-parse.js | 15 - assets/js/util/safe-json-parse.test.js | 16 - assets/js/util/update-value-at-index.js | 16 - assets/js/util/update-value-at-index.test.js | 39 - babel.config.json | 9 - build/adminSettings.asset.php | 1 + build/adminSettings.js | 2 + build/adminSettings.js.map | 1 + build/pluginSidebar.asset.php | 1 + build/pluginSidebar.js | 3 + build/pluginSidebar.js.LICENSE.txt | 1 + build/pluginSidebar.js.map | 1 + composer.lock | 8679 +++++++++++++++++ phpunit.xml.dist | 17 - .../apple-actions/index/test-class-delete.php | 93 - .../apple-actions/index/test-class-export.php | 307 - .../apple-actions/index/test-class-push.php | 293 - .../test-class-admin-apple-index-page.php | 49 - .../test-class-admin-apple-meta-boxes.php | 104 - tests/admin/test-class-admin-apple-notice.php | 134 - tests/admin/test-class-admin-apple-themes.php | 620 -- tests/admin/test-class-admin-rest.php | 57 - tests/admin/test-class-automation.php | 330 - .../test-class-advertising-settings.php | 137 - .../builders/test-class-component-layouts.php | 57 - .../builders/test-class-component-styles.php | 31 - .../test-class-component-text-styles.php | 32 - .../builders/test-class-components.php | 350 - .../builders/test-class-layout.php | 73 - .../builders/test-class-metadata.php | 165 - .../components/class-component-testcase.php | 43 - .../components/test-class-advertisement.php | 60 - .../components/test-class-audio.php | 93 - .../components/test-class-author.php | 131 - .../components/test-class-body.php | 599 -- .../components/test-class-byline.php | 164 - .../components/test-class-cover.php | 194 - .../components/test-class-date.php | 59 - .../components/test-class-divider.php | 61 - .../components/test-class-embed-generic.php | 409 - .../components/test-class-embed-web-video.php | 267 - .../components/test-class-end-of-article.php | 79 - .../components/test-class-facebook.php | 153 - .../components/test-class-gallery.php | 141 - .../components/test-class-heading.php | 266 - .../components/test-class-image.php | 409 - .../components/test-class-instagram.php | 150 - .../components/test-class-intro.php | 132 - .../components/test-class-link-button.php | 82 - .../components/test-class-podcast.php | 61 - .../components/test-class-quote.php | 311 - .../components/test-class-slug.php | 90 - .../components/test-class-table.php | 333 - .../components/test-class-tiktok.php | 80 - .../components/test-class-title.php | 88 - .../components/test-class-tweet.php | 118 - .../components/test-class-video.php | 138 - .../test-class-exporter-content.php | 76 - tests/apple-exporter/test-class-exporter.php | 54 - tests/apple-exporter/test-class-parser.php | 147 - tests/apple-exporter/test-class-theme.php | 128 - .../apple-push-api/test-class-credentials.php | 27 - .../test-class-mime-builder.php | 64 - tests/bootstrap.php | 94 - tests/class-apple-news-testcase.php | 594 -- tests/data/test-image-2.jpg | Bin 126887 -> 0 bytes tests/data/test-image.jpg | Bin 126887 -> 0 bytes tests/mocks/class-bc-accounts.php | 47 - tests/mocks/class-bc-cms-api.php | 49 - tests/mocks/class-bc-setup.php | 29 - tests/mocks/function-coauthors.php | 148 - tests/test-class-apple-news.php | 293 - webpack.config.js | 49 - 100 files changed, 8689 insertions(+), 10744 deletions(-) delete mode 100644 .deployignore delete mode 100644 .distignore delete mode 100644 .editorconfig delete mode 100644 .eslintignore delete mode 100644 .eslintrc.json delete mode 100644 .gitignore delete mode 100644 .phpcs.xml delete mode 100644 README.md delete mode 100644 assets/js/pluginsidebar/index.jsx delete mode 100644 assets/js/pluginsidebar/panels/cover-image.jsx delete mode 100644 assets/js/pluginsidebar/panels/maturity-rating.jsx delete mode 100644 assets/js/pluginsidebar/panels/metadata.jsx delete mode 100644 assets/js/pluginsidebar/panels/publish-controls.jsx delete mode 100644 assets/js/pluginsidebar/panels/publish-info.jsx delete mode 100644 assets/js/pluginsidebar/panels/pull-quote.jsx delete mode 100644 assets/js/pluginsidebar/panels/sections.jsx delete mode 100644 assets/js/pluginsidebar/panels/slug.jsx delete mode 100644 assets/js/pluginsidebar/sidebar.jsx delete mode 100644 assets/js/services/hooks/use-site-options/README.md delete mode 100644 assets/js/services/hooks/use-taxonomies/README.md delete mode 100644 assets/js/services/hooks/use-term-cache/README.md delete mode 100644 assets/js/util/delete-at-index.js delete mode 100644 assets/js/util/delete-at-index.test.js delete mode 100644 assets/js/util/safe-json-parse-array.js delete mode 100644 assets/js/util/safe-json-parse-array.test.js delete mode 100644 assets/js/util/safe-json-parse-object.js delete mode 100644 assets/js/util/safe-json-parse-object.test.js delete mode 100644 assets/js/util/safe-json-parse.js delete mode 100644 assets/js/util/safe-json-parse.test.js delete mode 100644 assets/js/util/update-value-at-index.js delete mode 100644 assets/js/util/update-value-at-index.test.js delete mode 100644 babel.config.json create mode 100644 build/adminSettings.asset.php create mode 100644 build/adminSettings.js create mode 100644 build/adminSettings.js.map create mode 100644 build/pluginSidebar.asset.php create mode 100644 build/pluginSidebar.js create mode 100644 build/pluginSidebar.js.LICENSE.txt create mode 100644 build/pluginSidebar.js.map create mode 100644 composer.lock delete mode 100644 phpunit.xml.dist delete mode 100644 tests/admin/apple-actions/index/test-class-delete.php delete mode 100644 tests/admin/apple-actions/index/test-class-export.php delete mode 100644 tests/admin/apple-actions/index/test-class-push.php delete mode 100644 tests/admin/test-class-admin-apple-index-page.php delete mode 100644 tests/admin/test-class-admin-apple-meta-boxes.php delete mode 100644 tests/admin/test-class-admin-apple-notice.php delete mode 100644 tests/admin/test-class-admin-apple-themes.php delete mode 100644 tests/admin/test-class-admin-rest.php delete mode 100644 tests/admin/test-class-automation.php delete mode 100644 tests/apple-exporter/builders/test-class-advertising-settings.php delete mode 100644 tests/apple-exporter/builders/test-class-component-layouts.php delete mode 100644 tests/apple-exporter/builders/test-class-component-styles.php delete mode 100644 tests/apple-exporter/builders/test-class-component-text-styles.php delete mode 100644 tests/apple-exporter/builders/test-class-components.php delete mode 100644 tests/apple-exporter/builders/test-class-layout.php delete mode 100644 tests/apple-exporter/builders/test-class-metadata.php delete mode 100644 tests/apple-exporter/components/class-component-testcase.php delete mode 100644 tests/apple-exporter/components/test-class-advertisement.php delete mode 100644 tests/apple-exporter/components/test-class-audio.php delete mode 100644 tests/apple-exporter/components/test-class-author.php delete mode 100644 tests/apple-exporter/components/test-class-body.php delete mode 100644 tests/apple-exporter/components/test-class-byline.php delete mode 100644 tests/apple-exporter/components/test-class-cover.php delete mode 100644 tests/apple-exporter/components/test-class-date.php delete mode 100644 tests/apple-exporter/components/test-class-divider.php delete mode 100644 tests/apple-exporter/components/test-class-embed-generic.php delete mode 100644 tests/apple-exporter/components/test-class-embed-web-video.php delete mode 100644 tests/apple-exporter/components/test-class-end-of-article.php delete mode 100644 tests/apple-exporter/components/test-class-facebook.php delete mode 100644 tests/apple-exporter/components/test-class-gallery.php delete mode 100644 tests/apple-exporter/components/test-class-heading.php delete mode 100644 tests/apple-exporter/components/test-class-image.php delete mode 100644 tests/apple-exporter/components/test-class-instagram.php delete mode 100644 tests/apple-exporter/components/test-class-intro.php delete mode 100644 tests/apple-exporter/components/test-class-link-button.php delete mode 100644 tests/apple-exporter/components/test-class-podcast.php delete mode 100644 tests/apple-exporter/components/test-class-quote.php delete mode 100644 tests/apple-exporter/components/test-class-slug.php delete mode 100644 tests/apple-exporter/components/test-class-table.php delete mode 100644 tests/apple-exporter/components/test-class-tiktok.php delete mode 100644 tests/apple-exporter/components/test-class-title.php delete mode 100644 tests/apple-exporter/components/test-class-tweet.php delete mode 100644 tests/apple-exporter/components/test-class-video.php delete mode 100644 tests/apple-exporter/test-class-exporter-content.php delete mode 100644 tests/apple-exporter/test-class-exporter.php delete mode 100644 tests/apple-exporter/test-class-parser.php delete mode 100644 tests/apple-exporter/test-class-theme.php delete mode 100644 tests/apple-push-api/test-class-credentials.php delete mode 100644 tests/apple-push-api/test-class-mime-builder.php delete mode 100644 tests/bootstrap.php delete mode 100644 tests/class-apple-news-testcase.php delete mode 100644 tests/data/test-image-2.jpg delete mode 100644 tests/data/test-image.jpg delete mode 100644 tests/mocks/class-bc-accounts.php delete mode 100644 tests/mocks/class-bc-cms-api.php delete mode 100644 tests/mocks/class-bc-setup.php delete mode 100644 tests/mocks/function-coauthors.php delete mode 100644 tests/test-class-apple-news.php delete mode 100644 webpack.config.js diff --git a/.deployignore b/.deployignore deleted file mode 100644 index ca52ad88..00000000 --- a/.deployignore +++ /dev/null @@ -1,52 +0,0 @@ -# Directories and files that we do not want to be included with the built -# IDEs -# version and deployed to WordPress.org. -*.sql -*.tar.gz -*.zip -.DS_Store -.babelrc -.circleci/config.yml -.distignore -.editorconfig -.eslintignore -.eslintrc.json -.git -.gitignore -.gitlab-ci.yml -.idea -.phpcs -.phpcs-cache.json -.phpcs.xml -.phpcs.xml.dist -.phpstan -.phpunit.result.cache -.travis.yml -.vscode -.wordpress-org -.wp-env.json -Gruntfile.js -README.md -Thumbs.db -assets/js/pluginsidebar -assets/js/util -behat.yml -bin -bitbucket-pipelines.yml -multisite.xml -multisite.xml.dist -node_modules -npm-debug.log -phpcs.xml -phpcs.xml.dist -phpstan.neon.dist -phpunit.xml -phpunit.xml.dist -tags -tests -vendor -webpack.config.js -wp-cli.local.yml -yarn.lock -DOCKER_ENV -babel.config.json diff --git a/.distignore b/.distignore deleted file mode 100644 index 852095f1..00000000 --- a/.distignore +++ /dev/null @@ -1,53 +0,0 @@ -# A set of files you probably don't want in your WordPress.org distribution -*.sql -*.tar.gz -*.zip -.DS_Store -.babelrc -.circleci/config.yml -.distignore -.editorconfig -.eslintignore -.eslintrc.json -.git -.github -.gitignore -.gitlab-ci.yml -.idea -.phpcs -.phpcs-cache.json -.phpcs.xml -.phpcs.xml.dist -.phpstan -.phpunit.result.cache -.travis.yml -.vscode -.wordpress-org -.wp-env.json -Gruntfile.js -README.md -Thumbs.db -assets/js/pluginsidebar -assets/js/util -behat.yml -bin -bitbucket-pipelines.yml -composer.json -composer.lock -multisite.xml -multisite.xml.dist -node_modules -npm-debug.log -package-lock.json -package.json -phpcs.xml -phpcs.xml.dist -phpstan.neon.dist -phpunit.xml -phpunit.xml.dist -tags -tests -vendor -webpack.config.js -wp-cli.local.yml -yarn.lock diff --git a/.editorconfig b/.editorconfig deleted file mode 100644 index 4963d419..00000000 --- a/.editorconfig +++ /dev/null @@ -1,21 +0,0 @@ -root = true - -# For all files: -# - UTF-8 -# - Unix newlines -# - Insert new line at the end -# - trim whitespace at end of lines -# - Use 2 spaces for indentation -[*] -charset = utf-8 -end_of_line = lf -insert_final_newline = true -trim_trailing_whitespace = true -indent_style = space -indent_size = 2 - -# For PHP files only: -# - Use tabs (following WordPress conventions) for indentation -# - Show tab width as 2 spaces (inherit from indent_size) -[*.php] -indent_style = tab diff --git a/.eslintignore b/.eslintignore deleted file mode 100644 index 872f242f..00000000 --- a/.eslintignore +++ /dev/null @@ -1,15 +0,0 @@ -assets/js/bulk-export.js -assets/js/cover-image.js -assets/js/export-table.js -assets/js/json.js -assets/js/meta-boxes.js -assets/js/notices.js -assets/js/preview.js -assets/js/sections.js -assets/js/select2.full.min.js -assets/js/settings.js -assets/js/single-push.js -assets/js/theme-edit.js -assets/js/themes.js -build -vendor diff --git a/.eslintrc.json b/.eslintrc.json deleted file mode 100644 index 2c691872..00000000 --- a/.eslintrc.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "env": { - "browser": true, - "es2021": true, - "jest": true, - "node": true - }, - "extends": [ - "airbnb", - "airbnb/hooks" - ], - "parser": "@babel/eslint-parser", - "parserOptions": { - "ecmaFeatures": { - "globalReturn": true, - "impliedStrict": true, - "jsx": true - }, - "sourceType": "module" - }, - "rules": { - "no-restricted-syntax": [ - "error", - { - "message": "Ternaries must be used instead of && in JSX expressions to avoid the potential for accidental output. Use, for example, {condition ? : null}.", - "selector": ":matches(JSXElement, JSXFragment) > JSXExpressionContainer > LogicalExpression[operator='&&']" - }, - { - "message": "Ternaries must be used instead of || in JSX expressions to avoid the potential for accidental output. Use, for example, {thing1 ? thing1 : thing2}.", - "selector": ":matches(JSXElement, JSXFragment) > JSXExpressionContainer > LogicalExpression[operator='||']" - } - ] - } -} diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 6fbcb6cd..00000000 --- a/.gitignore +++ /dev/null @@ -1,14 +0,0 @@ -.DS_Store -.phpcs-cache.json -.phpunit.result.cache -*.zip -tags -composer.lock -vendor -node_modules -npm-debug.log -build - -## IDE -.idea -.vscode diff --git a/.phpcs.xml b/.phpcs.xml deleted file mode 100644 index a03a8abc..00000000 --- a/.phpcs.xml +++ /dev/null @@ -1,73 +0,0 @@ - - - PHP_CodeSniffer standard for Publish to Apple News. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - tests/ - - - - - - - - - - - - - - - - - - - build/ - node_modules/ - vendor/ - - - - diff --git a/README.md b/README.md deleted file mode 100644 index 1dfd33a8..00000000 --- a/README.md +++ /dev/null @@ -1,84 +0,0 @@ -# Publish to Apple News - -[![read me standard badge](https://img.shields.io/badge/readme%20style-standard-brightgreen.svg?style=flat-square)](https://github.com/RichardLitt/standard-readme) - -The Publish to Apple News plugin enables your WordPress content to be published to your Apple News channel. - -- Convert your WordPress content into Apple News format automatically. -- Create a custom design for your Apple News content with no programming knowledge required. -- Automatically or manually publish posts from WordPress to Apple News. -- Control individual posts with options to publish, update, or delete. -- Publish individual posts or in bulk. -- Handles image galleries and popular embeds like YouTube and Vimeo that are supported by Apple News. -- Automatically adjust advertisement settings. - -Please visit our [wiki](https://github.com/alleyinteractive/apple-news/wiki) for detailed information on the follow items: - -- [Background](#background) -- [Releases](#Releases) - - [Install](#install) - - [Use](#use) - - [Source](#from-source) - - [Changelog](#changelog) -- [Development Process](#development-process) - - [Contributing](#contributing) -- [Project Structure](#project-structure) -- [Third-Party Dependencies](#third-party-dependencies) -- [Related Efforts](#related-efforts) -- [Maintainers](#maintainers) -- [License](#license) - -## Background - -To enable content from your WordPress site to be published to your Apple News channel, you must obtain and enter Apple News API credentials from Apple. - -Please see the [Apple Developer](https://developer.apple.com/) and [Apple News Publisher documentation](https://developer.apple.com/news-publisher/) and terms on Apple's website for complete information. - -## Releases - -### Install -See the wiki for [installation instructions](https://github.com/alleyinteractive/apple-news/wiki/Installation). - -### Use -See the wiki for [usage instructions](https://github.com/alleyinteractive/apple-news/wiki/Usage) as well as [configuration guidance](https://github.com/alleyinteractive/apple-news/wiki/Configuration). - -### Source - -### Changelog -See the wiki for the [changelog](https://github.com/alleyinteractive/apple-news/wiki/Changelog). - -## Development Process - -### Contributing -The wiki has [details about contributing](https://github.com/alleyinteractive/apple-news/wiki/Contributing). - -## Project Structure - -## Third-Party Dependencies - -## Related Efforts -- [Connect to Apple Music](https://github.com/alleyinteractive/apple-music) - -## Maintainers -- [Alley](https://github.com/alleyinteractive) - -![Alley logo](https://avatars.githubusercontent.com/u/1733454?s=200&v=4) - -## Releasing the Plugin - -The plugin uses a [built release workflow](./.github/workflows/built-release.yml) -to compile and tag releases. Whenever a new version is detected in the root -`composer.json` file or in the plugin's headers, the workflow will automatically -build the plugin and tag it with a new version. The built tag will contain all -the required front-end assets the plugin may require. This works well for -publishing to WordPress.org or for submodule-ing. - -When you are ready to release a new version of the plugin, you can run -`npm run release` to start the process of setting up a new release. - -### Contributors -Thanks to all of the [contributors](CONTRIBUTORS.md) to this project. - -## License -This project is licensed under the -[GNU Public License (GPL) version 3](LICENSE) or later. diff --git a/assets/js/pluginsidebar/index.jsx b/assets/js/pluginsidebar/index.jsx deleted file mode 100644 index 29c325b9..00000000 --- a/assets/js/pluginsidebar/index.jsx +++ /dev/null @@ -1,11 +0,0 @@ -import { registerPlugin } from '@wordpress/plugins'; -import React from 'react'; - -// Components. -import Icon from '../components/icon'; -import Sidebar from './sidebar'; - -registerPlugin('publish-to-apple-news', { - icon: , - render: Sidebar, -}); diff --git a/assets/js/pluginsidebar/panels/cover-image.jsx b/assets/js/pluginsidebar/panels/cover-image.jsx deleted file mode 100644 index 6d5b1289..00000000 --- a/assets/js/pluginsidebar/panels/cover-image.jsx +++ /dev/null @@ -1,41 +0,0 @@ -import { ImagePicker } from '@alleyinteractive/block-editor-tools'; -import { BaseControl, PanelBody, TextareaControl } from '@wordpress/components'; -import { __ } from '@wordpress/i18n'; -import PropTypes from 'prop-types'; -import React from 'react'; - -const CoverImage = ({ - coverImageCaption, - coverImageId, - onChangeCoverImageCaption, - onChangeCoverImageId, -}) => ( - - - onChangeCoverImageId(0)} - onUpdate={({ id }) => onChangeCoverImageId(id)} - value={coverImageId} - /> - - - -); - -CoverImage.propTypes = { - coverImageCaption: PropTypes.string.isRequired, - coverImageId: PropTypes.number.isRequired, - onChangeCoverImageCaption: PropTypes.func.isRequired, - onChangeCoverImageId: PropTypes.func.isRequired, -}; - -export default CoverImage; diff --git a/assets/js/pluginsidebar/panels/maturity-rating.jsx b/assets/js/pluginsidebar/panels/maturity-rating.jsx deleted file mode 100644 index c2e38996..00000000 --- a/assets/js/pluginsidebar/panels/maturity-rating.jsx +++ /dev/null @@ -1,34 +0,0 @@ -import { PanelBody, SelectControl } from '@wordpress/components'; -import { __ } from '@wordpress/i18n'; -import PropTypes from 'prop-types'; -import React from 'react'; - -const MaturityRating = ({ - maturityRating, - onChangeMaturityRating, -}) => ( - - - -); - -MaturityRating.propTypes = { - maturityRating: PropTypes.string.isRequired, - onChangeMaturityRating: PropTypes.func.isRequired, -}; - -export default MaturityRating; diff --git a/assets/js/pluginsidebar/panels/metadata.jsx b/assets/js/pluginsidebar/panels/metadata.jsx deleted file mode 100644 index 4555de77..00000000 --- a/assets/js/pluginsidebar/panels/metadata.jsx +++ /dev/null @@ -1,149 +0,0 @@ -import { - Button, - CheckboxControl, - PanelBody, - SelectControl, - TextControl, -} from '@wordpress/components'; -import { __ } from '@wordpress/i18n'; -import PropTypes from 'prop-types'; -import React from 'react'; - -// Config. -import { METADATA_SHAPE } from '../../config/prop-types'; - -// Util. -import deleteAtIndex from '../../util/delete-at-index'; -import updateValueAtIndex from '../../util/update-value-at-index'; - -const Metadata = ({ - isHidden, - isPaid, - isPreview, - isSponsored, - metadata, - onChangeIsHidden, - onChangeIsPaid, - onChangeIsPreview, - onChangeIsSponsored, - onChangeMetadata, - onChangeSuppressVideoURL, - onChangeUseImageComponent, - suppressVideoURL, - useImageComponent, -}) => ( - - - - -); - -Metadata.propTypes = { - isHidden: PropTypes.bool.isRequired, - isPaid: PropTypes.bool.isRequired, - isPreview: PropTypes.bool.isRequired, - isSponsored: PropTypes.bool.isRequired, - metadata: PropTypes.arrayOf(PropTypes.shape(METADATA_SHAPE)).isRequired, - onChangeIsHidden: PropTypes.func.isRequired, - onChangeIsPaid: PropTypes.func.isRequired, - onChangeIsPreview: PropTypes.func.isRequired, - onChangeIsSponsored: PropTypes.func.isRequired, - onChangeMetadata: PropTypes.func.isRequired, - onChangeSuppressVideoURL: PropTypes.func.isRequired, - onChangeUseImageComponent: PropTypes.func.isRequired, - suppressVideoURL: PropTypes.bool.isRequired, - useImageComponent: PropTypes.bool.isRequired, -}; - -export default Metadata; diff --git a/assets/js/pluginsidebar/panels/publish-controls.jsx b/assets/js/pluginsidebar/panels/publish-controls.jsx deleted file mode 100644 index 52003762..00000000 --- a/assets/js/pluginsidebar/panels/publish-controls.jsx +++ /dev/null @@ -1,83 +0,0 @@ -import { Button, Spinner } from '@wordpress/components'; -import { __ } from '@wordpress/i18n'; -import PropTypes from 'prop-types'; -import React from 'react'; - -const PublishControls = ({ - apiAutosync, - apiAutosyncDelete, - apiAutosyncUpdate, - deletePost, - loading, - postIsDirty, - postStatus, - publishPost, - publishState, - updatePost, - userCanPublish, -}) => { - // If the post isn't published, or the user can't publish to Apple News, bail. - if (postStatus !== 'publish' || !userCanPublish) { - return null; - } - - // If we're loading, spin. - if (loading) { - return ; - } - - return ( - <> - {postIsDirty ? ( -
- - {__('Please click the Update button above to ensure that all changes are saved before publishing to Apple News.', 'apple-news')} - -
- ) : null} - {publishState !== 'N/A' && !apiAutosyncUpdate ? ( - - ) : null} - {publishState !== 'N/A' && !apiAutosyncDelete ? ( - - ) : null} - {publishState === 'N/A' && !apiAutosync ? ( - - ) : null} - - ); -}; - -PublishControls.propTypes = { - apiAutosync: PropTypes.bool.isRequired, - apiAutosyncDelete: PropTypes.bool.isRequired, - apiAutosyncUpdate: PropTypes.bool.isRequired, - deletePost: PropTypes.func.isRequired, - loading: PropTypes.bool.isRequired, - postIsDirty: PropTypes.bool.isRequired, - postStatus: PropTypes.string.isRequired, - publishPost: PropTypes.func.isRequired, - publishState: PropTypes.string.isRequired, - updatePost: PropTypes.func.isRequired, - userCanPublish: PropTypes.bool.isRequired, -}; - -export default PublishControls; diff --git a/assets/js/pluginsidebar/panels/publish-info.jsx b/assets/js/pluginsidebar/panels/publish-info.jsx deleted file mode 100644 index 4ceafeb4..00000000 --- a/assets/js/pluginsidebar/panels/publish-info.jsx +++ /dev/null @@ -1,48 +0,0 @@ -import { PanelBody } from '@wordpress/components'; -import { __ } from '@wordpress/i18n'; -import PropTypes from 'prop-types'; -import React from 'react'; - -const PublishInfo = ({ - apiId, - dateCreated, - dateModified, - revision, - shareUrl, - publishState, -}) => { - if (!publishState || publishState === 'N/A') { - return null; - } - - return ( - -

{__('API Id', 'apple-news')}

-

{apiId}

-

{__('Created On', 'apple-news')}

-

{dateCreated}

-

{__('Last Updated On', 'apple-news')}

-

{dateModified}

-

{__('Share URL', 'apple-news')}

-

{shareUrl}

-

{__('Revision', 'apple-news')}

-

{revision}

-

{__('Publish State', 'apple-news')}

-

{publishState}

-
- ); -}; - -PublishInfo.propTypes = { - apiId: PropTypes.string.isRequired, - dateCreated: PropTypes.string.isRequired, - dateModified: PropTypes.string.isRequired, - revision: PropTypes.string.isRequired, - shareUrl: PropTypes.string.isRequired, - publishState: PropTypes.string.isRequired, -}; - -export default PublishInfo; diff --git a/assets/js/pluginsidebar/panels/pull-quote.jsx b/assets/js/pluginsidebar/panels/pull-quote.jsx deleted file mode 100644 index 6e24fd03..00000000 --- a/assets/js/pluginsidebar/panels/pull-quote.jsx +++ /dev/null @@ -1,47 +0,0 @@ -import { - PanelBody, - SelectControl, - TextareaControl, -} from '@wordpress/components'; -import { __ } from '@wordpress/i18n'; -import PropTypes from 'prop-types'; -import React from 'react'; - -const PullQuote = ({ - onChangePullquotePosition, - onChangePullquoteText, - pullquotePosition, - pullquoteText, -}) => ( - - - - -); - -PullQuote.propTypes = { - onChangePullquotePosition: PropTypes.func.isRequired, - onChangePullquoteText: PropTypes.func.isRequired, - pullquotePosition: PropTypes.string.isRequired, - pullquoteText: PropTypes.string.isRequired, -}; - -export default PullQuote; diff --git a/assets/js/pluginsidebar/panels/sections.jsx b/assets/js/pluginsidebar/panels/sections.jsx deleted file mode 100644 index 979a25ed..00000000 --- a/assets/js/pluginsidebar/panels/sections.jsx +++ /dev/null @@ -1,66 +0,0 @@ -import { - BaseControl, - CheckboxControl, - PanelBody, - Spinner, -} from '@wordpress/components'; -import { __ } from '@wordpress/i18n'; -import PropTypes from 'prop-types'; -import React from 'react'; - -// Config. -import { SECTION_SHAPE } from '../../config/prop-types'; - -const Sections = ({ - autoAssignCategories, - automaticAssignment, - onChangeAutoAssignCategories, - onChangeSelectedSections, - sections, - selectedSections, -}) => ( - - {!Array.isArray(sections) || sections.length === 0 ? ( - - ) : ( - <> - {automaticAssignment ? ( - - ) : null} - {automaticAssignment && !autoAssignCategories ?
: null} - {(!automaticAssignment || !autoAssignCategories) ? ( - - {sections.map(({ id, name }) => ( - onChangeSelectedSections(id)} - /> - ))} - - ) : null} - - )} -
-); - -Sections.propTypes = { - autoAssignCategories: PropTypes.bool.isRequired, - automaticAssignment: PropTypes.bool.isRequired, - onChangeAutoAssignCategories: PropTypes.func.isRequired, - onChangeSelectedSections: PropTypes.func.isRequired, - sections: PropTypes.arrayOf(PropTypes.shape(SECTION_SHAPE)).isRequired, - selectedSections: PropTypes.arrayOf(PropTypes.string).isRequired, -}; - -export default Sections; diff --git a/assets/js/pluginsidebar/panels/slug.jsx b/assets/js/pluginsidebar/panels/slug.jsx deleted file mode 100644 index 084fa241..00000000 --- a/assets/js/pluginsidebar/panels/slug.jsx +++ /dev/null @@ -1,31 +0,0 @@ -import { - PanelBody, - TextControl, -} from '@wordpress/components'; -import { __ } from '@wordpress/i18n'; -import PropTypes from 'prop-types'; -import React from 'react'; - -const Slug = ({ - onChangeSlug, - slug, -}) => ( - - - -); - -Slug.propTypes = { - onChangeSlug: PropTypes.func.isRequired, - slug: PropTypes.string.isRequired, -}; - -export default Slug; diff --git a/assets/js/pluginsidebar/sidebar.jsx b/assets/js/pluginsidebar/sidebar.jsx deleted file mode 100644 index a930649e..00000000 --- a/assets/js/pluginsidebar/sidebar.jsx +++ /dev/null @@ -1,294 +0,0 @@ -import { usePostMeta, usePostMetaValue } from '@alleyinteractive/block-editor-tools'; -import apiFetch from '@wordpress/api-fetch'; -import { useDispatch, useSelect } from '@wordpress/data'; -import { - PluginSidebar, - PluginSidebarMoreMenuItem, -} from '@wordpress/edit-post'; -import { __ } from '@wordpress/i18n'; -import DOMPurify from 'dompurify'; -import React, { useCallback, useEffect, useState } from 'react'; - -// Panels. -import CoverImage from './panels/cover-image'; -import MaturityRating from './panels/maturity-rating'; -import Metadata from './panels/metadata'; -import PublishControls from './panels/publish-controls'; -import PublishInfo from './panels/publish-info'; -import PullQuote from './panels/pull-quote'; -import Sections from './panels/sections'; -import Slug from './panels/slug'; - -// Utils. -import safeJsonParseArray from '../util/safe-json-parse-array'; - -const Sidebar = () => { - const [state, setState] = useState({ - autoAssignCategories: false, - loading: false, - publishState: 'N/A', - sections: [], - settings: { - apiAutosync: false, - apiAutosyncDelete: false, - apiAutosyncUpdate: false, - automaticAssignment: false, - }, - userCanPublish: false, - }); - - // Destructure values out of state for easier access. - const { - autoAssignCategories, - loading, - publishState, - sections, - settings: { - apiAutosync, - apiAutosyncDelete, - apiAutosyncUpdate, - automaticAssignment, - }, - userCanPublish, - } = state; - - // Get a reference to the dispatch function for notices for use later. - const dispatchNotice = useDispatch('core/notices'); - - // Get information about the current post. - const { - notices, - postId, - postIsDirty, - postStatus, - } = useSelect((select) => { - const editor = select('core/editor'); - return { - notices: editor.getEditedPostAttribute('apple_news_notices'), - postId: editor.getCurrentPostId(), - postIsDirty: editor.isEditedPostDirty(), - postStatus: editor.getEditedPostAttribute('status'), - }; - }); - - // Get read-only values from postmeta. - const [{ - apple_news_api_created_at: dateCreated, - apple_news_api_id: apiId, - apple_news_api_modified_at: dateModified, - apple_news_api_revision: revision, - apple_news_api_share_url: shareUrl, - }] = usePostMeta(); - - // Getters and setters for individual postmeta values. - const [coverImageId, setCoverImageId] = usePostMetaValue('apple_news_coverimage'); - const [coverImageCaption, setCoverImageCaption] = usePostMetaValue('apple_news_coverimage_caption'); - const [isHidden, setIsHidden] = usePostMetaValue('apple_news_is_hidden'); - const [isPaid, setIsPaid] = usePostMetaValue('apple_news_is_paid'); - const [isPreview, setIsPreview] = usePostMetaValue('apple_news_is_preview'); - const [isSponsored, setIsSponsored] = usePostMetaValue('apple_news_is_sponsored'); - const [maturityRating, setMaturityRating] = usePostMetaValue('apple_news_maturity_rating'); - const [metadataRaw, setMetadataRaw] = usePostMetaValue('apple_news_metadata'); - const [pullquoteText, setPullquoteText] = usePostMetaValue('apple_news_pullquote'); - const [pullquotePosition, setPullquotePosition] = usePostMetaValue('apple_news_pullquote_position'); - const [selectedSectionsRaw, setSelectedSectionsRaw] = usePostMetaValue('apple_news_sections'); - const [slug, setSlug] = usePostMetaValue('apple_news_slug'); - const [suppressVideoURL, setSuppressVideoURL] = usePostMetaValue('apple_news_suppress_video_url'); - const [useImageComponent, setUseImageComponent] = usePostMetaValue('apple_news_use_image_component'); - - // Decode selected sections. - const metadata = safeJsonParseArray(metadataRaw); - const selectedSections = safeJsonParseArray(selectedSectionsRaw); - - /** - * A helper function for setting metadata. - * @param {object} next - The metadata value to set. - */ - const setMetadata = (next) => setMetadataRaw(JSON.stringify(next)); - - /** - * A helper function for setting selected sections. - * @param {Array} next - The array of selected sections to set. - */ - const setSelectedSections = (next) => setSelectedSectionsRaw(JSON.stringify(next)); - - /** - * A helper function for displaying a notification to the user. - * @param {string} message - The notification message displayed to the user. - * @param {string} type - Optional. The type of message to display. Defaults to success. - */ - const displayNotification = useCallback((message, type = 'success') => (type === 'success' - ? dispatchNotice.createInfoNotice(DOMPurify.sanitize(message), { type: 'snackbar' }) - : dispatchNotice.createErrorNotice(message, { __unstableHTML: true }) - ), [dispatchNotice]); - - /** - * Sends a request to the REST API to modify the post. - * @param {string} operation - One of delete, publish, update. - */ - const modifyPost = async (operation) => { - setState({ - ...state, - loading: true, - }); - - try { - const { - notifications = [], - publishState: nextPublishState = '', - } = await apiFetch({ - data: { - id: postId, - }, - method: 'POST', - path: `/apple-news/v1/${operation}`, - }); - notifications.forEach((notification) => displayNotification( - notification.message, - notification.type, - )); - setState({ - ...state, - loading: false, - publishState: nextPublishState, - }); - } catch (error) { - displayNotification(error.message, 'error'); - setState({ - ...state, - loading: false, - }); - } - }; - - /** - * A helper function to update which sections are selected. - * @param {string} id - The id of the section to toggle. - */ - const toggleSelectedSection = (id) => setSelectedSections( - selectedSections.includes(id) - ? selectedSections.filter((section) => section !== id) - : [...selectedSections, id], - ); - - // On initial load, fetch info from the API into state. - useEffect(() => { - (async () => { - const fetches = [ - await apiFetch({ path: `/apple-news/v1/get-published-state/${postId}` }), - await apiFetch({ path: '/apple-news/v1/sections' }), - await apiFetch({ path: '/apple-news/v1/get-settings' }), - await apiFetch({ path: `/apple-news/v1/user-can-publish/${postId}` }), - ]; - - // Wait for everything to load, update state, and handle errors. - try { - const data = await Promise.all(fetches); - setState({ - ...state, - autoAssignCategories: (selectedSections === null || selectedSections.length === 0) - && data[2].automaticAssignment === true, - ...data[0], - sections: data[1], - settings: data[2], - ...data[3], - }); - } catch (error) { - displayNotification(error.message, 'error'); - } - })(); - }, []); // eslint-disable-line react-hooks/exhaustive-deps - - // Display notices whenever they change. - useEffect(() => { - notices.forEach((notice) => displayNotification(notice.message, notice.type)); - }, [displayNotification, notices]); - - return ( - <> - - {__('Apple News Options', 'apple-news')} - - - { - setState({ - ...state, - autoAssignCategories: next, - }); - setSelectedSections([]); - }} - onChangeSelectedSections={toggleSelectedSection} - sections={sections} - selectedSections={selectedSections} - /> - - - - - - {publishState !== 'N/A' ? ( - - ) : null} - modifyPost('delete')} - loading={loading} - postIsDirty={postIsDirty} - postStatus={postStatus} - publishPost={() => modifyPost('publish')} - publishState={publishState} - updatePost={() => modifyPost('update')} - userCanPublish={userCanPublish} - /> - - - ); -}; - -export default Sidebar; diff --git a/assets/js/services/hooks/use-site-options/README.md b/assets/js/services/hooks/use-site-options/README.md deleted file mode 100644 index 7b97d6dd..00000000 --- a/assets/js/services/hooks/use-site-options/README.md +++ /dev/null @@ -1,19 +0,0 @@ -# Custom Hooks: useSiteOptions -Get and set site options via `apiFetch`. Inherits user's capabilities and returns an error notice to the snackbar if the user is not able to fetch or set options. - -Utilize also `notices` to return the snackbar messages. -## Usage -### Getting site settings - -```jsx -const [{ loading, saving, settings }, setOptions] = useSiteOptions(); -``` - -Utilize the settings object as the object containing settings available to the user. - -### Setting site settings. -Expects the full settings object on save. Spread settings, and set the new key/value pair as the second param. - -```jsx -(next) => setHolder({ ...settings, options_key: next }) -``` diff --git a/assets/js/services/hooks/use-taxonomies/README.md b/assets/js/services/hooks/use-taxonomies/README.md deleted file mode 100644 index 02afb605..00000000 --- a/assets/js/services/hooks/use-taxonomies/README.md +++ /dev/null @@ -1,11 +0,0 @@ -# Custom Hooks: useTaxonomies - -Get and cache taxonomies config via `apiFetch`. - -## Usage - -```jsx -const taxonomies = useTaxonomies(); -``` - -Returns the API response from /wp/v2/taxonomies. Caches it for future use. diff --git a/assets/js/services/hooks/use-term-cache/README.md b/assets/js/services/hooks/use-term-cache/README.md deleted file mode 100644 index f0590ecf..00000000 --- a/assets/js/services/hooks/use-term-cache/README.md +++ /dev/null @@ -1,14 +0,0 @@ -# Custom Hooks: useTermCache - -Get and set terms from a cache for from various taxonomies. - -## Usage - -```jsx -const termCache = useTermCache(); -const myTerm = termCache.get('category', 5); -termCache.set({ /* REST response here */ }); -``` - -Returns the API response for the term ID in the given taxonomy. Caches it for -future use. diff --git a/assets/js/util/delete-at-index.js b/assets/js/util/delete-at-index.js deleted file mode 100644 index 06d94bc4..00000000 --- a/assets/js/util/delete-at-index.js +++ /dev/null @@ -1,10 +0,0 @@ -/** - * Given an array of values, returns a copy of the array with the value at the - * given index removed. - * @param {Array} values - The array of values to modify. - * @param {number} index - The index to remove. - * @returns {Array} A copy of the values array with the value at the specified index removed. - */ -const deleteAtIndex = (values, index) => values.filter((value, idx) => index !== idx); - -export default deleteAtIndex; diff --git a/assets/js/util/delete-at-index.test.js b/assets/js/util/delete-at-index.test.js deleted file mode 100644 index 1529ffdf..00000000 --- a/assets/js/util/delete-at-index.test.js +++ /dev/null @@ -1,8 +0,0 @@ -import deleteAtIndex from './delete-at-index'; - -test('deleteAtIndex should properly delete items at a given index.', () => { - const values = ['a', 'b', 'c']; - expect(deleteAtIndex(values, 0)).toEqual(['b', 'c']); - expect(deleteAtIndex(values, 1)).toEqual(['a', 'c']); - expect(deleteAtIndex(values, 2)).toEqual(['a', 'b']); -}); diff --git a/assets/js/util/safe-json-parse-array.js b/assets/js/util/safe-json-parse-array.js deleted file mode 100644 index 515ff502..00000000 --- a/assets/js/util/safe-json-parse-array.js +++ /dev/null @@ -1,21 +0,0 @@ -import safeJsonParse from './safe-json-parse'; - -/** - * Given a value, run JSON.parse on it, but if parsing fails, or if - * what results from the parse is not an array, return an empty - * array rather than a syntax error or a value of another type. - * @param {*} value - The value to attempt to parse. - * @returns {array} - The parsed value, or an empty array on failure. - */ -const safeJsonParseArray = (value) => { - const parsedValue = safeJsonParse(value); - - // Make absolutely sure that the parsed value is an array. - if (!Array.isArray(parsedValue)) { - return []; - } - - return parsedValue; -}; - -export default safeJsonParseArray; diff --git a/assets/js/util/safe-json-parse-array.test.js b/assets/js/util/safe-json-parse-array.test.js deleted file mode 100644 index 1f91cea8..00000000 --- a/assets/js/util/safe-json-parse-array.test.js +++ /dev/null @@ -1,16 +0,0 @@ -import safeJsonParseArray from './safe-json-parse-array'; - -test('safeJsonParseArray should properly return a parsed array.', () => { - expect(safeJsonParseArray('[1, 5, "false"]')).toEqual([1, 5, 'false']); - expect(safeJsonParseArray('["a", "b", "c"]')).toEqual(['a', 'b', 'c']); -}); - -test('safeJsonParseArray should return an empty array for any non-array types.', () => { - expect(safeJsonParseArray('true')).toEqual([]); - expect(safeJsonParseArray('"foo"')).toEqual([]); - expect(safeJsonParseArray('null')).toEqual([]); - expect(safeJsonParseArray('{}')).toEqual([]); - expect(safeJsonParseArray('{"a": "b"}')).toEqual([]); - expect(safeJsonParseArray('')).toEqual([]); - expect(safeJsonParseArray(undefined)).toEqual([]); -}); diff --git a/assets/js/util/safe-json-parse-object.js b/assets/js/util/safe-json-parse-object.js deleted file mode 100644 index 952c7883..00000000 --- a/assets/js/util/safe-json-parse-object.js +++ /dev/null @@ -1,25 +0,0 @@ -import safeJsonParse from './safe-json-parse'; - -/** - * Given a value, run JSON.parse on it, but if parsing fails, or if - * what results from the parse is not a standard object, return an empty - * object rather than a syntax error or a value of another type. - * @param {*} value - The value to attempt to parse. - * @returns {object} - The parsed value, or an empty object on failure. - */ -const safeJsonParseObject = (value) => { - const parsedValue = safeJsonParse(value); - - // Make absolutely sure that the object is a standard object. - if (parsedValue === null - || typeof parsedValue !== 'object' - || Array.isArray(parsedValue) - || JSON.stringify(parsedValue).indexOf('{') !== 0 - ) { - return {}; - } - - return parsedValue; -}; - -export default safeJsonParseObject; diff --git a/assets/js/util/safe-json-parse-object.test.js b/assets/js/util/safe-json-parse-object.test.js deleted file mode 100644 index fe607b1f..00000000 --- a/assets/js/util/safe-json-parse-object.test.js +++ /dev/null @@ -1,16 +0,0 @@ -import safeJsonParseObject from './safe-json-parse-object'; - -test('safeJsonParseObject should properly return a parsed object.', () => { - expect(safeJsonParseObject('{}')).toEqual({}); - expect(safeJsonParseObject('{"a": "b"}')).toEqual({ a: 'b' }); -}); - -test('safeJsonParseObject should return an empty object for any non-object types.', () => { - expect(safeJsonParseObject('true')).toEqual({}); - expect(safeJsonParseObject('"foo"')).toEqual({}); - expect(safeJsonParseObject('[1, 5, "false"]')).toEqual({}); - expect(safeJsonParseObject('null')).toEqual({}); - expect(safeJsonParseObject('["a", "b", "c"]')).toEqual({}); - expect(safeJsonParseObject('')).toEqual({}); - expect(safeJsonParseObject(undefined)).toEqual({}); -}); diff --git a/assets/js/util/safe-json-parse.js b/assets/js/util/safe-json-parse.js deleted file mode 100644 index 786a8799..00000000 --- a/assets/js/util/safe-json-parse.js +++ /dev/null @@ -1,15 +0,0 @@ -/** - * Given a value, run JSON.parse on it, but if parsing fails, return null - * instead of throwing a SyntaxError. - * @param {*} value - The value to attempt to parse. - * @returns {*} - The parsed value, or null on failure. - */ -const safeJsonParse = (value) => { - try { - return JSON.parse(value); - } catch (e) { - return null; - } -}; - -export default safeJsonParse; diff --git a/assets/js/util/safe-json-parse.test.js b/assets/js/util/safe-json-parse.test.js deleted file mode 100644 index 82884632..00000000 --- a/assets/js/util/safe-json-parse.test.js +++ /dev/null @@ -1,16 +0,0 @@ -import safeJsonParse from './safe-json-parse'; - -test('safeJsonParse should properly decode valid JSON.', () => { - expect(safeJsonParse('{}')).toEqual({}); - expect(safeJsonParse('true')).toEqual(true); - expect(safeJsonParse('"foo"')).toEqual('foo'); - expect(safeJsonParse('[1, 5, "false"]')).toEqual([1, 5, 'false']); - expect(safeJsonParse('null')).toEqual(null); - expect(safeJsonParse('["a", "b", "c"]')).toEqual(['a', 'b', 'c']); - expect(safeJsonParse('{"a": "b"}')).toEqual({ a: 'b' }); -}); - -test('Should not choke on invalid JSON.', () => { - expect(safeJsonParse('')).toEqual(null); - expect(safeJsonParse(undefined)).toEqual(null); -}); diff --git a/assets/js/util/update-value-at-index.js b/assets/js/util/update-value-at-index.js deleted file mode 100644 index 7ac7dfd2..00000000 --- a/assets/js/util/update-value-at-index.js +++ /dev/null @@ -1,16 +0,0 @@ -/** - * Given an array of objects, a key, and a value, returns a copy of the array - * with the value for the key set at the given index. - * @param {Array} values - An array of objects. - * @param {string} key - The object key to update. - * @param {*} value - The value to set for the key. - * @param {number} index - The index to set the value on. - * @returns {Array} A copy of the array with the value set for the key at the given index. - */ -const updateValueAtIndex = (values, key, value, index) => { - const valuesCopy = values.map((item) => ({ ...item })); - valuesCopy[index][key] = value; - return valuesCopy; -}; - -export default updateValueAtIndex; diff --git a/assets/js/util/update-value-at-index.test.js b/assets/js/util/update-value-at-index.test.js deleted file mode 100644 index 388d6277..00000000 --- a/assets/js/util/update-value-at-index.test.js +++ /dev/null @@ -1,39 +0,0 @@ -import updateValueAtIndex from './update-value-at-index'; - -test('updateValueAtIndex should properly update values at indices.', () => { - const values = [ - { a: 'b', c: 'd' }, - { e: 'f', g: 'h' }, - { i: 'j', k: 'l' }, - ]; - expect(updateValueAtIndex(values, 'a', 'x', 0)).toEqual([ - { a: 'x', c: 'd' }, - { e: 'f', g: 'h' }, - { i: 'j', k: 'l' }, - ]); - expect(updateValueAtIndex(values, 'c', 'x', 0)).toEqual([ - { a: 'b', c: 'x' }, - { e: 'f', g: 'h' }, - { i: 'j', k: 'l' }, - ]); - expect(updateValueAtIndex(values, 'e', 'x', 1)).toEqual([ - { a: 'b', c: 'd' }, - { e: 'x', g: 'h' }, - { i: 'j', k: 'l' }, - ]); - expect(updateValueAtIndex(values, 'g', 'x', 1)).toEqual([ - { a: 'b', c: 'd' }, - { e: 'f', g: 'x' }, - { i: 'j', k: 'l' }, - ]); - expect(updateValueAtIndex(values, 'i', 'x', 2)).toEqual([ - { a: 'b', c: 'd' }, - { e: 'f', g: 'h' }, - { i: 'x', k: 'l' }, - ]); - expect(updateValueAtIndex(values, 'k', 'x', 2)).toEqual([ - { a: 'b', c: 'd' }, - { e: 'f', g: 'h' }, - { i: 'j', k: 'x' }, - ]); -}); diff --git a/babel.config.json b/babel.config.json deleted file mode 100644 index 7e07e6cc..00000000 --- a/babel.config.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "plugins": [ - "babel-plugin-styled-components" - ], - "presets": [ - "@babel/preset-env", - "@babel/preset-react" - ] -} diff --git a/build/adminSettings.asset.php b/build/adminSettings.asset.php new file mode 100644 index 00000000..37891732 --- /dev/null +++ b/build/adminSettings.asset.php @@ -0,0 +1 @@ + array('react', 'react-dom', 'wp-api-fetch', 'wp-components', 'wp-data', 'wp-i18n'), 'version' => '224b3bcbfabe83e2400b1c89e956ac1f'); \ No newline at end of file diff --git a/build/adminSettings.js b/build/adminSettings.js new file mode 100644 index 00000000..e035b4b0 --- /dev/null +++ b/build/adminSettings.js @@ -0,0 +1,2 @@ +!function(){var e={373:function(e){var t;self,t=()=>(()=>{var e={184:(e,t)=>{var r;!function(){"use strict";var n={}.hasOwnProperty;function o(){for(var e=[],t=0;t{"use strict";r.d(t,{Z:()=>s});var n=r(537),o=r.n(n),i=r(645),a=r.n(i)()(o());a.push([e.id,'.edit-post-sidebar .autocomplete__component,.editor-styles-wrapper .autocomplete__component{margin-bottom:20px}.edit-post-sidebar .autocomplete-base-control,.editor-styles-wrapper .autocomplete-base-control{position:relative}.edit-post-sidebar .autocomplete-text-control__input,.editor-styles-wrapper .autocomplete-text-control__input{margin:0}.edit-post-sidebar .autocomplete__selection-list,.editor-styles-wrapper .autocomplete__selection-list{list-style-type:none;margin:0 0 6px;padding:0}.edit-post-sidebar .autocomplete__selection-list--item,.editor-styles-wrapper .autocomplete__selection-list--item{display:inline-block;list-style:none}.edit-post-sidebar .autocomplete__selection-list--item--button,.editor-styles-wrapper .autocomplete__selection-list--item--button{margin-bottom:4px;margin-right:3px}.edit-post-sidebar .autocomplete__selection-list--item--button::after,.editor-styles-wrapper .autocomplete__selection-list--item--button::after{content:"×";font-size:16px;line-height:20px;margin-left:5px}.edit-post-sidebar .autocomplete__dropdown,.editor-styles-wrapper .autocomplete__dropdown{background-color:#fff;border-color:rgba(0,0,0,0) #e2e4e7 #e2e4e7;border-radius:0 0 4px 4px;border-style:solid;border-width:0 1px 1px;left:0;max-height:0;overflow-y:hidden;position:absolute;top:calc(100% + 1px);visibility:hidden;width:100%;z-index:10}.edit-post-sidebar .autocomplete__dropdown--is-open,.editor-styles-wrapper .autocomplete__dropdown--is-open{box-shadow:0 3px 30px rgba(25,30,35,.1);max-height:225px;overflow-y:scroll;visibility:visible}.edit-post-sidebar .autocomplete__dropdown--notice,.editor-styles-wrapper .autocomplete__dropdown--notice{padding:15px}.edit-post-sidebar .autocomplete__dropdown--results,.editor-styles-wrapper .autocomplete__dropdown--results{list-style:none;margin:0;padding:0}.edit-post-sidebar .autocomplete__list--item,.editor-styles-wrapper .autocomplete__list--item{list-style:none}.edit-post-sidebar .autocomplete__list--item>button,.editor-styles-wrapper .autocomplete__list--item>button{background:rgba(0,0,0,0);border-color:#e2e4e7;border-style:solid;border-width:0 0 1px;height:100%;line-height:1.25;text-align:left;white-space:inherit;width:100%}.edit-post-sidebar .autocomplete__list--item:last-child>button,.editor-styles-wrapper .autocomplete__list--item:last-child>button{border-bottom:0}',"",{version:3,sources:["webpack://./src/components/selector/styles.scss"],names:[],mappings:"AAAA,4FAgBI,kBACE,CAAA,gGAMF,iBACE,CAAA,8GAMF,QACE,CAAA,sGAMF,oBACE,CAAA,cACA,CAAA,SACA,CAAA,kHAEA,oBACE,CAAA,eACA,CAAA,kIAEA,iBACE,CAAA,gBACA,CAAA,gJAEA,WACE,CAAA,cACA,CAAA,gBACA,CAAA,eACA,CAAA,0FASR,qBACE,CAAA,0CACA,CAAA,yBACA,CAAA,kBACA,CAAA,sBACA,CAAA,MACA,CAAA,YACA,CAAA,iBACA,CAAA,iBACA,CAAA,oBACA,CAAA,iBACA,CAAA,UACA,CAAA,UACA,CAAA,4GAGA,uCACE,CAAA,gBACA,CAAA,iBACA,CAAA,kBACA,CAAA,0GAIF,YACE,CAAA,4GAIF,eACE,CAAA,QACA,CAAA,SACA,CAAA,8FAOJ,eACE,CAAA,4GAEA,wBACE,CAAA,oBACA,CAAA,kBACA,CAAA,oBACA,CAAA,WACA,CAAA,gBACA,CAAA,eACA,CAAA,mBACA,CAAA,UACA,CAAA,kIAGF,eACE",sourcesContent:["//--------------------------------------------------------------\n// AutoComplete Styles\n//--------------------------------------------------------------\n\n/* stylelint-disable max-nesting-depth */\n\n//-----------------------------------------\n// Accommodate editor well, or the sidebar.\n//-----------------------------------------\n.edit-post-sidebar,\n.editor-styles-wrapper {\n .autocomplete {\n\n //-----------------------------------------\n // Parent form wrapper.\n //-----------------------------------------\n &__component {\n margin-bottom: 20px;\n }\n\n //-----------------------------------------\n // Wrapper\n //-----------------------------------------\n &-base-control {\n position: relative;\n }\n\n //-----------------------------------------\n // Input\n //-----------------------------------------\n &-text-control__input {\n margin: 0;\n }\n\n //-----------------------------------------\n // Selected buttons.\n //-----------------------------------------\n &__selection-list {\n list-style-type: none;\n margin: 0 0 6px;\n padding: 0;\n\n &--item {\n display: inline-block;\n list-style: none;\n\n &--button {\n margin-bottom: 4px;\n margin-right: 3px;\n\n &::after {\n content: '×';\n font-size: 16px;\n line-height: 20px;\n margin-left: 5px;\n }\n }\n }\n }\n\n //-----------------------------------------\n // Results\n //-----------------------------------------\n &__dropdown {\n background-color: #fff;\n border-color: transparent #e2e4e7 #e2e4e7;\n border-radius: 0 0 4px 4px;\n border-style: solid;\n border-width: 0 1px 1px;\n left: 0;\n max-height: 0;\n overflow-y: hidden;\n position: absolute;\n top: calc(100% + 1px); // Offset focus border.\n visibility: hidden;\n width: 100%;\n z-index: 10;\n\n // Container is open.\n &--is-open {\n box-shadow: 0 3px 30px rgba(25, 30, 35, 0.1);\n max-height: 225px;\n overflow-y: scroll;\n visibility: visible;\n }\n\n // Notice handler.\n &--notice {\n padding: 15px;\n }\n\n // Results container.\n &--results {\n list-style: none;\n margin: 0;\n padding: 0;\n }\n }\n\n //-----------------------------------------\n // List/Results\n //-----------------------------------------\n &__list--item {\n list-style: none;\n\n > button {\n background: transparent;\n border-color: #e2e4e7;\n border-style: solid;\n border-width: 0 0 1px;\n height: 100%;\n line-height: 1.25;\n text-align: left;\n white-space: inherit;\n width: 100%;\n }\n\n &:last-child > button {\n border-bottom: 0;\n }\n }\n }\n}\n"],sourceRoot:""}]);const s=a},645:e=>{"use strict";e.exports=function(e){var t=[];return t.toString=function(){return this.map((function(t){var r="",n=void 0!==t[5];return t[4]&&(r+="@supports (".concat(t[4],") {")),t[2]&&(r+="@media ".concat(t[2]," {")),n&&(r+="@layer".concat(t[5].length>0?" ".concat(t[5]):""," {")),r+=e(t),n&&(r+="}"),t[2]&&(r+="}"),t[4]&&(r+="}"),r})).join("")},t.i=function(e,r,n,o,i){"string"==typeof e&&(e=[[null,e,void 0]]);var a={};if(n)for(var s=0;s0?" ".concat(u[5]):""," {").concat(u[1],"}")),u[5]=i),r&&(u[2]?(u[1]="@media ".concat(u[2]," {").concat(u[1],"}"),u[2]=r):u[2]=r),o&&(u[4]?(u[1]="@supports (".concat(u[4],") {").concat(u[1],"}"),u[4]=o):u[4]="".concat(o)),t.push(u))}},t}},537:e=>{"use strict";e.exports=function(e){var t=e[1],r=e[3];if(!r)return t;if("function"==typeof btoa){var n=btoa(unescape(encodeURIComponent(JSON.stringify(r)))),o="sourceMappingURL=data:application/json;charset=utf-8;base64,".concat(n),i="/*# ".concat(o," */"),a=r.sources.map((function(e){return"/*# sourceURL=".concat(r.sourceRoot||"").concat(e," */")}));return[t].concat(a).concat([i]).join("\n")}return[t].join("\n")}},856:function(e){e.exports=function(){"use strict";function e(t){return(e="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(t)}function t(e,r){return t=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e},t(e,r)}function r(e,n,o){return r=function(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){}))),!0}catch(e){return!1}}()?Reflect.construct:function(e,r,n){var o=[null];o.push.apply(o,r);var i=new(Function.bind.apply(e,o));return n&&t(i,n.prototype),i},r.apply(null,arguments)}function n(e){return function(e){if(Array.isArray(e))return o(e)}(e)||function(e){if("undefined"!=typeof Symbol&&null!=e[Symbol.iterator]||null!=e["@@iterator"])return Array.from(e)}(e)||function(e,t){if(e){if("string"==typeof e)return o(e,t);var r=Object.prototype.toString.call(e).slice(8,-1);return"Object"===r&&e.constructor&&(r=e.constructor.name),"Map"===r||"Set"===r?Array.from(e):"Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r)?o(e,t):void 0}}(e)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function o(e,t){(null==t||t>e.length)&&(t=e.length);for(var r=0,n=new Array(t);r1?r-1:0),o=1;o/gm),H=p(/^data-[\-\w.\u00B7-\uFFFF]/),G=p(/^aria-[\-\w]+$/),W=p(/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|cid|xmpp):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i),V=p(/^(?:\w+script|data):/i),Y=p(/[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g),K=p(/^html$/i);return function t(){var r=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"undefined"==typeof window?null:window,o=function(e){return t(e)};if(o.version="2.3.9",o.removed=[],!r||!r.document||9!==r.document.nodeType)return o.isSupported=!1,o;var i=r.document,a=r.document,s=r.DocumentFragment,l=r.HTMLTemplateElement,c=r.Node,p=r.Element,d=r.NodeFilter,f=r.NamedNodeMap,m=void 0===f?r.NamedNodeMap||r.MozNamedAttrMap:f,h=r.HTMLFormElement,y=r.DOMParser,x=r.trustedTypes,X=p.prototype,Z=O(X,"cloneNode"),J=O(X,"nextSibling"),Q=O(X,"childNodes"),ee=O(X,"parentNode");if("function"==typeof l){var te=a.createElement("template");te.content&&te.content.ownerDocument&&(a=te.content.ownerDocument)}var re=function(t,r){if("object"!==e(t)||"function"!=typeof t.createPolicy)return null;var n=null,o="data-tt-policy-suffix";r.currentScript&&r.currentScript.hasAttribute(o)&&(n=r.currentScript.getAttribute(o));var i="dompurify"+(n?"#"+n:"");try{return t.createPolicy(i,{createHTML:function(e){return e}})}catch(e){return console.warn("TrustedTypes policy "+i+" could not be created."),null}}(x,i),ne=re?re.createHTML(""):"",oe=a,ie=oe.implementation,ae=oe.createNodeIterator,se=oe.createDocumentFragment,le=oe.getElementsByTagName,ce=i.importNode,ue={};try{ue=T(a).documentMode?a.documentMode:{}}catch(e){}var pe={};o.isSupported="function"==typeof ee&&ie&&void 0!==ie.createHTMLDocument&&9!==ue;var de,fe,me=q,he=$,ye=H,ge=G,ve=V,be=Y,we=W,_e=null,Ae=R({},[].concat(n(I),n(N),n(L),n(j),n(M))),Se=null,Ce=R({},[].concat(n(U),n(F),n(z),n(B))),Ee=Object.seal(Object.create(null,{tagNameCheck:{writable:!0,configurable:!1,enumerable:!0,value:null},attributeNameCheck:{writable:!0,configurable:!1,enumerable:!0,value:null},allowCustomizedBuiltInElements:{writable:!0,configurable:!1,enumerable:!0,value:!1}})),ke=null,xe=null,Re=!0,Te=!0,Oe=!1,Ie=!1,Ne=!1,Le=!1,Pe=!1,je=!1,De=!1,Me=!1,Ue=!0,Fe=!0,ze=!1,Be={},qe=null,$e=R({},["annotation-xml","audio","colgroup","desc","foreignobject","head","iframe","math","mi","mn","mo","ms","mtext","noembed","noframes","noscript","plaintext","script","style","svg","template","thead","title","video","xmp"]),He=null,Ge=R({},["audio","video","img","source","image","track"]),We=null,Ve=R({},["alt","class","for","id","label","name","pattern","placeholder","role","summary","title","value","style","xmlns"]),Ye="http://www.w3.org/1998/Math/MathML",Ke="http://www.w3.org/2000/svg",Xe="http://www.w3.org/1999/xhtml",Ze=Xe,Je=!1,Qe=["application/xhtml+xml","text/html"],et=null,tt=a.createElement("form"),rt=function(e){return e instanceof RegExp||e instanceof Function},nt=function(t){et&&et===t||(t&&"object"===e(t)||(t={}),t=T(t),de=de=-1===Qe.indexOf(t.PARSER_MEDIA_TYPE)?"text/html":t.PARSER_MEDIA_TYPE,fe="application/xhtml+xml"===de?function(e){return e}:w,_e="ALLOWED_TAGS"in t?R({},t.ALLOWED_TAGS,fe):Ae,Se="ALLOWED_ATTR"in t?R({},t.ALLOWED_ATTR,fe):Ce,We="ADD_URI_SAFE_ATTR"in t?R(T(Ve),t.ADD_URI_SAFE_ATTR,fe):Ve,He="ADD_DATA_URI_TAGS"in t?R(T(Ge),t.ADD_DATA_URI_TAGS,fe):Ge,qe="FORBID_CONTENTS"in t?R({},t.FORBID_CONTENTS,fe):$e,ke="FORBID_TAGS"in t?R({},t.FORBID_TAGS,fe):{},xe="FORBID_ATTR"in t?R({},t.FORBID_ATTR,fe):{},Be="USE_PROFILES"in t&&t.USE_PROFILES,Re=!1!==t.ALLOW_ARIA_ATTR,Te=!1!==t.ALLOW_DATA_ATTR,Oe=t.ALLOW_UNKNOWN_PROTOCOLS||!1,Ie=t.SAFE_FOR_TEMPLATES||!1,Ne=t.WHOLE_DOCUMENT||!1,je=t.RETURN_DOM||!1,De=t.RETURN_DOM_FRAGMENT||!1,Me=t.RETURN_TRUSTED_TYPE||!1,Pe=t.FORCE_BODY||!1,Ue=!1!==t.SANITIZE_DOM,Fe=!1!==t.KEEP_CONTENT,ze=t.IN_PLACE||!1,we=t.ALLOWED_URI_REGEXP||we,Ze=t.NAMESPACE||Xe,t.CUSTOM_ELEMENT_HANDLING&&rt(t.CUSTOM_ELEMENT_HANDLING.tagNameCheck)&&(Ee.tagNameCheck=t.CUSTOM_ELEMENT_HANDLING.tagNameCheck),t.CUSTOM_ELEMENT_HANDLING&&rt(t.CUSTOM_ELEMENT_HANDLING.attributeNameCheck)&&(Ee.attributeNameCheck=t.CUSTOM_ELEMENT_HANDLING.attributeNameCheck),t.CUSTOM_ELEMENT_HANDLING&&"boolean"==typeof t.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements&&(Ee.allowCustomizedBuiltInElements=t.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements),Ie&&(Te=!1),De&&(je=!0),Be&&(_e=R({},n(M)),Se=[],!0===Be.html&&(R(_e,I),R(Se,U)),!0===Be.svg&&(R(_e,N),R(Se,F),R(Se,B)),!0===Be.svgFilters&&(R(_e,L),R(Se,F),R(Se,B)),!0===Be.mathMl&&(R(_e,j),R(Se,z),R(Se,B))),t.ADD_TAGS&&(_e===Ae&&(_e=T(_e)),R(_e,t.ADD_TAGS,fe)),t.ADD_ATTR&&(Se===Ce&&(Se=T(Se)),R(Se,t.ADD_ATTR,fe)),t.ADD_URI_SAFE_ATTR&&R(We,t.ADD_URI_SAFE_ATTR,fe),t.FORBID_CONTENTS&&(qe===$e&&(qe=T(qe)),R(qe,t.FORBID_CONTENTS,fe)),Fe&&(_e["#text"]=!0),Ne&&R(_e,["html","head","body"]),_e.table&&(R(_e,["tbody"]),delete ke.tbody),u&&u(t),et=t)},ot=R({},["mi","mo","mn","ms","mtext"]),it=R({},["foreignobject","desc","title","annotation-xml"]),at=R({},["title","style","font","a","script"]),st=R({},N);R(st,L),R(st,P);var lt=R({},j);R(lt,D);var ct=function(e){b(o.removed,{element:e});try{e.parentNode.removeChild(e)}catch(t){try{e.outerHTML=ne}catch(t){e.remove()}}},ut=function(e,t){try{b(o.removed,{attribute:t.getAttributeNode(e),from:t})}catch(e){b(o.removed,{attribute:null,from:t})}if(t.removeAttribute(e),"is"===e&&!Se[e])if(je||De)try{ct(t)}catch(e){}else try{t.setAttribute(e,"")}catch(e){}},pt=function(e){var t,r;if(Pe)e=""+e;else{var n=_(e,/^[\r\n\t ]+/);r=n&&n[0]}"application/xhtml+xml"===de&&(e=''+e+"");var o=re?re.createHTML(e):e;if(Ze===Xe)try{t=(new y).parseFromString(o,de)}catch(e){}if(!t||!t.documentElement){t=ie.createDocument(Ze,"template",null);try{t.documentElement.innerHTML=Je?"":o}catch(e){}}var i=t.body||t.documentElement;return e&&r&&i.insertBefore(a.createTextNode(r),i.childNodes[0]||null),Ze===Xe?le.call(t,Ne?"html":"body")[0]:Ne?t.documentElement:i},dt=function(e){return ae.call(e.ownerDocument||e,e,d.SHOW_ELEMENT|d.SHOW_COMMENT|d.SHOW_TEXT,null,!1)},ft=function(t){return"object"===e(c)?t instanceof c:t&&"object"===e(t)&&"number"==typeof t.nodeType&&"string"==typeof t.nodeName},mt=function(e,t,r){pe[e]&&g(pe[e],(function(e){e.call(o,t,r,et)}))},ht=function(e){var t;if(mt("beforeSanitizeElements",e,null),function(e){return e instanceof h&&("string"!=typeof e.nodeName||"string"!=typeof e.textContent||"function"!=typeof e.removeChild||!(e.attributes instanceof m)||"function"!=typeof e.removeAttribute||"function"!=typeof e.setAttribute||"string"!=typeof e.namespaceURI||"function"!=typeof e.insertBefore)}(e))return ct(e),!0;if(E(/[\u0080-\uFFFF]/,e.nodeName))return ct(e),!0;var r=fe(e.nodeName);if(mt("uponSanitizeElement",e,{tagName:r,allowedTags:_e}),e.hasChildNodes()&&!ft(e.firstElementChild)&&(!ft(e.content)||!ft(e.content.firstElementChild))&&E(/<[/\w]/g,e.innerHTML)&&E(/<[/\w]/g,e.textContent))return ct(e),!0;if("select"===r&&E(/