From 72c0bac236b179031e5e90beafa9f896a9e21c01 Mon Sep 17 00:00:00 2001 From: Alley CI Operations Date: Fri, 3 Mar 2023 01:10:37 +0000 Subject: [PATCH] Committing Build Assets --- .deployignore | 33 - .editorconfig | 21 - .eslintignore | 15 - .eslintrc.json | 34 - .github/workflows/build.yml | 25 - .github/workflows/node-tests.yml | 28 - .github/workflows/phpcs.yml | 25 - .github/workflows/phpunit.yml | 51 - .github/workflows/release.yml | 24 - .gitignore | 27 +- .phpcs.xml | 73 - README.md | 72 - 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 - 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.json | 27 - package-lock.json | 21519 ---------------- package.json | 113 - 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 | 613 - 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 | 601 - .../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 | 321 - .../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 | 148 - tests/apple-exporter/test-class-theme.php | 128 - .../apple-push-api/test-class-credentials.php | 27 - .../test-class-mime-builder.php | 53 - tests/bootstrap.php | 87 - tests/class-apple-news-testcase.php | 592 - 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 | 142 - tests/test-class-apple-news.php | 293 - webpack.config.js | 49 - 105 files changed, 33 insertions(+), 32411 deletions(-) delete mode 100644 .deployignore delete mode 100644 .editorconfig delete mode 100644 .eslintignore delete mode 100644 .eslintrc.json delete mode 100644 .github/workflows/build.yml delete mode 100644 .github/workflows/node-tests.yml delete mode 100644 .github/workflows/phpcs.yml delete mode 100644 .github/workflows/phpunit.yml delete mode 100644 .github/workflows/release.yml 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 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 delete mode 100644 composer.json delete mode 100644 package-lock.json delete mode 100644 package.json 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 9b4f73f1b..000000000 --- a/.deployignore +++ /dev/null @@ -1,33 +0,0 @@ -.DS_Store -*.zip -tags -composer.lock -vendor -node_modules -npm-debug.log - -# IDEs -.idea -.vscode - -# Directories and files that we do not want to be included with the built -# version and deployed to WordPress.org. -.babelrc -.editorconfig -.eslintignore -.eslintrc.json -.github -.phpcs.xml -.phpcs-cache.json -.phpunit.result.cache -.travis.yml -assets/js/pluginsidebar -assets/js/util -bin -composer.json -package.json -package-lock.json -phpunit.xml.dist -README.md -tests -webpack.config.js diff --git a/.editorconfig b/.editorconfig deleted file mode 100644 index 4963d4195..000000000 --- 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 872f242f9..000000000 --- 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 2c6918728..000000000 --- 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/.github/workflows/build.yml b/.github/workflows/build.yml deleted file mode 100644 index 804636ebb..000000000 --- a/.github/workflows/build.yml +++ /dev/null @@ -1,25 +0,0 @@ -on: - push: - tags: - - 'v*.*.*' # Push events to matching v* (eg. v2.0.8) - - '!*-built' # Exclude built branches (eg. v2.0.8-built) - -name: Trigger Build - -jobs: - build: - name: Trigger Build - runs-on: ubuntu-latest - - steps: - - name: 'curl to build server' - shell: bash - env: - URL: ${{ secrets.DB_BUILD_URL }} - TOKEN: ${{ secrets.DB_BUILD_SECRET }} - ENV_ID: ${{ secrets.DB_BUILD_ENV }} - run: | - curl -s "$URL" \ - -X POST \ - -H "X-Api-Token: $TOKEN" \ - -d "{\"environment_id\":${ENV_ID},\"deploy_from_scratch\":true,\"trigger_notifications\":true,\"comment\":\"Build Trigger from GitHub Actions\"}" diff --git a/.github/workflows/node-tests.yml b/.github/workflows/node-tests.yml deleted file mode 100644 index 55dd44e57..000000000 --- a/.github/workflows/node-tests.yml +++ /dev/null @@ -1,28 +0,0 @@ -name: Node Tests - -on: - pull_request: - -jobs: - npm-ci: - name: (npm) Install, build, and test - runs-on: ubuntu-latest - steps: - - name: Cancel Previous Runs - uses: styfle/cancel-workflow-action@0.11.0 - with: - all_but_latest: true - - name: Checkout code - uses: actions/checkout@v3 - - name: Setup Node - uses: actions/setup-node@v3 - with: - node-version: 16 - - name: Install node dependencies (npm ci) - run: npm ci - - name: Run npm lint - run: npm run lint - - name: Run npm test - run: npm run test - - name: Run npm build - run: npm run build diff --git a/.github/workflows/phpcs.yml b/.github/workflows/phpcs.yml deleted file mode 100644 index 38a3269e3..000000000 --- a/.github/workflows/phpcs.yml +++ /dev/null @@ -1,25 +0,0 @@ -name: PHP Coding Standards -on: - pull_request: - workflow_dispatch: -jobs: - phpcs: - runs-on: ubuntu-latest - steps: - - name: Cancel Previous Runs - uses: styfle/cancel-workflow-action@0.11.0 - with: - all_but_latest: true - - name: Checkout code - uses: actions/checkout@v3 - - name: Setup PHP - uses: shivammathur/setup-php@v2 - with: - php-version: '8.0' - coverage: none - - name: Validate Composer package - run: composer validate --strict - - name: Install dependencies - uses: ramsey/composer-install@v2 - - name: Run PHPCS - run: composer phpcs diff --git a/.github/workflows/phpunit.yml b/.github/workflows/phpunit.yml deleted file mode 100644 index 04663c501..000000000 --- a/.github/workflows/phpunit.yml +++ /dev/null @@ -1,51 +0,0 @@ -name: Unit Tests -on: - pull_request: - workflow_dispatch: -jobs: - tests: - name: "PHP: ${{ matrix.php }} (MU: ${{ matrix.multisite }})" - runs-on: ubuntu-latest - strategy: - fail-fast: true - matrix: - multisite: [0, 1] - php: ['8.0', '7.4', '7.3', '7.2', '7.1'] - env: - WP_CORE_DIR: /tmp/wordpress/ - WP_MULTISITE: ${{ matrix.multisite }} - services: - mysql: - image: mysql:5.7 - env: - MYSQL_ALLOW_EMPTY_PASSWORD: yes - ports: - - 3306:3306 - options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3 - steps: - - name: Cancel Previous Runs - uses: styfle/cancel-workflow-action@0.11.0 - with: - all_but_latest: true - - name: Checkout code - uses: actions/checkout@v3 - - name: Setup PHP - uses: shivammathur/setup-php@v2 - with: - php-version: ${{ matrix.php }} - extensions: dom, curl, libxml, mbstring, zip, pcntl, pdo, sqlite, pdo_sqlite, gd - coverage: none - - name: Install dependencies - uses: ramsey/composer-install@v2 - - name: Set up WordPress - run: | - bash <(curl -s "https://raw.githubusercontent.com/wp-cli/sample-plugin/master/bin/install-wp-tests.sh") wordpress_unit_tests root '' 127.0.0.1 - rm -rf "${WP_CORE_DIR}wp-content/plugins" - mkdir -p "${WP_CORE_DIR}wp-content/plugins/publish-to-apple-news" - rsync -a --exclude=.git . "${WP_CORE_DIR}wp-content/plugins/publish-to-apple-news" - cd ${WP_CORE_DIR}wp-content/plugins/publish-to-apple-news && composer install - - name: Run tests - shell: bash - run: | - cd ${WP_CORE_DIR}/wp-content/plugins/publish-to-apple-news - composer run phpunit diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml deleted file mode 100644 index 24fb4daf8..000000000 --- a/.github/workflows/release.yml +++ /dev/null @@ -1,24 +0,0 @@ -on: - push: - tags: - - 'v*-built' # Create releases for built branches (eg. v2.0.8-built) - -name: Create -built release - -jobs: - release: - name: Create release - runs-on: ubuntu-latest - - steps: - - name: Create Release - id: create_release - uses: actions/create-release@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Provided by Actions - with: - tag_name: ${{ github.ref }} - release_name: ${{ github.ref }} - body: A version that contains pre-built JavaScript assets for Gutenberg. This version matches what is deployed to WordPress.org, minus some development and wiki image files, and is suitable for inclusion via submodule. - draft: false - prerelease: true diff --git a/.gitignore b/.gitignore index 6fbcb6cde..9b4f73f1b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,14 +1,33 @@ .DS_Store -.phpcs-cache.json -.phpunit.result.cache *.zip tags composer.lock vendor node_modules npm-debug.log -build -## IDE +# IDEs .idea .vscode + +# Directories and files that we do not want to be included with the built +# version and deployed to WordPress.org. +.babelrc +.editorconfig +.eslintignore +.eslintrc.json +.github +.phpcs.xml +.phpcs-cache.json +.phpunit.result.cache +.travis.yml +assets/js/pluginsidebar +assets/js/util +bin +composer.json +package.json +package-lock.json +phpunit.xml.dist +README.md +tests +webpack.config.js diff --git a/.phpcs.xml b/.phpcs.xml deleted file mode 100644 index e8782cbfc..000000000 --- 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 5db89d1e4..000000000 --- a/README.md +++ /dev/null @@ -1,72 +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) - -### 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 29c325b93..000000000 --- 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 6d5b1289f..000000000 --- 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 c2e389960..000000000 --- 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 4555de77c..000000000 --- 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 520037622..000000000 --- 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 4ceafeb4e..000000000 --- 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 6e24fd036..000000000 --- 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 979a25ed3..000000000 --- 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 084fa2411..000000000 --- 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 a930649e1..000000000 --- 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 7b97d6dd0..000000000 --- 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 02afb6056..000000000 --- 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 f0590ecf2..000000000 --- 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 06d94bc40..000000000 --- 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 1529ffdfe..000000000 --- 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 515ff502b..000000000 --- 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 1f91cea86..000000000 --- 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 952c7883c..000000000 --- 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 fe607b1fe..000000000 --- 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 786a8799e..000000000 --- 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 82884632a..000000000 --- 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 7ac7dfd22..000000000 --- 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 388d62773..000000000 --- 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/build/adminSettings.asset.php b/build/adminSettings.asset.php new file mode 100644 index 000000000..d381c05ce --- /dev/null +++ b/build/adminSettings.asset.php @@ -0,0 +1 @@ + array('react', 'react-dom', 'wp-api-fetch', 'wp-components', 'wp-data', 'wp-i18n'), 'version' => '95a13702dabb8eed564884f8398d020e'); \ No newline at end of file diff --git a/build/adminSettings.js b/build/adminSettings.js new file mode 100644 index 000000000..188ec5ce2 --- /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(){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}}function n(e,o,i){return n=r()?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},n.apply(null,arguments)}function o(e){return function(e){if(Array.isArray(e))return i(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 i(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)?i(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 i(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),G=d(/^data-[\-\w.\u00B7-\uFFFF]/),W=d(/^aria-[\-\w]+$/),V=d(/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|cid|xmpp):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i),Y=d(/^(?:\w+script|data):/i),K=d(/[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g),X=d(/^html$/i),Z=function(){return"undefined"==typeof window?null:window},J=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}};return function t(){var r=arguments.length>0&&void 0!==arguments[0]?arguments[0]:Z(),n=function(e){return t(e)};if(n.version="2.3.9",n.removed=[],!r||!r.document||9!==r.document.nodeType)return n.isSupported=!1,n;var i=r.document,a=r.document,s=r.DocumentFragment,l=r.HTMLTemplateElement,c=r.Node,u=r.Element,d=r.NodeFilter,f=r.NamedNodeMap,m=void 0===f?r.NamedNodeMap||r.MozNamedAttrMap:f,h=r.HTMLFormElement,y=r.DOMParser,g=r.trustedTypes,R=u.prototype,Q=I(R,"cloneNode"),ee=I(R,"nextSibling"),te=I(R,"childNodes"),re=I(R,"parentNode");if("function"==typeof l){var ne=a.createElement("template");ne.content&&ne.content.ownerDocument&&(a=ne.content.ownerDocument)}var oe=J(g,i),ie=oe?oe.createHTML(""):"",ae=a,se=ae.implementation,le=ae.createNodeIterator,ce=ae.createDocumentFragment,ue=ae.getElementsByTagName,pe=i.importNode,de={};try{de=O(a).documentMode?a.documentMode:{}}catch(e){}var fe={};n.isSupported="function"==typeof re&&se&&void 0!==se.createHTMLDocument&&9!==de;var me,he,ye=$,ge=H,ve=G,be=W,we=Y,_e=K,Ae=V,Se=null,Ce=T({},[].concat(o(N),o(L),o(P),o(D),o(U))),Ee=null,ke=T({},[].concat(o(F),o(z),o(B),o(q))),xe=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}})),Re=null,Te=null,Oe=!0,Ie=!0,Ne=!1,Le=!1,Pe=!1,je=!1,De=!1,Me=!1,Ue=!1,Fe=!1,ze=!0,Be=!0,qe=!1,$e={},He=null,Ge=T({},["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"]),We=null,Ve=T({},["audio","video","img","source","image","track"]),Ye=null,Ke=T({},["alt","class","for","id","label","name","pattern","placeholder","role","summary","title","value","style","xmlns"]),Xe="http://www.w3.org/1998/Math/MathML",Ze="http://www.w3.org/2000/svg",Je="http://www.w3.org/1999/xhtml",Qe=Je,et=!1,tt=["application/xhtml+xml","text/html"],rt="text/html",nt=null,ot=a.createElement("form"),it=function(e){return e instanceof RegExp||e instanceof Function},at=function(t){nt&&nt===t||(t&&"object"===e(t)||(t={}),t=O(t),me=me=-1===tt.indexOf(t.PARSER_MEDIA_TYPE)?rt:t.PARSER_MEDIA_TYPE,he="application/xhtml+xml"===me?function(e){return e}:_,Se="ALLOWED_TAGS"in t?T({},t.ALLOWED_TAGS,he):Ce,Ee="ALLOWED_ATTR"in t?T({},t.ALLOWED_ATTR,he):ke,Ye="ADD_URI_SAFE_ATTR"in t?T(O(Ke),t.ADD_URI_SAFE_ATTR,he):Ke,We="ADD_DATA_URI_TAGS"in t?T(O(Ve),t.ADD_DATA_URI_TAGS,he):Ve,He="FORBID_CONTENTS"in t?T({},t.FORBID_CONTENTS,he):Ge,Re="FORBID_TAGS"in t?T({},t.FORBID_TAGS,he):{},Te="FORBID_ATTR"in t?T({},t.FORBID_ATTR,he):{},$e="USE_PROFILES"in t&&t.USE_PROFILES,Oe=!1!==t.ALLOW_ARIA_ATTR,Ie=!1!==t.ALLOW_DATA_ATTR,Ne=t.ALLOW_UNKNOWN_PROTOCOLS||!1,Le=t.SAFE_FOR_TEMPLATES||!1,Pe=t.WHOLE_DOCUMENT||!1,Me=t.RETURN_DOM||!1,Ue=t.RETURN_DOM_FRAGMENT||!1,Fe=t.RETURN_TRUSTED_TYPE||!1,De=t.FORCE_BODY||!1,ze=!1!==t.SANITIZE_DOM,Be=!1!==t.KEEP_CONTENT,qe=t.IN_PLACE||!1,Ae=t.ALLOWED_URI_REGEXP||Ae,Qe=t.NAMESPACE||Je,t.CUSTOM_ELEMENT_HANDLING&&it(t.CUSTOM_ELEMENT_HANDLING.tagNameCheck)&&(xe.tagNameCheck=t.CUSTOM_ELEMENT_HANDLING.tagNameCheck),t.CUSTOM_ELEMENT_HANDLING&&it(t.CUSTOM_ELEMENT_HANDLING.attributeNameCheck)&&(xe.attributeNameCheck=t.CUSTOM_ELEMENT_HANDLING.attributeNameCheck),t.CUSTOM_ELEMENT_HANDLING&&"boolean"==typeof t.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements&&(xe.allowCustomizedBuiltInElements=t.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements),Le&&(Ie=!1),Ue&&(Me=!0),$e&&(Se=T({},o(U)),Ee=[],!0===$e.html&&(T(Se,N),T(Ee,F)),!0===$e.svg&&(T(Se,L),T(Ee,z),T(Ee,q)),!0===$e.svgFilters&&(T(Se,P),T(Ee,z),T(Ee,q)),!0===$e.mathMl&&(T(Se,D),T(Ee,B),T(Ee,q))),t.ADD_TAGS&&(Se===Ce&&(Se=O(Se)),T(Se,t.ADD_TAGS,he)),t.ADD_ATTR&&(Ee===ke&&(Ee=O(Ee)),T(Ee,t.ADD_ATTR,he)),t.ADD_URI_SAFE_ATTR&&T(Ye,t.ADD_URI_SAFE_ATTR,he),t.FORBID_CONTENTS&&(He===Ge&&(He=O(He)),T(He,t.FORBID_CONTENTS,he)),Be&&(Se["#text"]=!0),Pe&&T(Se,["html","head","body"]),Se.table&&(T(Se,["tbody"]),delete Re.tbody),p&&p(t),nt=t)},st=T({},["mi","mo","mn","ms","mtext"]),lt=T({},["foreignobject","desc","title","annotation-xml"]),ct=T({},["title","style","font","a","script"]),ut=T({},L);T(ut,P),T(ut,j);var pt=T({},D);T(pt,M);var dt=function(e){var t=re(e);t&&t.tagName||(t={namespaceURI:Je,tagName:"template"});var r=_(e.tagName),n=_(t.tagName);return e.namespaceURI===Ze?t.namespaceURI===Je?"svg"===r:t.namespaceURI===Xe?"svg"===r&&("annotation-xml"===n||st[n]):Boolean(ut[r]):e.namespaceURI===Xe?t.namespaceURI===Je?"math"===r:t.namespaceURI===Ze?"math"===r&<[n]:Boolean(pt[r]):e.namespaceURI===Je&&!(t.namespaceURI===Ze&&!lt[n])&&!(t.namespaceURI===Xe&&!st[n])&&!pt[r]&&(ct[r]||!ut[r])},ft=function(e){w(n.removed,{element:e});try{e.parentNode.removeChild(e)}catch(t){try{e.outerHTML=ie}catch(t){e.remove()}}},mt=function(e,t){try{w(n.removed,{attribute:t.getAttributeNode(e),from:t})}catch(e){w(n.removed,{attribute:null,from:t})}if(t.removeAttribute(e),"is"===e&&!Ee[e])if(Me||Ue)try{ft(t)}catch(e){}else try{t.setAttribute(e,"")}catch(e){}},ht=function(e){var t,r;if(De)e=""+e;else{var n=A(e,/^[\r\n\t ]+/);r=n&&n[0]}"application/xhtml+xml"===me&&(e=''+e+"");var o=oe?oe.createHTML(e):e;if(Qe===Je)try{t=(new y).parseFromString(o,me)}catch(e){}if(!t||!t.documentElement){t=se.createDocument(Qe,"template",null);try{t.documentElement.innerHTML=et?"":o}catch(e){}}var i=t.body||t.documentElement;return e&&r&&i.insertBefore(a.createTextNode(r),i.childNodes[0]||null),Qe===Je?ue.call(t,Pe?"html":"body")[0]:Pe?t.documentElement:i},yt=function(e){return le.call(e.ownerDocument||e,e,d.SHOW_ELEMENT|d.SHOW_COMMENT|d.SHOW_TEXT,null,!1)},gt=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)},vt=function(t){return"object"===e(c)?t instanceof c:t&&"object"===e(t)&&"number"==typeof t.nodeType&&"string"==typeof t.nodeName},bt=function(e,t,r){fe[e]&&v(fe[e],(function(e){e.call(n,t,r,nt)}))},wt=function(e){var t;if(bt("beforeSanitizeElements",e,null),gt(e))return ft(e),!0;if(k(/[\u0080-\uFFFF]/,e.nodeName))return ft(e),!0;var r=he(e.nodeName);if(bt("uponSanitizeElement",e,{tagName:r,allowedTags:Se}),e.hasChildNodes()&&!vt(e.firstElementChild)&&(!vt(e.content)||!vt(e.content.firstElementChild))&&k(/<[/\w]/g,e.innerHTML)&&k(/<[/\w]/g,e.textContent))return ft(e),!0;if("select"===r&&k(/