.zip
with build changes](${zipArtifactUrl})
+
+**⚠️ Note:** The preview sites are created using [WordPress Playground](https://wordpress.org/playground/). You can add content, edit settings, and test the themes as you would on a real site, but please note that changes are not saved between sessions.
+`;
+
+ const repoData = {
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ };
+
+ // Check if a comment already exists and update it if it does
+ const { data: comments } = await github.rest.issues.listComments({
+ issue_number: context.payload.pull_request.number,
+ ...repoData,
+ });
+ const existingComment = comments.find(
+ (comment) =>
+ comment.user.login === 'github-actions[bot]' &&
+ comment.body.startsWith( title )
+ );
+ const commentObject = {
+ body: `${title}\n${comment}`,
+ ...repoData,
+ };
+
+ if (existingComment) {
+ // Do not update, but delete and recreate Comment to have a new one after last commit.
+ await github.rest.issues.deleteComment({
+ comment_id: existingComment.id,
+ ...commentObject,
+ });
+ }
+
+ // Create a new comment if one doesn't exist
+ github.rest.issues.createComment({
+ issue_number: context.payload.pull_request.number,
+ ...commentObject,
+ });
+}
+
+module.exports = createPreviewLinksComment;
\ No newline at end of file
diff --git a/.github/scripts/wordpress-org-screenshots/blueprint.json b/.github/scripts/wordpress-org-screenshots/blueprint.json
new file mode 100644
index 000000000..0990516a1
--- /dev/null
+++ b/.github/scripts/wordpress-org-screenshots/blueprint.json
@@ -0,0 +1,60 @@
+{
+ "$schema": "https://playground.wordpress.net/blueprint-schema.json",
+ "preferredVersions": {
+ "php": "8.2",
+ "wp": "latest"
+ },
+ "phpExtensionBundles": [
+ "kitchen-sink"
+ ],
+ "features": {
+ "networking": true
+ },
+ "constants": {
+ "WP_HTTP_BLOCK_EXTERNAL": "true",
+ "GATHERPRESS_ALPHA_VERSION": "true"
+ },
+ "siteOptions": {
+ "blogname": "GatherPress",
+ "blogdescription": "Powering Communities with WordPress.",
+ "users_can_register": "1",
+ "permalink_structure": "/%postname%/"
+ },
+ "steps": [
+ {
+ "step": "defineWpConfigConsts",
+ "consts": {
+ "WP_DEBUG": false,
+ "WP_DEBUG_DISPLAY": false,
+ "DISABLE_WP_CRON": true
+ }
+ },
+ {
+ "step": "login"
+ },
+ {
+ "step": "updateUserMeta",
+ "meta": {
+ "admin_color": "modern"
+ },
+ "userId": 1
+ },
+ {
+ "step": "installPlugin",
+ "pluginZipFile": {
+ "resource": "wordpress.org/plugins",
+ "slug": "gatherpress"
+ },
+ "options": {
+ "activate": true
+ }
+ },
+ {
+ "step": "importWxr",
+ "file": {
+ "resource": "url",
+ "url": "https://raw.githubusercontent.com/GatherPress/demo-data/main/GatherPress-demo-data-2024.xml"
+ }
+ }
+ ]
+}
\ No newline at end of file
diff --git a/.github/scripts/wordpress-org-screenshots/playwright.config.ts b/.github/scripts/wordpress-org-screenshots/playwright.config.ts
new file mode 100644
index 000000000..6989abc1d
--- /dev/null
+++ b/.github/scripts/wordpress-org-screenshots/playwright.config.ts
@@ -0,0 +1,55 @@
+/**
+ * External dependencies
+ */
+import { defineConfig, devices } from '@playwright/test';
+
+/**
+ * WordPress dependencies
+ *
+ * Playwright default configuration, that is used & provided by Gutenberg.
+ * https://github.com/WordPress/gutenberg/blob/trunk/packages/scripts/config/playwright.config.js
+ */
+const { ...baseConfig} = require( '@wordpress/scripts/config/playwright.config' );
+
+export default defineConfig({
+ ...baseConfig,
+
+ // This directory holds all the test files.
+ // https://playwright.dev/docs/api/class-testconfig#test-config-test-dir
+ testDir: '.',
+
+ snapshotPathTemplate: './../../../.wordpress-org/{arg}{ext}',
+
+ expect: {
+ toHaveScreenshot: {
+ // https://playwright.dev/docs/test-snapshots#maxdiffpixels
+ maxDiffPixelRatio: process.env.UPDATE_ALL_SNAPSHOTS ? 0 : 0.05,
+ // https://playwright.dev/docs/test-snapshots#stylepath
+ stylePath: './ui-adjustments.css'
+ },
+ },
+
+ // Configure projects for major browsers
+ // We can test on different or multiple browsers if needed.
+ // https://playwright.dev/docs/test-projects#configure-projects-for-multiple-browsers
+ projects: [
+ {
+ name: "chromium",
+ use: { ...devices["Desktop Chrome"] },
+ },
+ ],
+ // Don't report slow test "files", as we will be running our tests in serial.
+ reportSlowTests: null,
+ use: {
+ ...baseConfig.use,
+ baseURL: process.env.WP_BASE_URL || 'http://127.0.0.1:9400',
+ },
+ retries: 0,
+ webServer: {
+ ...baseConfig.webServer,
+ command: 'npm run playground -- --blueprint=./localized_blueprint.json',
+ port: 9400,
+ // reuseExistingServer: !process.env.CI,
+ reuseExistingServer: true,
+ },
+});
\ No newline at end of file
diff --git a/.github/scripts/wordpress-org-screenshots/ui-adjustments.css b/.github/scripts/wordpress-org-screenshots/ui-adjustments.css
new file mode 100644
index 000000000..8e2c6094e
--- /dev/null
+++ b/.github/scripts/wordpress-org-screenshots/ui-adjustments.css
@@ -0,0 +1,12 @@
+/**
+ The content of this file is injected into the page within script tags,
+ rather than being included as a file.
+**/
+#adminmenuwrap {
+ /**
+ Stretch the dark grey background
+ behind the left main menu
+ over the full height of the page
+ **/
+ height: 10000px;
+}
\ No newline at end of file
diff --git a/.github/scripts/wordpress-org-screenshots/wporg.spec.ts b/.github/scripts/wordpress-org-screenshots/wporg.spec.ts
new file mode 100644
index 000000000..9e47b2847
--- /dev/null
+++ b/.github/scripts/wordpress-org-screenshots/wporg.spec.ts
@@ -0,0 +1,115 @@
+/**
+ * WordPress dependencies
+ */
+const { test, expect } = require( '@wordpress/e2e-test-utils-playwright' );
+
+test.describe( 'Screenshots for the wordpress.org/plugins repository', () => {
+ let
+ language: string,
+ local_code: string;
+
+ // set the file name of the screenshot basaed on the current locale
+ // https://developer.wordpress.org/plugins/wordpress-org/plugin-assets/#filenames-2
+ const getFileName = ( title: string ) => {
+ return [
+ title,
+ local_code,
+ '.png'
+ ].join('').toLowerCase();
+ }
+
+ test.beforeAll( async ( { requestUtils } ) => {
+
+ // https://github.com/WordPress/gutenberg/blob/trunk/packages/e2e-test-utils-playwright/src/request-utils/site-settings.ts#L34-L35
+ language = ( await requestUtils.getSiteSettings() ).language;
+ console.log('language', language);
+ local_code = ( 'en_US' === language ) ? '' : '-' + language.substring(0, 2);
+ } );
+
+ // The test-description should match the caption for screenshot-# in the readme.md
+ test('Create a new event', async ({
+ admin,
+ editor,
+ page,
+ }) => {
+ await admin.visitAdminPage(
+ 'post-new.php',
+ 'post_type=gatherpress_event'
+ );
+
+ await editor.setPreferences( 'core/edit-post', {
+ welcomeGuide: false,
+ });
+
+ // Wait for 2 seconds
+ await page.waitForTimeout(2000);
+
+ // https://playwright.dev/docs/api/class-pageassertions#page-assertions-to-have-screenshot-1
+ await expect(page).toHaveScreenshot( getFileName( 'screenshot-1' ), {
+ fullPage: true
+ });
+ });
+
+ // The test-description should match the caption for screenshot-# in the readme.md
+ test('Create a new venue', async ({
+ admin,
+ editor,
+ page,
+ }) => {
+ await admin.visitAdminPage(
+ 'post-new.php',
+ 'post_type=gatherpress_venue'
+ );
+
+ await editor.setPreferences( 'core/edit-post', {
+ welcomeGuide: false,
+ });
+
+ // Wait for 2 seconds
+ await page.waitForTimeout(2000);
+
+ // https://playwright.dev/docs/api/class-pageassertions#page-assertions-to-have-screenshot-1
+ await expect(page).toHaveScreenshot( getFileName( 'screenshot-2' ), {
+ fullPage: true
+ });
+ });
+
+ // The test-description should match the caption for screenshot-# in the readme.md
+ test('General Settings', async ({
+ page,
+ admin,
+ }) => {
+ await admin.visitAdminPage(
+ 'edit.php',
+ 'post_type=gatherpress_event&page=gatherpress_general'
+ );
+
+ // Wait for 2 seconds
+ await page.waitForTimeout(2000);
+
+ // https://playwright.dev/docs/api/class-pageassertions#page-assertions-to-have-screenshot-1
+ await expect(page).toHaveScreenshot( getFileName( 'screenshot-3' ), {
+ fullPage: true
+ });
+ });
+
+ // The test-description should match the caption for screenshot-# in the readme.md
+ test('Leadership Settings', async ({
+ page,
+ admin,
+ }) => {
+ await admin.visitAdminPage(
+ 'edit.php',
+ 'post_type=gatherpress_event&page=gatherpress_leadership'
+ );
+
+ // Wait for 2 seconds
+ await page.waitForTimeout(2000);
+
+ // https://playwright.dev/docs/api/class-pageassertions#page-assertions-to-have-screenshot-1
+ await expect(page).toHaveScreenshot( getFileName( 'screenshot-4' ), {
+ fullPage: true
+ });
+ });
+
+});
\ No newline at end of file
diff --git a/.github/workflows/coding-standards.yml b/.github/workflows/coding-standards.yml
index 6e5001a4f..a2828a5ed 100644
--- a/.github/workflows/coding-standards.yml
+++ b/.github/workflows/coding-standards.yml
@@ -4,14 +4,21 @@ on:
branches:
- main
pull_request:
-
+ paths:
+ - '.github/workflows/coding-standards.yml'
+ - 'includes/**'
+ - 'src/**'
+ - 'test/**'
+ - 'package.*'
+ - '*.js'
+ - '*.php'
jobs:
phpcs:
name: PHP Coding Standards
runs-on: ubuntu-latest
steps:
- name: Checkout repository
- uses: actions/checkout@v2
+ uses: actions/checkout@v4
- name: Get Composer cache directory
id: composer-cache
@@ -53,7 +60,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
- uses: actions/checkout@v2
+ uses: actions/checkout@v4
- name: Log debug information
run: |
@@ -64,13 +71,88 @@ jobs:
composer --version
- name: Install NodeJS
- uses: actions/setup-node@v2
+ uses: actions/setup-node@v4
+ with:
+ node-version-file: '.nvmrc'
+ # Enable built-in functionality for caching and restoring dependencies, which is disabled by default.
+ # The actions/setup-node uses actions/cache under the hood.
+ # https://github.com/actions/setup-node#caching-global-packages-data
+ cache: 'npm'
+
+ # Restoring the short lived node_modules cache
+ # to be used across all workflows running on the last commit.
+ # https://github.com/actions/cache/blob/main/caching-strategies.md#creating-a-short-lived-cache
+ - uses: actions/cache/restore@v4
+ id: node_modules-cache
with:
- node-version-file: '.nvmrc'
+ path: |
+ ./node_modules
+ key: ${{ runner.os }}-node_modules-${{ github.sha }}-${{ hashFiles('package-lock.json') }}
- name: NPM install
+ if: steps.node_modules-cache.outputs.cache-hit != 'true'
run: npm ci --legacy-peer-deps
+ # Creating a short lived node_modules cache
+ - uses: actions/cache/save@v4
+ if: steps.node_modules-cache.outputs.cache-hit != 'true'
+ with:
+ path: |
+ ./node_modules
+ key: ${{ steps.node_modules-cache.outputs.cache-primary-key }}
+
- name: Run JSHint
run: npm run lint:js
if: ${{ success() || failure() }}
+
+ stylelint:
+ name: CSS Coding Standards
+ needs: jshint # Wait for jshint job, to make use of node_modules caching.
+ if: always() # Run always, even when the jshint job didn't ran.
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v4
+
+ - name: Log debug information
+ run: |
+ npm --version
+ node --version
+ git --version
+ php --version
+ composer --version
+
+ - name: Install NodeJS
+ uses: actions/setup-node@v4
+ with:
+ node-version-file: '.nvmrc'
+ # Enable built-in functionality for caching and restoring dependencies, which is disabled by default.
+ # The actions/setup-node uses actions/cache under the hood.
+ # https://github.com/actions/setup-node#caching-global-packages-data
+ cache: 'npm'
+
+ # Restoring the short lived node_modules cache
+ # to be used across all workflows running on the last commit.
+ # https://github.com/actions/cache/blob/main/caching-strategies.md#creating-a-short-lived-cache
+ - uses: actions/cache/restore@v4
+ id: node_modules-cache
+ with:
+ path: |
+ ./node_modules
+ key: ${{ runner.os }}-node_modules-${{ github.sha }}-${{ hashFiles('package-lock.json') }}
+
+ - name: NPM install
+ if: steps.node_modules-cache.outputs.cache-hit != 'true'
+ run: npm ci --legacy-peer-deps
+
+ # Creating a short lived node_modules cache
+ - uses: actions/cache/save@v4
+ if: steps.node_modules-cache.outputs.cache-hit != 'true'
+ with:
+ path: |
+ ./node_modules
+ key: ${{ steps.node_modules-cache.outputs.cache-primary-key }}
+
+ - name: Run StyleLint
+ run: npm run lint:css
+ if: ${{ success() || failure() }}
diff --git a/.github/workflows/compress-images.yml b/.github/workflows/compress-images.yml
new file mode 100644
index 000000000..7fd714d21
--- /dev/null
+++ b/.github/workflows/compress-images.yml
@@ -0,0 +1,34 @@
+name: Compress Images
+on:
+ push:
+ branches:
+ - 'fix/wp-org-screenshots-**'
+ pull_request:
+ # Run Image Actions when JPG, JPEG, PNG or WebP files are added or changed.
+ # See https://help.github.com/en/actions/automating-your-workflow-with-github-actions/workflow-syntax-for-github-actions#onpushpull_requestpaths for reference.
+ paths:
+ - '**.jpg'
+ - '**.jpeg'
+ - '**.png'
+ - '**.webp'
+jobs:
+ build:
+ # Only run on Pull Requests within the same repository, and not from forks.
+ #if: github.event.pull_request.head.repo.full_name == github.repository
+ name: calibreapp/image-actions
+ permissions: write-all
+ runs-on: ubuntu-latest
+ steps:
+
+ - name: Checkout Repo
+ uses: actions/checkout@v4
+
+ - name: Compress Images
+ uses: calibreapp/image-actions@main #main is regularly updated (until 09/2024 so far), while the latest tagged version is from 2020
+ with:
+ # Configuration could be added
+ # https://github.com/marketplace/actions/image-actions#%EF%B8%8F-configuration
+ #
+ # The `GITHUB_TOKEN` is automatically generated by GitHub and scoped only to the repository that is currently running the action. By default, the action can’t update Pull Requests initiated from forked repositories.
+ # See https://docs.github.com/en/actions/reference/authentication-in-a-workflow and https://help.github.com/en/articles/virtual-environments-for-github-actions#token-permissions
+ githubToken: ${{ secrets.GITHUB_TOKEN }}
\ No newline at end of file
diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml
index a44443433..67634ca13 100644
--- a/.github/workflows/dependency-review.yml
+++ b/.github/workflows/dependency-review.yml
@@ -1,11 +1,17 @@
# Dependency Review Action
#
-# This Action will scan dependency manifest files that change as part of a Pull Reqest, surfacing known-incompatible licenses and/or known-vulnerable versions of the packages declared or updated in the PR. Once installed, if the workflow run is marked as required, PRs introducing known-incompatible licenses or known-vulnerable packages will be blocked from merging.
+# This Action will scan dependency manifest files that change as part of a Pull Request, surfacing known-incompatible licenses and/or known-vulnerable versions of the packages declared or updated in the PR. Once installed, if the workflow run is marked as required, PRs introducing known-incompatible licenses or known-vulnerable packages will be blocked from merging.
#
# Source repository: https://github.com/actions/dependency-review-action
# Public documentation: https://docs.github.com/en/code-security/supply-chain-security/understanding-your-software-supply-chain/about-dependency-review#dependency-review-enforcement
name: 'Dependency Review'
-on: [pull_request]
+on:
+ pull_request:
+ paths:
+ - '.github/workflows/dependency-review.yml'
+ - 'package*'
+ - 'composer*'
+
permissions:
contents: read
@@ -17,13 +23,28 @@ jobs:
steps:
- name: 'Checkout Repository'
uses: actions/checkout@v4
+
- name: Dependency Review
- uses: actions/dependency-review-action@v4
+ uses: actions/dependency-review-action@72eb03d02c7872a771aacd928f3123ac62ad6d3a # Version 4.3.3 # https://github.com/actions/dependency-review-action/releases/tag/v4.3.3
+ # Version 4.3.4 does not work with invalid license names in the config and since that version,
+ # SPDX expression licenses are considered invalid (see: https://github.com/actions/dependency-review-action/issues/792).
+ # In short, remove all SPDX expressions from the config!
+ #
+ # Note that if you have packages that use SPDX expressions, this will report them as invalid,
+ # as support is not yet implemented (see: https://github.com/actions/dependency-review-action/issues/263).
+ #
+ # In that case you need to downgrade to version 4.3.3 where SPDX expressions are handled as exact strings !!
+ # @source https://github.com/actions/dependency-review-action/issues/809#issuecomment-2285930024
with:
license-check: true
vulnerability-check: false
- comment-summary-in-pr: on-failure
- # You can only include one of these two options: `allow-licenses` and `deny-licences`
+
+ # Prevent this workflow to create a comment on the PR on forks outside of the GatherPress organization,
+ # because the required permission would not be given and the workflow would fail.
+ # Using a condition check will skip commenting.
+ comment-summary-in-pr: ${{ github.repository_owner == 'GatherPress' && 'on-failure' || 'never' }}
+
+ # You can only include one of these two options: `allow-licenses` and `deny-licenses`
# ([String]). Only allow these licenses (optional)
# Possible values: Any `spdx_id` value(s) from https://docs.github.com/en/rest/licenses
# The following list is an attempt to match exactly what's listed on https://www.gnu.org/licenses/license-list.html#GPLCompatibleLicenses as GPL Compatible (currently ignoring the FSF Free/Libre and OSI Approved column data from the SPDX License List at https://spdx.org/licenses/):
diff --git a/.github/workflows/e2e-tests.yml b/.github/workflows/e2e-tests.yml
index a74b82020..471733df4 100644
--- a/.github/workflows/e2e-tests.yml
+++ b/.github/workflows/e2e-tests.yml
@@ -10,7 +10,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
- uses: actions/checkout@v2
+ uses: actions/checkout@v4
- name: Log debug information
run: |
@@ -21,9 +21,13 @@ jobs:
composer --version
- name: Install NodeJS
- uses: actions/setup-node@v2
+ uses: actions/setup-node@v4
with:
- node-version-file: '.nvmrc'
+ node-version-file: '.nvmrc'
+ # Enable built-in functionality for caching and restoring dependencies, which is disabled by default.
+ # The actions/setup-node uses actions/cache under the hood.
+ # https://github.com/actions/setup-node#caching-global-packages-data
+ cache: 'npm'
- name: NPM install
run: npm ci --legacy-peer-deps
diff --git a/.github/workflows/jest-tests.yml b/.github/workflows/jest-tests.yml
index 17af931c8..07b981118 100644
--- a/.github/workflows/jest-tests.yml
+++ b/.github/workflows/jest-tests.yml
@@ -4,14 +4,19 @@ on:
branches:
- main
pull_request:
-
+ paths:
+ - '.github/workflows/jest-tests.yml'
+ - 'src/**'
+ - 'test/unit/js**'
+ - '*.js'
+ - 'package.*'
jobs:
test-js:
name: Jest Tests
runs-on: ubuntu-latest
steps:
- name: Checkout repository
- uses: actions/checkout@v2
+ uses: actions/checkout@v4
- name: Log debug information
run: |
@@ -22,13 +27,36 @@ jobs:
composer --version
- name: Install NodeJS
- uses: actions/setup-node@v2
+ uses: actions/setup-node@v4
+ with:
+ node-version-file: '.nvmrc'
+ # Enable built-in functionality for caching and restoring dependencies, which is disabled by default.
+ # The actions/setup-node uses actions/cache under the hood.
+ # https://github.com/actions/setup-node#caching-global-packages-data
+ cache: 'npm'
+
+ # Restoring the short lived node_modules cache
+ # to be used across all workflows running on the last commit.
+ # https://github.com/actions/cache/blob/main/caching-strategies.md#creating-a-short-lived-cache
+ - uses: actions/cache/restore@v4
+ id: node_modules-cache
with:
- node-version-file: '.nvmrc'
+ path: |
+ ./node_modules
+ key: ${{ runner.os }}-node_modules-${{ github.sha }}-${{ hashFiles('package-lock.json') }}
- name: NPM install
+ if: steps.node_modules-cache.outputs.cache-hit != 'true'
run: npm ci --legacy-peer-deps
+ # Creating a short lived node_modules cache
+ - uses: actions/cache/save@v4
+ if: steps.node_modules-cache.outputs.cache-hit != 'true'
+ with:
+ path: |
+ ./node_modules
+ key: ${{ steps.node_modules-cache.outputs.cache-primary-key }}
+
- name: Run Jest Tests
run: npm run test:unit:js
if: ${{ success() || failure() }}
diff --git a/.github/workflows/phpunit-tests.yml b/.github/workflows/phpunit-tests.yml
index 9df6272a3..b6c336fb8 100644
--- a/.github/workflows/phpunit-tests.yml
+++ b/.github/workflows/phpunit-tests.yml
@@ -4,7 +4,13 @@ on:
branches:
- main
pull_request:
-
+ paths:
+ - '.github/workflows/phpunit-tests.yml'
+ - 'includes/**'
+ - 'test/unit/php**'
+ - '*.php'
+ - 'phpunit.xml.dist'
+ - 'composer.*'
jobs:
test-php:
name: ${{ matrix.php_versions }} on ${{ matrix.os }}
@@ -15,7 +21,7 @@ jobs:
php_versions: [ '7.4', '8.0', '8.1', '8.2', '8.3' ]
steps:
- name: Checkout
- uses: actions/checkout@v2
+ uses: actions/checkout@v4
- name: Setup PHP
uses: shivammathur/setup-php@v2
@@ -27,9 +33,13 @@ jobs:
run: composer install --optimize-autoloader --prefer-dist
- name: Install NodeJS
- uses: actions/setup-node@v2
+ uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
+ # Enable built-in functionality for caching and restoring dependencies, which is disabled by default.
+ # The actions/setup-node uses actions/cache under the hood.
+ # https://github.com/actions/setup-node#caching-global-packages-data
+ cache: 'npm'
- name: Log debug information
run: |
diff --git a/.github/workflows/playground-preview.yml b/.github/workflows/playground-preview.yml
new file mode 100644
index 000000000..fec9cb439
--- /dev/null
+++ b/.github/workflows/playground-preview.yml
@@ -0,0 +1,129 @@
+# For now (!) the name here is important and should not be changed!
+#
+# The plugin-proxy.php does a check against exact this workflow name.
+name: Playground Preview
+
+# Inspired by, but not based on https://github.com/WordPress/gutenberg/blob/b89fb7b6eaf619bde0269e2a7fbf6245822f6cbf/.github/workflows/build-plugin-zip.yml#L153
+
+on:
+ # What and Why pull_request_target?
+ # https://github.com/GatherPress/gatherpress/pull/666#issuecomment-2143088443
+ #
+ # The GitHub Actions built in environment variables and Context
+ # of pull_request_target event are different from those of pull_request event.
+ #
+ # For example, the following environment variables and context are different.
+ #
+ # - event_name, GITHUB_EVENT_NAME
+ # - ref, GITHUB_REF
+ # - sha, GITHUB_SHA
+ # - ref_name, GITHUB_REF_NAME
+ #
+ # @source https://dev.to/suzukishunsuke/secure-github-actions-by-pullrequesttarget-641#modify-workflows-for-pullrequesttarget
+
+ pull_request_target:
+ types: [opened, synchronize]
+ paths:
+ - 'build/**'
+ - 'includes/**'
+ - 'src/**'
+ - '*.php'
+
+# Cancels all previous workflow runs for pull requests that have not completed.
+concurrency:
+ # The concurrency group contains the workflow name and the branch name for pull requests
+ # or the commit hash for any other events.
+ group: ${{ github.workflow }}-${{ github.event_name == 'pull_request_target' && github.head_ref || github.sha }}
+ cancel-in-progress: true
+
+jobs:
+
+ zip:
+ name: Build GatherPress plugin & upload as zipped artifact
+ runs-on: ubuntu-latest
+ steps:
+
+ # To checkout the merged commit with actions/checkout on pull_request_target event,
+ # you need to get the pull request by GitHub API
+ # and set the merge commit hash to actions/checkout input ref.
+ #
+ # @source https://dev.to/suzukishunsuke/secure-github-actions-by-pullrequesttarget-641#checkout-merge-commits
+ - uses: suzuki-shunsuke/get-pr-action@v0.1.0
+ id: pr
+
+ - name: Checkout
+ uses: actions/checkout@v4
+ with:
+ ref: ${{ steps.pr.outputs.merge_commit_sha }}
+ show-progress: ${{ runner.debug == '1' && 'true' || 'false' }}
+
+ - name: Setup PHP
+ uses: shivammathur/setup-php@v2
+ with:
+ php-version: latest
+ coverage: none
+ tools: wp-cli
+
+ - name: Install latest version of dist-archive-command
+ run: wp package install wp-cli/dist-archive-command:dev-main
+
+ - name: Setup Node
+ uses: actions/setup-node@v4
+ with:
+ node-version-file: '.nvmrc'
+ # Enable built-in functionality for caching and restoring dependencies, which is disabled by default.
+ # The actions/setup-node uses actions/cache under the hood.
+ # https://github.com/actions/setup-node#caching-global-packages-data
+ cache: 'npm'
+
+ # Restoring the short lived node_modules cache
+ # to be used across all workflows running on the last commit.
+ # https://github.com/actions/cache/blob/main/caching-strategies.md#creating-a-short-lived-cache
+ - uses: actions/cache/restore@v4
+ id: node_modules-cache
+ with:
+ path: |
+ ./node_modules
+ key: ${{ runner.os }}-node_modules-${{ steps.pr.outputs.merge_commit_sha }}-${{ hashFiles('package-lock.json') }}
+
+ - name: NPM install
+ if: steps.node_modules-cache.outputs.cache-hit != 'true'
+ run: npm ci --legacy-peer-deps
+
+ # Creating a short lived node_modules cache
+ - uses: actions/cache/save@v4
+ if: steps.node_modules-cache.outputs.cache-hit != 'true'
+ with:
+ path: |
+ ./node_modules
+ key: ${{ steps.node_modules-cache.outputs.cache-primary-key }}
+
+ - name: Build plugin
+ # - [Incorrect version number used when creating zip archive · Issue #92 · wp-cli/dist-archive-command](https://github.com/wp-cli/dist-archive-command/issues/92)
+ run: |
+ npm run build
+ wp dist-archive . ./${{ github.event.repository.name }}.zip
+
+ - name: Upload artifact
+ uses: actions/upload-artifact@v4
+ with:
+ name: ${{ github.event.repository.name }}-pr
+ path: ./${{ github.event.repository.name }}.zip
+
+ comment:
+ name: Comment with playground link
+ needs: zip # Ensure this runs after zip job.
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+
+ - name: Add Preview Links comment
+ id: comment-on-pr
+ uses: actions/github-script@v7
+ with:
+ github-token: ${{ secrets.GITHUB_TOKEN }}
+ script: |
+ const createPreviewLinks = require('.github/scripts/create-preview-links');
+ createPreviewLinks(github, context);
\ No newline at end of file
diff --git a/.github/workflows/sonarcloud.yml b/.github/workflows/sonarcloud.yml
index f0b0ae6d2..94ad2fd29 100644
--- a/.github/workflows/sonarcloud.yml
+++ b/.github/workflows/sonarcloud.yml
@@ -10,7 +10,7 @@ jobs:
runs-on: 'ubuntu-latest'
steps:
- name: Checkout
- uses: actions/checkout@v2
+ uses: actions/checkout@v4
- name: Setup PHP
uses: shivammathur/setup-php@v2
@@ -22,13 +22,36 @@ jobs:
run: composer install --optimize-autoloader --prefer-dist
- name: Install NodeJS
- uses: actions/setup-node@v2
+ uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
+ # Enable built-in functionality for caching and restoring dependencies, which is disabled by default.
+ # The actions/setup-node uses actions/cache under the hood.
+ # https://github.com/actions/setup-node#caching-global-packages-data
+ cache: 'npm'
+
+ # Restoring the short lived node_modules cache
+ # to be used across all workflows running on the last commit.
+ # https://github.com/actions/cache/blob/main/caching-strategies.md#creating-a-short-lived-cache
+ - uses: actions/cache/restore@v4
+ id: node_modules-cache
+ with:
+ path: |
+ ./node_modules
+ key: ${{ runner.os }}-node_modules-${{ github.sha }}-${{ hashFiles('package-lock.json') }}
- name: NPM install
+ if: steps.node_modules-cache.outputs.cache-hit != 'true'
run: npm ci --legacy-peer-deps
+ # Creating a short lived node_modules cache
+ - uses: actions/cache/save@v4
+ if: steps.node_modules-cache.outputs.cache-hit != 'true'
+ with:
+ path: |
+ ./node_modules
+ key: ${{ steps.node_modules-cache.outputs.cache-primary-key }}
+
- name: Log debug information
run: |
npm --version
diff --git a/.github/workflows/typos.yml b/.github/workflows/typos.yml
new file mode 100644
index 000000000..cb59013c0
--- /dev/null
+++ b/.github/workflows/typos.yml
@@ -0,0 +1,23 @@
+# Check if there are typos in the source code
+# https://github.com/crate-ci/typos
+# https://github.com/crate-ci/typos/blob/HEAD/docs/reference.md
+
+name: Spell Check with Typos
+on:
+ workflow_dispatch:
+ pull_request:
+
+jobs:
+ typos:
+ name: Spell Check with Typos
+ runs-on: ubuntu-latest
+ steps:
+
+ - name: Checkout Actions Repository
+ uses: actions/checkout@v4
+
+ - name: Check spelling
+ uses: crate-ci/typos@master
+ with:
+ files: ./.github ./docs ./includes ./src ./test ./*.php ./*.md
+ config: ./.typos.toml
\ No newline at end of file
diff --git a/.github/workflows/wordpress-org-plugin-guidelines.yml b/.github/workflows/wordpress-org-plugin-guidelines.yml
index 2912b2be2..7c7e28360 100644
--- a/.github/workflows/wordpress-org-plugin-guidelines.yml
+++ b/.github/workflows/wordpress-org-plugin-guidelines.yml
@@ -2,6 +2,13 @@ name: 'WordPress.org plugin directory guidelines'
on: # rebuild any PRs and main branch changes
workflow_dispatch:
pull_request:
+ paths:
+ - '.github/workflows/wordpress-org-plugin-guidelines.yml'
+ - 'includes/**'
+ - 'src/**'
+ - 'package.*'
+ - '*.js'
+ - '*.php'
push:
branches:
- main
@@ -29,10 +36,32 @@ jobs:
with:
# Make sure to use the same version like WordPress/gutenberg.
node-version-file: '.nvmrc'
- cache: npm
+ # Enable built-in functionality for caching and restoring dependencies, which is disabled by default.
+ # The actions/setup-node uses actions/cache under the hood.
+ # https://github.com/actions/setup-node#caching-global-packages-data
+ cache: 'npm'
- - name: Install dependencies
- run: npm ci
+ # Restoring the short lived node_modules cache
+ # to be used across all workflows running on the last commit.
+ # https://github.com/actions/cache/blob/main/caching-strategies.md#creating-a-short-lived-cache
+ - uses: actions/cache/restore@v4
+ id: node_modules-cache
+ with:
+ path: |
+ ./node_modules
+ key: ${{ runner.os }}-node_modules-${{ github.sha }}-${{ hashFiles('package-lock.json') }}
+
+ - name: NPM install
+ if: steps.node_modules-cache.outputs.cache-hit != 'true'
+ run: npm ci --legacy-peer-deps
+
+ # Creating a short lived node_modules cache
+ - uses: actions/cache/save@v4
+ if: steps.node_modules-cache.outputs.cache-hit != 'true'
+ with:
+ path: |
+ ./node_modules
+ key: ${{ steps.node_modules-cache.outputs.cache-primary-key }}
- name: Build plugin
run: |
diff --git a/.github/workflows/wordpress-org-readme-md-validation.yml b/.github/workflows/wordpress-org-readme-md-validation.yml
new file mode 100644
index 000000000..c7f51b07c
--- /dev/null
+++ b/.github/workflows/wordpress-org-readme-md-validation.yml
@@ -0,0 +1,23 @@
+name: 'WordPress.org README.md validation'
+on: # rebuild any PRs and main branch changes
+ workflow_dispatch:
+ pull_request:
+ paths:
+ - '.github/workflows/wordpress-org-readme-md-validation.yml'
+ - 'readme.md'
+ push:
+ branches:
+ - main
+
+jobs:
+ wp-org-readme-md-validation:
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+
+ - name: Validate readme.md
+ uses: pantheon-systems/validate-readme-spacing@v1
+ with:
+ filepath: 'readme.md'
diff --git a/.github/workflows/wordpress-org-screenshots.yml b/.github/workflows/wordpress-org-screenshots.yml
new file mode 100644
index 000000000..392c186d5
--- /dev/null
+++ b/.github/workflows/wordpress-org-screenshots.yml
@@ -0,0 +1,177 @@
+name: WordPress.org screenshot generation
+
+on:
+ workflow_dispatch:
+ inputs:
+ updateAllSnapshots:
+ description: 'Replace all existing images? (By default only images with noticeable changes will be updated.)'
+ required: false
+ type: 'boolean'
+ default: 'false' # Needs to be a string, see https://graphite.dev/guides/github-actions-inputs#handling-boolean-inputs
+
+# Cancels all previous workflow runs.
+concurrency:
+ # The concurrency group contains the workflow name and the commit hash.
+ group: ${{ github.workflow }}-${{ github.sha }}
+ cancel-in-progress: true
+
+permissions:
+ pull-requests: write
+ contents: write # Grant write permissions for the contents scope to allow pushing changes
+
+jobs:
+ screenshot:
+ runs-on: ubuntu-latest
+ strategy:
+ fail-fast: false
+ max-parallel: 1 # Prevent parallel runs to make use of the caching for node_modules and playwright browsers
+ matrix:
+ # Use all locales with more than 90% complete translations on https://translate.wordpress.org/projects/wp-plugins/gatherpress/
+ locale: [
+ 'en_US',
+ 'fr_FR',
+ 'de_DE',
+ 'es_ES',
+ 'mr',
+ 'nl_BE',
+ 'it_IT'
+ ]
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+
+ - uses: actions/cache@v4
+ id: playwright-cache
+ with:
+ path: |
+ ~/.cache/ms-playwright
+ key: ${{ runner.os }}-playwright-${{ hashFiles('**/package-lock.json') }}
+
+ - name: Setup Node
+ uses: actions/setup-node@v4
+ with:
+ node-version-file: '.nvmrc'
+ # Enable built-in functionality for caching and restoring dependencies, which is disabled by default.
+ # The actions/setup-node uses actions/cache under the hood.
+ # https://github.com/actions/setup-node#caching-global-packages-data
+ cache: 'npm'
+
+ # Restoring the short lived node_modules cache
+ # to be used across all workflows running on the last commit.
+ # https://github.com/actions/cache/blob/main/caching-strategies.md#creating-a-short-lived-cache
+ - uses: actions/cache/restore@v4
+ id: node_modules-cache
+ with:
+ path: |
+ ./node_modules
+ key: ${{ runner.os }}-node_modules-${{ github.sha }}-${{ hashFiles('package-lock.json') }}
+
+ - name: NPM install
+ if: steps.node_modules-cache.outputs.cache-hit != 'true'
+ run: npm ci --legacy-peer-deps
+
+ # Creating a short lived node_modules cache
+ - uses: actions/cache/save@v4
+ if: steps.node_modules-cache.outputs.cache-hit != 'true'
+ with:
+ path: |
+ ./node_modules
+ key: ${{ steps.node_modules-cache.outputs.cache-primary-key }}
+
+ - name: Install Playwright dependencies
+ run: npx playwright install --with-deps chromium
+ if: steps.playwright-cache.outputs.cache-hit != 'true'
+ - run: npx playwright install-deps chromium
+ if: steps.playwright-cache.outputs.cache-hit == 'true'
+
+ - name: Prepare localized blueprint
+ # en_US should not get any additional steps added, as this will result in errors!
+ #
+ # All other locales need those two steps!
+ # The first downloads all lang-packs, while the second is important for
+ # "( await requestUtils.getSiteSettings() ).language;"
+ # which would otherwise return only "en_US". Learned that the hard way!
+ # Might be a bug in Playgrounds setSiteLanguage step or intended behavior.
+ run: |
+ if [ ${{ matrix.locale }} == 'en_US' ]; then
+ cp .github/scripts/wordpress-org-screenshots/blueprint.json localized_blueprint.json
+ else
+ language_step='[
+ {
+ "step": "setSiteLanguage",
+ "language": "${{ matrix.locale }}"
+ },
+ {
+ "step": "wp-cli",
+ "command": "wp option update WPLANG ${{ matrix.locale }}"
+ }
+ ]'
+ echo "Use jq to append the site language step to the existing blueprint JSON file."
+ jq --argjson languageStep "$language_step" '.steps += $languageStep' .github/scripts/wordpress-org-screenshots/blueprint.json > localized_blueprint.json
+ fi
+
+ - name: Starting Playground
+ # Having this as a separate workflow step, should help making sure Playwright runs only, when this is DONE & READY.
+ #
+ # Because it seems to be a problem to "wait on webServer.command" https://github.com/microsoft/playwright/issues/11811
+ # & "it seems that globalSetup runs before webServer is started." https://github.com/microsoft/playwright/issues/11811#issuecomment-1040732201
+ #
+ # The "&" is important to allow the next step to start!
+ run: |
+ npm run playground -- --blueprint=./localized_blueprint.json &
+
+ - name: Running the screenshot tests
+ id: screenshot-tests
+ # Having set "continue-on-error:true" should help the workflow to pass (and get a green checkmark)
+ # even if this step fails, what could happen because of intended changes or the addition of new locales.
+ continue-on-error: true
+ if: ${{ ! github.event.inputs.updateAllSnapshots }}
+ env:
+ PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1
+ WP_BASE_URL: 'http://127.0.0.1:9400/'
+ run: |
+ DEBUG=pw:webserver \
+ npm run screenshots:wporg
+
+ - name: Updating the Screenshots
+ # Using "continue-on-error:true" results in 'conclusion' being a success in any case, while the 'outcome' can differ.
+ # And, as you already guessed, if: failure() looks at 'conclusion'.
+ #
+ # Or the step is triggered directly, while the former step is skipped,
+ # when the updateAllSnapshots is trueish.
+ if: ${{ github.event.inputs.updateAllSnapshots || steps.screenshot-tests.outcome == 'failure' }}
+ env:
+ PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1
+ WP_BASE_URL: 'http://127.0.0.1:9400/'
+ UPDATE_ALL_SNAPSHOTS: ${{ github.event.inputs.updateAllSnapshots }}
+ run: |
+ DEBUG=pw:webserver \
+ npm run screenshots:wporg -- --update-snapshots
+
+ - name: Commit updated screenshots
+ # Using "continue-on-error:true" results in 'conclusion' being a success in any case, while the 'outcome' can differ.
+ # And, as you already guessed, if: failure() looks at 'conclusion'.
+ if: ${{ github.event.inputs.updateAllSnapshots || steps.screenshot-tests.outcome == 'failure' }}
+ run: |
+ git checkout -b fix/wp-org-screenshots-${{ matrix.locale }}-${{ github.sha }}
+ git config --local user.email "action@github.com"
+ git config --local user.name "GitHub Action"
+ # Remove untracked, temporary file
+ rm -f ./localized_blueprint.json
+ git add -A
+ git commit -m "Screenshots for ${{ matrix.locale }} updated!"
+ git push origin fix/wp-org-screenshots-${{ matrix.locale }}-${{ github.sha }}
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+
+ - name: Create a Pull Request
+ # Using "continue-on-error:true" results in 'conclusion' being a success in any case, while the 'outcome' can differ.
+ # And, as you already guessed, if: failure() looks at 'conclusion'.
+ if: ${{ github.event.inputs.updateAllSnapshots || steps.screenshot-tests.outcome == 'failure' }}
+ # Using GitHub CLI in Workflows
+ # https://docs.github.com/en/actions/using-workflows/using-github-cli-in-workflows
+ # https://cli.github.com/manual/gh_pr_create
+ run: gh pr create -B main -H fix/wp-org-screenshots-${{ matrix.locale }}-${{ github.sha }} --title 'Update ${{ matrix.locale }} screenshots for wordpress.org' --body 'Created with ❤️ by WordPress Playground, Playwright & GitHub action'
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
diff --git a/.github/workflows/wordpress-version-checker.yml b/.github/workflows/wordpress-version-checker.yml
index 8237e75f3..055870155 100644
--- a/.github/workflows/wordpress-version-checker.yml
+++ b/.github/workflows/wordpress-version-checker.yml
@@ -23,6 +23,6 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: WordPress Version Checker
- uses: skaut/wordpress-version-checker@v2.1.0
+ uses: skaut/wordpress-version-checker@v2.2.1
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
diff --git a/.gitignore b/.gitignore
index f0e99a083..6aa213174 100644
--- a/.gitignore
+++ b/.gitignore
@@ -39,9 +39,11 @@ wp-core
.phpunit.result.cache
coverage.xml
.env
+.wp-env.override.json
# Playwright #
##########
+artifacts/
playwright-report/
test-results/
add-new-event.png
diff --git a/.nvmrc b/.nvmrc
index 9bcccb943..80a9956e1 100644
--- a/.nvmrc
+++ b/.nvmrc
@@ -1 +1 @@
-v20.13.1
+v20.16.0
diff --git a/.stylelintignore b/.stylelintignore
new file mode 100644
index 000000000..aa6f24936
--- /dev/null
+++ b/.stylelintignore
@@ -0,0 +1,7 @@
+node_modules
+build
+coverage
+playwright-report
+test-results
+vendor
+wp-core
diff --git a/.stylelintrc.js b/.stylelintrc.js
new file mode 100644
index 000000000..a04e05527
--- /dev/null
+++ b/.stylelintrc.js
@@ -0,0 +1,34 @@
+module.exports = {
+ extends: [
+ 'stylelint-config-standard',
+ 'stylelint-config-recommended',
+ 'stylelint-config-recommended-scss'
+ ],
+ plugins: ['stylelint-scss'],
+ ignoreFiles: [
+ 'node_modules/**/*',
+ 'build/**/*',
+ 'coverage/**/*',
+ 'playwright-report/**/*',
+ 'test-results/**/*',
+ 'vendor/**/*',
+ 'wp-core/**/*',
+ ],
+ rules: {
+ 'import-notation': null,
+ 'color-no-invalid-hex': true,
+ 'font-family-no-duplicate-names': true,
+ 'function-calc-no-unspaced-operator': true,
+ 'string-no-newline': true,
+ 'block-no-empty': null,
+ 'unit-no-unknown': true,
+ 'property-no-unknown': [true, {
+ ignoreProperties: ['/^--wp--preset--/']
+ }],
+ 'custom-property-pattern': null,
+ 'at-rule-no-unknown': null,
+ 'scss/at-rule-no-unknown': true,
+ 'no-descending-specificity': null,
+ 'selector-class-pattern': null,
+ },
+};
diff --git a/.typos.toml b/.typos.toml
new file mode 100644
index 000000000..fa2be1e09
--- /dev/null
+++ b/.typos.toml
@@ -0,0 +1,38 @@
+# Corrections take the form of a key/value pair. The key is the incorrect word
+# and the value is the correct word. If the key and value are the same, the
+# word is treated as always correct. If the value is an empty string, the word
+# is treated as always incorrect.
+
+[files]
+extend-exclude = [
+ ".git/",
+ "**/vendor/**",
+ "**/node_modules/**",
+ "build/**",
+ "docs/media/**",
+]
+ignore-hidden = false
+
+[default]
+locale = "en-us"
+extend-ignore-re = [
+ "\\biMatix\\b",
+ "\\bEvent Organiser\\b",
+]
+
+[default.extend-identifiers]
+# Typos
+"Github" = "GitHub"
+"Wordpress" = "WordPress"
+"Gatherpress" = "GatherPress"
+
+
+# Case sensitive, matches entire word.
+# [default.extend-identifiers]
+# anc_color = "anc_color"
+# rady = "rady"
+
+# Case insensitive, matches inside word.
+# [default.extend-words]
+# bellow = "below"
+# toi = "toi"
\ No newline at end of file
diff --git a/.wordpress-org/banner-1544x500.jpg b/.wordpress-org/banner-1544x500.jpg
index ca429a430..541beedc3 100644
Binary files a/.wordpress-org/banner-1544x500.jpg and b/.wordpress-org/banner-1544x500.jpg differ
diff --git a/.wordpress-org/banner-772x250.jpg b/.wordpress-org/banner-772x250.jpg
index 5fad0a835..7e57a66bf 100644
Binary files a/.wordpress-org/banner-772x250.jpg and b/.wordpress-org/banner-772x250.jpg differ
diff --git a/.wordpress-org/blueprints/blueprint.json b/.wordpress-org/blueprints/blueprint.json
new file mode 100644
index 000000000..404818d20
--- /dev/null
+++ b/.wordpress-org/blueprints/blueprint.json
@@ -0,0 +1,58 @@
+{
+ "$schema": "https://playground.wordpress.net/blueprint-schema.json",
+ "landingPage": "https://playground.wordpress.net/events",
+ "preferredVersions": {
+ "php": "8.2",
+ "wp": "latest"
+ },
+ "phpExtensionBundles": [
+ "kitchen-sink"
+ ],
+ "features": {
+ "networking": true
+ },
+ "steps": [
+ {
+ "step": "setSiteOptions",
+ "options": {
+ "blogname": "GatherPress",
+ "blogdescription": "Powering Communities with WordPress.",
+ "users_can_register": 1,
+ "permalink_structure": "/%year%/%monthnum%/%postname%/"
+ }
+ },
+ {
+ "step": "runPHP",
+ "code": "set_role('editor');"
+ },
+ {
+ "step": "login",
+ "username": "admin",
+ "password": "password"
+ },
+ {
+ "step": "updateUserMeta",
+ "meta": {
+ "admin_color": "modern"
+ },
+ "userId": 1
+ },
+ {
+ "step": "installPlugin",
+ "pluginZipFile": {
+ "resource": "wordpress.org\/plugins",
+ "slug": "gatherpress"
+ },
+ "options": {
+ "activate": true
+ }
+ },
+ {
+ "step": "importWxr",
+ "file": {
+ "resource": "url",
+ "url": "https://raw.githubusercontent.com/GatherPress/demo-data/main/GatherPress-demo-data-2024.xml"
+ }
+ }
+ ]
+}
diff --git a/.wordpress-org/icon-128x128.jpg b/.wordpress-org/icon-128x128.jpg
index f0a0541e6..9b3c2d6b0 100644
Binary files a/.wordpress-org/icon-128x128.jpg and b/.wordpress-org/icon-128x128.jpg differ
diff --git a/.wordpress-org/icon-128x128.png b/.wordpress-org/icon-128x128.png
index d6eec3f25..6b77f5a00 100644
Binary files a/.wordpress-org/icon-128x128.png and b/.wordpress-org/icon-128x128.png differ
diff --git a/.wordpress-org/icon-256x256.jpg b/.wordpress-org/icon-256x256.jpg
index dfa8f2b3c..92754235d 100644
Binary files a/.wordpress-org/icon-256x256.jpg and b/.wordpress-org/icon-256x256.jpg differ
diff --git a/.wordpress-org/icon-256x256.png b/.wordpress-org/icon-256x256.png
index c5b3f2e9d..f259fb683 100644
Binary files a/.wordpress-org/icon-256x256.png and b/.wordpress-org/icon-256x256.png differ
diff --git a/.wordpress-org/screenshot-1-de.png b/.wordpress-org/screenshot-1-de.png
new file mode 100644
index 000000000..13a9802e6
Binary files /dev/null and b/.wordpress-org/screenshot-1-de.png differ
diff --git a/.wordpress-org/screenshot-1-es.png b/.wordpress-org/screenshot-1-es.png
new file mode 100644
index 000000000..7cf46e855
Binary files /dev/null and b/.wordpress-org/screenshot-1-es.png differ
diff --git a/.wordpress-org/screenshot-1-fr.png b/.wordpress-org/screenshot-1-fr.png
new file mode 100644
index 000000000..e66b8b360
Binary files /dev/null and b/.wordpress-org/screenshot-1-fr.png differ
diff --git a/.wordpress-org/screenshot-1-it.png b/.wordpress-org/screenshot-1-it.png
new file mode 100644
index 000000000..7d33de074
Binary files /dev/null and b/.wordpress-org/screenshot-1-it.png differ
diff --git a/.wordpress-org/screenshot-1-mr.png b/.wordpress-org/screenshot-1-mr.png
new file mode 100644
index 000000000..8b85c7b2d
Binary files /dev/null and b/.wordpress-org/screenshot-1-mr.png differ
diff --git a/.wordpress-org/screenshot-1-nl.png b/.wordpress-org/screenshot-1-nl.png
new file mode 100644
index 000000000..cbe8df7a7
Binary files /dev/null and b/.wordpress-org/screenshot-1-nl.png differ
diff --git a/.wordpress-org/screenshot-1.png b/.wordpress-org/screenshot-1.png
new file mode 100644
index 000000000..3811b20f1
Binary files /dev/null and b/.wordpress-org/screenshot-1.png differ
diff --git a/.wordpress-org/screenshot-2-de.png b/.wordpress-org/screenshot-2-de.png
new file mode 100644
index 000000000..1f094e460
Binary files /dev/null and b/.wordpress-org/screenshot-2-de.png differ
diff --git a/.wordpress-org/screenshot-2-es.png b/.wordpress-org/screenshot-2-es.png
new file mode 100644
index 000000000..7b639a306
Binary files /dev/null and b/.wordpress-org/screenshot-2-es.png differ
diff --git a/.wordpress-org/screenshot-2-fr.png b/.wordpress-org/screenshot-2-fr.png
new file mode 100644
index 000000000..66a2b377e
Binary files /dev/null and b/.wordpress-org/screenshot-2-fr.png differ
diff --git a/.wordpress-org/screenshot-2-it.png b/.wordpress-org/screenshot-2-it.png
new file mode 100644
index 000000000..882614c88
Binary files /dev/null and b/.wordpress-org/screenshot-2-it.png differ
diff --git a/.wordpress-org/screenshot-2-mr.png b/.wordpress-org/screenshot-2-mr.png
new file mode 100644
index 000000000..da77d672d
Binary files /dev/null and b/.wordpress-org/screenshot-2-mr.png differ
diff --git a/.wordpress-org/screenshot-2-nl.png b/.wordpress-org/screenshot-2-nl.png
new file mode 100644
index 000000000..dce0f6d56
Binary files /dev/null and b/.wordpress-org/screenshot-2-nl.png differ
diff --git a/.wordpress-org/screenshot-2.png b/.wordpress-org/screenshot-2.png
new file mode 100644
index 000000000..a77544ddc
Binary files /dev/null and b/.wordpress-org/screenshot-2.png differ
diff --git a/.wordpress-org/screenshot-3-de.png b/.wordpress-org/screenshot-3-de.png
new file mode 100644
index 000000000..a9a4d4417
Binary files /dev/null and b/.wordpress-org/screenshot-3-de.png differ
diff --git a/.wordpress-org/screenshot-3-es.png b/.wordpress-org/screenshot-3-es.png
new file mode 100644
index 000000000..07ffdbfe7
Binary files /dev/null and b/.wordpress-org/screenshot-3-es.png differ
diff --git a/.wordpress-org/screenshot-3-fr.png b/.wordpress-org/screenshot-3-fr.png
new file mode 100644
index 000000000..b65531ec6
Binary files /dev/null and b/.wordpress-org/screenshot-3-fr.png differ
diff --git a/.wordpress-org/screenshot-3-it.png b/.wordpress-org/screenshot-3-it.png
new file mode 100644
index 000000000..34e15b973
Binary files /dev/null and b/.wordpress-org/screenshot-3-it.png differ
diff --git a/.wordpress-org/screenshot-3-mr.png b/.wordpress-org/screenshot-3-mr.png
new file mode 100644
index 000000000..0bfcac88e
Binary files /dev/null and b/.wordpress-org/screenshot-3-mr.png differ
diff --git a/.wordpress-org/screenshot-3-nl.png b/.wordpress-org/screenshot-3-nl.png
new file mode 100644
index 000000000..601e4d4c0
Binary files /dev/null and b/.wordpress-org/screenshot-3-nl.png differ
diff --git a/.wordpress-org/screenshot-3.png b/.wordpress-org/screenshot-3.png
new file mode 100644
index 000000000..f84c58a55
Binary files /dev/null and b/.wordpress-org/screenshot-3.png differ
diff --git a/.wordpress-org/screenshot-4-de.png b/.wordpress-org/screenshot-4-de.png
new file mode 100644
index 000000000..fb0b9d1f3
Binary files /dev/null and b/.wordpress-org/screenshot-4-de.png differ
diff --git a/.wordpress-org/screenshot-4-es.png b/.wordpress-org/screenshot-4-es.png
new file mode 100644
index 000000000..e0b98065e
Binary files /dev/null and b/.wordpress-org/screenshot-4-es.png differ
diff --git a/.wordpress-org/screenshot-4-fr.png b/.wordpress-org/screenshot-4-fr.png
new file mode 100644
index 000000000..b747929ea
Binary files /dev/null and b/.wordpress-org/screenshot-4-fr.png differ
diff --git a/.wordpress-org/screenshot-4-it.png b/.wordpress-org/screenshot-4-it.png
new file mode 100644
index 000000000..f228f4439
Binary files /dev/null and b/.wordpress-org/screenshot-4-it.png differ
diff --git a/.wordpress-org/screenshot-4-mr.png b/.wordpress-org/screenshot-4-mr.png
new file mode 100644
index 000000000..97e339dad
Binary files /dev/null and b/.wordpress-org/screenshot-4-mr.png differ
diff --git a/.wordpress-org/screenshot-4-nl.png b/.wordpress-org/screenshot-4-nl.png
new file mode 100644
index 000000000..54a1b8953
Binary files /dev/null and b/.wordpress-org/screenshot-4-nl.png differ
diff --git a/.wordpress-org/screenshot-4.png b/.wordpress-org/screenshot-4.png
new file mode 100644
index 000000000..0419b62d3
Binary files /dev/null and b/.wordpress-org/screenshot-4.png differ
diff --git a/.wp-env.json b/.wp-env.json
index 54dcdbdc0..7074e7a5c 100644
--- a/.wp-env.json
+++ b/.wp-env.json
@@ -4,15 +4,5 @@
],
"config": {
"WP_DEBUG_LOG": true
- },
- "mappings": {
- "wp-content/plugins": "./wp-core/plugins",
- "wp-content/themes": "./wp-core/themes"
- },
- "port": 2003,
- "env": {
- "tests": {
- "port": 2023
- }
}
}
diff --git a/build/272.js b/build/272.js
new file mode 100644
index 000000000..458d392fc
--- /dev/null
+++ b/build/272.js
@@ -0,0 +1 @@
+"use strict";(globalThis.webpackChunkgatherpress=globalThis.webpackChunkgatherpress||[]).push([[272],{1272:(s,e,a)=>{s.exports=a.p+"images/marker-icon-2x.png"}}]);
\ No newline at end of file
diff --git a/build/481.js b/build/481.js
new file mode 100644
index 000000000..cdd399f6b
--- /dev/null
+++ b/build/481.js
@@ -0,0 +1 @@
+(globalThis.webpackChunkgatherpress=globalThis.webpackChunkgatherpress||[]).push([[481],{3481:function(t,i){!function(t){"use strict";function i(t){var i,e,n,o;for(e=1,n=arguments.length;e{var r,l;const i={left:`${e}px`,top:`${t}px`,border:s},{x:c,y:a}=null!==(r=o.arrow)&&void 0!==r?r:{x:0,y:0},u=null!==(l={top:"bottom",right:"left",bottom:"top",left:"right"}[n.split("-")[0]])&&void 0!==l?l:"bottom",d=s&&{borderBottom:s,borderRight:s};let f=0;if(s){const e=`${s}`.match(/(\d+)px/);f=(null==e?void 0:e[1])?Number(e[1]):1}return{tooltipStyles:i,tooltipArrowStyles:{left:null!=c?`${c}px`:"",top:null!=a?`${a}px`:"",right:"",bottom:"",...d,[u]:`-${4+f}px`},place:n}}))):ue(e,t,{placement:"bottom",strategy:l,middleware:a}).then((({x:e,y:t,placement:n})=>({tooltipStyles:{left:`${e}px`,top:`${t}px`},tooltipArrowStyles:{},place:n})));var u},ve=(e,t)=>!("CSS"in window&&"supports"in window.CSS)||window.CSS.supports(e,t),he=(e,t,n)=>{let o=null;const r=function(...r){const l=()=>{o=null,n||e.apply(this,r)};n&&!o&&(e.apply(this,r),o=setTimeout(l,t)),n||(o&&clearTimeout(o),o=setTimeout(l,t))};return r.cancel=()=>{o&&(clearTimeout(o),o=null)},r},ye=e=>null!==e&&!Array.isArray(e)&&"object"==typeof e,ge=(e,t)=>{if(e===t)return!0;if(Array.isArray(e)&&Array.isArray(t))return e.length===t.length&&e.every(((e,n)=>ge(e,t[n])));if(Array.isArray(e)!==Array.isArray(t))return!1;if(!ye(e)||!ye(t))return e===t;const n=Object.keys(e),o=Object.keys(t);return n.length===o.length&&n.every((n=>ge(e[n],t[n])))},we=e=>{if(!(e instanceof HTMLElement||e instanceof SVGElement))return!1;const t=getComputedStyle(e);return["overflow","overflow-x","overflow-y"].some((e=>{const n=t.getPropertyValue(e);return"auto"===n||"scroll"===n}))},be=e=>{if(!e)return null;let t=e.parentElement;for(;t;){if(we(t))return t;t=t.parentElement}return document.scrollingElement||document.documentElement},xe="undefined"!=typeof window?s.useLayoutEffect:s.useEffect,_e=e=>{e.current&&(clearTimeout(e.current),e.current=null)},Ee={anchorRefs:new Set,activeAnchor:{current:null},attach:()=>{},detach:()=>{},setActiveAnchor:()=>{}},Se=(0,s.createContext)({getTooltipData:()=>Ee});function ke(e="DEFAULT_TOOLTIP_ID"){return(0,s.useContext)(Se).getTooltipData(e)}var Ae={tooltip:"core-styles-module_tooltip__3vRRp",fixed:"core-styles-module_fixed__pcSol",arrow:"core-styles-module_arrow__cvMwQ",noArrow:"core-styles-module_noArrow__xock6",clickable:"core-styles-module_clickable__ZuTTB",show:"core-styles-module_show__Nt9eE",closing:"core-styles-module_closing__sGnxF"},Oe={tooltip:"styles-module_tooltip__mnnfp",arrow:"styles-module_arrow__K0L3T",dark:"styles-module_dark__xNqje",light:"styles-module_light__Z6W-X",success:"styles-module_success__A2AKt",warning:"styles-module_warning__SCK0X",error:"styles-module_error__JvumD",info:"styles-module_info__BWdHW"};const Re=({forwardRef:e,id:t,className:n,classNameArrow:o,variant:r="dark",anchorId:l,anchorSelect:i,place:u="top",offset:f=10,events:p=["hover"],openOnClick:m=!1,positionStrategy:v="absolute",middlewares:h,wrapper:y,delayShow:g=0,delayHide:w=0,float:b=!1,hidden:x=!1,noArrow:_=!1,clickable:E=!1,closeOnEsc:S=!1,closeOnScroll:k=!1,closeOnResize:A=!1,openEvents:O,closeEvents:R,globalCloseEvents:T,imperativeModeOnly:L,style:j,position:D,afterShow:N,afterHide:P,content:I,contentWrapperRef:B,isOpen:$,defaultIsOpen:F=!1,setIsOpen:H,activeAnchor:z,setActiveAnchor:W,border:M,opacity:V,arrowColor:q,role:X="tooltip"})=>{var Y;const J=(0,s.useRef)(null),U=(0,s.useRef)(null),Q=(0,s.useRef)(null),ee=(0,s.useRef)(null),te=(0,s.useRef)(null),[ne,oe]=(0,s.useState)({tooltipStyles:{},tooltipArrowStyles:{},place:u}),[re,le]=(0,s.useState)(!1),[ie,se]=(0,s.useState)(!1),[ce,ae]=(0,s.useState)(null),ue=(0,s.useRef)(!1),fe=(0,s.useRef)(null),{anchorRefs:pe,setActiveAnchor:ve}=ke(t),ye=(0,s.useRef)(!1),[we,Ee]=(0,s.useState)([]),Se=(0,s.useRef)(!1),Re=m||p.includes("click"),Te=Re||(null==O?void 0:O.click)||(null==O?void 0:O.dblclick)||(null==O?void 0:O.mousedown),Le=O?{...O}:{mouseover:!0,focus:!0,mouseenter:!1,click:!1,dblclick:!1,mousedown:!1};!O&&Re&&Object.assign(Le,{mouseenter:!1,focus:!1,mouseover:!1,click:!0});const Ce=R?{...R}:{mouseout:!0,blur:!0,mouseleave:!1,click:!1,dblclick:!1,mouseup:!1};!R&&Re&&Object.assign(Ce,{mouseleave:!1,blur:!1,mouseout:!1});const je=T?{...T}:{escape:S||!1,scroll:k||!1,resize:A||!1,clickOutsideAnchor:Te||!1};L&&(Object.assign(Le,{mouseenter:!1,focus:!1,click:!1,dblclick:!1,mousedown:!1}),Object.assign(Ce,{mouseleave:!1,blur:!1,click:!1,dblclick:!1,mouseup:!1}),Object.assign(je,{escape:!1,scroll:!1,resize:!1,clickOutsideAnchor:!1})),xe((()=>(Se.current=!0,()=>{Se.current=!1})),[]);const De=e=>{Se.current&&(e&&se(!0),setTimeout((()=>{Se.current&&(null==H||H(e),void 0===$&&le(e))}),10))};(0,s.useEffect)((()=>{if(void 0===$)return()=>null;$&&se(!0);const e=setTimeout((()=>{le($)}),10);return()=>{clearTimeout(e)}}),[$]),(0,s.useEffect)((()=>{if(re!==ue.current)if(_e(te),ue.current=re,re)null==N||N();else{const e=(()=>{const e=getComputedStyle(document.body).getPropertyValue("--rt-transition-show-delay").match(/^([\d.]+)(ms|s)$/);if(!e)return 0;const[,t,n]=e;return Number(t)*("ms"===n?1:1e3)})();te.current=setTimeout((()=>{se(!1),ae(null),null==P||P()}),e+25)}}),[re]);const Ne=e=>{oe((t=>ge(t,e)?t:e))},Pe=(e=g)=>{_e(Q),ie?De(!0):Q.current=setTimeout((()=>{De(!0)}),e)},Ie=(e=w)=>{_e(ee),ee.current=setTimeout((()=>{ye.current||De(!1)}),e)},Be=e=>{var t;if(!e)return;const n=null!==(t=e.currentTarget)&&void 0!==t?t:e.target;if(!(null==n?void 0:n.isConnected))return W(null),void ve({current:null});g?Pe():De(!0),W(n),ve({current:n}),_e(ee)},$e=()=>{E?Ie(w||100):w?Ie():De(!1),_e(Q)},Fe=({x:e,y:t})=>{var n;const o={getBoundingClientRect:()=>({x:e,y:t,width:0,height:0,top:t,left:e,right:e,bottom:t})};me({place:null!==(n=null==ce?void 0:ce.place)&&void 0!==n?n:u,offset:f,elementReference:o,tooltipReference:J.current,tooltipArrowReference:U.current,strategy:v,middlewares:h,border:M}).then((e=>{Ne(e)}))},He=e=>{if(!e)return;const t=e,n={x:t.clientX,y:t.clientY};Fe(n),fe.current=n},ze=e=>{var t;if(!re)return;const n=e.target;n.isConnected&&((null===(t=J.current)||void 0===t?void 0:t.contains(n))||[document.querySelector(`[id='${l}']`),...we].some((e=>null==e?void 0:e.contains(n)))||(De(!1),_e(Q)))},We=he(Be,50,!0),Me=he($e,50,!0),Ve=e=>{Me.cancel(),We(e)},qe=()=>{We.cancel(),Me()},Ke=(0,s.useCallback)((()=>{var e,t;const n=null!==(e=null==ce?void 0:ce.position)&&void 0!==e?e:D;n?Fe(n):b?fe.current&&Fe(fe.current):(null==z?void 0:z.isConnected)&&me({place:null!==(t=null==ce?void 0:ce.place)&&void 0!==t?t:u,offset:f,elementReference:z,tooltipReference:J.current,tooltipArrowReference:U.current,strategy:v,middlewares:h,border:M}).then((e=>{Se.current&&Ne(e)}))}),[re,z,I,j,u,null==ce?void 0:ce.place,f,v,D,null==ce?void 0:ce.position,b]);(0,s.useEffect)((()=>{var e,t;const n=new Set(pe);we.forEach((e=>{n.add({current:e})}));const o=document.querySelector(`[id='${l}']`);o&&n.add({current:o});const r=()=>{De(!1)},i=be(z),s=be(J.current);je.scroll&&(window.addEventListener("scroll",r),null==i||i.addEventListener("scroll",r),null==s||s.addEventListener("scroll",r));let u=null;je.resize?window.addEventListener("resize",r):z&&J.current&&(u=function(e,t,n,o){void 0===o&&(o={});const{ancestorScroll:r=!0,ancestorResize:l=!0,elementResize:i="function"==typeof ResizeObserver,layoutShift:s="function"==typeof IntersectionObserver,animationFrame:u=!1}=o,f=G(e),p=r||l?[...f?K(f):[],...K(t)]:[];p.forEach((e=>{r&&e.addEventListener("scroll",n,{passive:!0}),l&&e.addEventListener("resize",n)}));const m=f&&s?function(e,t){let n,o=null;const r=C(e);function l(){var e;clearTimeout(n),null==(e=o)||e.disconnect(),o=null}return function i(s,u){void 0===s&&(s=!1),void 0===u&&(u=1),l();const{left:f,top:p,width:m,height:v}=e.getBoundingClientRect();if(s||t(),!m||!v)return;const h={rootMargin:-d(p)+"px "+-d(r.clientWidth-(f+m))+"px "+-d(r.clientHeight-(p+v))+"px "+-d(f)+"px",threshold:a(0,c(1,u))||1};let y=!0;function g(e){const t=e[0].intersectionRatio;if(t!==u){if(!y)return i();t?i(!1,t):n=setTimeout((()=>{i(!1,1e-7)}),1e3)}y=!1}try{o=new IntersectionObserver(g,{...h,root:r.ownerDocument})}catch(e){o=new IntersectionObserver(g,h)}o.observe(e)}(!0),l}(f,n):null;let v,h=-1,y=null;i&&(y=new ResizeObserver((e=>{let[o]=e;o&&o.target===f&&y&&(y.unobserve(t),cancelAnimationFrame(h),h=requestAnimationFrame((()=>{var e;null==(e=y)||e.observe(t)}))),n()})),f&&!u&&y.observe(f),y.observe(t));let g=u?Z(e):null;return u&&function t(){const o=Z(e);!g||o.x===g.x&&o.y===g.y&&o.width===g.width&&o.height===g.height||n(),g=o,v=requestAnimationFrame(t)}(),n(),()=>{var e;p.forEach((e=>{r&&e.removeEventListener("scroll",n),l&&e.removeEventListener("resize",n)})),null==m||m(),null==(e=y)||e.disconnect(),y=null,u&&cancelAnimationFrame(v)}}(z,J.current,Ke,{ancestorResize:!0,elementResize:!0,layoutShift:!0}));const f=e=>{"Escape"===e.key&&De(!1)};je.escape&&window.addEventListener("keydown",f),je.clickOutsideAnchor&&window.addEventListener("click",ze);const p=[],m=e=>{re&&(null==e?void 0:e.target)===z||Be(e)},v=e=>{re&&(null==e?void 0:e.target)===z&&$e()},h=["mouseover","mouseout","mouseenter","mouseleave","focus","blur"],y=["click","dblclick","mousedown","mouseup"];Object.entries(Le).forEach((([e,t])=>{t&&(h.includes(e)?p.push({event:e,listener:Ve}):y.includes(e)&&p.push({event:e,listener:m}))})),Object.entries(Ce).forEach((([e,t])=>{t&&(h.includes(e)?p.push({event:e,listener:qe}):y.includes(e)&&p.push({event:e,listener:v}))})),b&&p.push({event:"pointermove",listener:He});const g=()=>{ye.current=!0},w=()=>{ye.current=!1,$e()};return E&&!Te&&(null===(e=J.current)||void 0===e||e.addEventListener("mouseenter",g),null===(t=J.current)||void 0===t||t.addEventListener("mouseleave",w)),p.forEach((({event:e,listener:t})=>{n.forEach((n=>{var o;null===(o=n.current)||void 0===o||o.addEventListener(e,t)}))})),()=>{var e,t;je.scroll&&(window.removeEventListener("scroll",r),null==i||i.removeEventListener("scroll",r),null==s||s.removeEventListener("scroll",r)),je.resize?window.removeEventListener("resize",r):null==u||u(),je.clickOutsideAnchor&&window.removeEventListener("click",ze),je.escape&&window.removeEventListener("keydown",f),E&&!Te&&(null===(e=J.current)||void 0===e||e.removeEventListener("mouseenter",g),null===(t=J.current)||void 0===t||t.removeEventListener("mouseleave",w)),p.forEach((({event:e,listener:t})=>{n.forEach((n=>{var o;null===(o=n.current)||void 0===o||o.removeEventListener(e,t)}))}))}}),[z,Ke,ie,pe,we,O,R,T,Re,g,w]),(0,s.useEffect)((()=>{var e,n;let o=null!==(n=null!==(e=null==ce?void 0:ce.anchorSelect)&&void 0!==e?e:i)&&void 0!==n?n:"";!o&&t&&(o=`[data-tooltip-id='${t.replace(/'/g,"\\'")}']`);const r=new MutationObserver((e=>{const n=[],r=[];e.forEach((e=>{if("attributes"===e.type&&"data-tooltip-id"===e.attributeName&&(e.target.getAttribute("data-tooltip-id")===t?n.push(e.target):e.oldValue===t&&r.push(e.target)),"childList"===e.type){if(z){const t=[...e.removedNodes].filter((e=>1===e.nodeType));if(o)try{r.push(...t.filter((e=>e.matches(o)))),r.push(...t.flatMap((e=>[...e.querySelectorAll(o)])))}catch(e){}t.some((e=>{var t;return!!(null===(t=null==e?void 0:e.contains)||void 0===t?void 0:t.call(e,z))&&(se(!1),De(!1),W(null),_e(Q),_e(ee),!0)}))}if(o)try{const t=[...e.addedNodes].filter((e=>1===e.nodeType));n.push(...t.filter((e=>e.matches(o)))),n.push(...t.flatMap((e=>[...e.querySelectorAll(o)])))}catch(e){}}})),(n.length||r.length)&&Ee((e=>[...e.filter((e=>!r.includes(e))),...n]))}));return r.observe(document.body,{childList:!0,subtree:!0,attributes:!0,attributeFilter:["data-tooltip-id"],attributeOldValue:!0}),()=>{r.disconnect()}}),[t,i,null==ce?void 0:ce.anchorSelect,z]),(0,s.useEffect)((()=>{Ke()}),[Ke]),(0,s.useEffect)((()=>{if(!(null==B?void 0:B.current))return()=>null;const e=new ResizeObserver((()=>{setTimeout((()=>Ke()))}));return e.observe(B.current),()=>{e.disconnect()}}),[I,null==B?void 0:B.current]),(0,s.useEffect)((()=>{var e;const t=document.querySelector(`[id='${l}']`),n=[...we,t];z&&n.includes(z)||W(null!==(e=we[0])&&void 0!==e?e:t)}),[l,we,z]),(0,s.useEffect)((()=>(F&&De(!0),()=>{_e(Q),_e(ee)})),[]),(0,s.useEffect)((()=>{var e;let n=null!==(e=null==ce?void 0:ce.anchorSelect)&&void 0!==e?e:i;if(!n&&t&&(n=`[data-tooltip-id='${t.replace(/'/g,"\\'")}']`),n)try{const e=Array.from(document.querySelectorAll(n));Ee(e)}catch(e){Ee([])}}),[t,i,null==ce?void 0:ce.anchorSelect]),(0,s.useEffect)((()=>{Q.current&&(_e(Q),Pe(g))}),[g]);const Xe=null!==(Y=null==ce?void 0:ce.content)&&void 0!==Y?Y:I,Ge=re&&Object.keys(ne.tooltipStyles).length>0;return(0,s.useImperativeHandle)(e,(()=>({open:e=>{if(null==e?void 0:e.anchorSelect)try{document.querySelector(e.anchorSelect)}catch(t){return void console.warn(`[react-tooltip] "${e.anchorSelect}" is not a valid CSS selector`)}ae(null!=e?e:null),(null==e?void 0:e.delay)?Pe(e.delay):De(!0)},close:e=>{(null==e?void 0:e.delay)?Ie(e.delay):De(!1)},activeAnchor:z,place:ne.place,isOpen:Boolean(ie&&!x&&Xe&&Ge)}))),ie&&!x&&Xe?s.createElement(y,{id:t,role:X,className:de("react-tooltip",Ae.tooltip,Oe.tooltip,Oe[r],n,`react-tooltip__place-${ne.place}`,Ae[Ge?"show":"closing"],Ge?"react-tooltip__show":"react-tooltip__closing","fixed"===v&&Ae.fixed,E&&Ae.clickable),onTransitionEnd:e=>{_e(te),re||"opacity"!==e.propertyName||(se(!1),ae(null),null==P||P())},style:{...j,...ne.tooltipStyles,opacity:void 0!==V&&Ge?V:void 0},ref:J},Xe,s.createElement(y,{className:de("react-tooltip-arrow",Ae.arrow,Oe.arrow,o,_&&Ae.noArrow),style:{...ne.tooltipArrowStyles,background:q?`linear-gradient(to right bottom, transparent 50%, ${q} 50%)`:void 0},ref:U})):null},Te=({content:e})=>s.createElement("span",{dangerouslySetInnerHTML:{__html:e}}),Le=s.forwardRef((({id:e,anchorId:t,anchorSelect:n,content:o,html:r,render:l,className:i,classNameArrow:c,variant:a="dark",place:u="top",offset:d=10,wrapper:f="div",children:p=null,events:m=["hover"],openOnClick:v=!1,positionStrategy:h="absolute",middlewares:y,delayShow:g=0,delayHide:w=0,float:b=!1,hidden:x=!1,noArrow:_=!1,clickable:E=!1,closeOnEsc:S=!1,closeOnScroll:k=!1,closeOnResize:A=!1,openEvents:O,closeEvents:R,globalCloseEvents:T,imperativeModeOnly:L=!1,style:C,position:j,isOpen:D,defaultIsOpen:N=!1,disableStyleInjection:P=!1,border:I,opacity:B,arrowColor:$,setIsOpen:F,afterShow:H,afterHide:z,role:W="tooltip"},M)=>{const[V,q]=(0,s.useState)(o),[K,X]=(0,s.useState)(r),[G,Y]=(0,s.useState)(u),[J,U]=(0,s.useState)(a),[Z,Q]=(0,s.useState)(d),[ee,te]=(0,s.useState)(g),[ne,oe]=(0,s.useState)(w),[re,le]=(0,s.useState)(b),[ie,se]=(0,s.useState)(x),[ce,ae]=(0,s.useState)(f),[ue,fe]=(0,s.useState)(m),[pe,me]=(0,s.useState)(h),[he,ye]=(0,s.useState)(null),[ge,we]=(0,s.useState)(null),be=(0,s.useRef)(P),{anchorRefs:xe,activeAnchor:_e}=ke(e),Ee=e=>null==e?void 0:e.getAttributeNames().reduce(((t,n)=>{var o;return n.startsWith("data-tooltip-")&&(t[n.replace(/^data-tooltip-/,"")]=null!==(o=null==e?void 0:e.getAttribute(n))&&void 0!==o?o:null),t}),{}),Se=e=>{const t={place:e=>{var t;Y(null!==(t=e)&&void 0!==t?t:u)},content:e=>{q(null!=e?e:o)},html:e=>{X(null!=e?e:r)},variant:e=>{var t;U(null!==(t=e)&&void 0!==t?t:a)},offset:e=>{Q(null===e?d:Number(e))},wrapper:e=>{var t;ae(null!==(t=e)&&void 0!==t?t:f)},events:e=>{const t=null==e?void 0:e.split(" ");fe(null!=t?t:m)},"position-strategy":e=>{var t;me(null!==(t=e)&&void 0!==t?t:h)},"delay-show":e=>{te(null===e?g:Number(e))},"delay-hide":e=>{oe(null===e?w:Number(e))},float:e=>{le(null===e?b:"true"===e)},hidden:e=>{se(null===e?x:"true"===e)},"class-name":e=>{ye(e)}};Object.values(t).forEach((e=>e(null))),Object.entries(e).forEach((([e,n])=>{var o;null===(o=t[e])||void 0===o||o.call(t,n)}))};(0,s.useEffect)((()=>{q(o)}),[o]),(0,s.useEffect)((()=>{X(r)}),[r]),(0,s.useEffect)((()=>{Y(u)}),[u]),(0,s.useEffect)((()=>{U(a)}),[a]),(0,s.useEffect)((()=>{Q(d)}),[d]),(0,s.useEffect)((()=>{te(g)}),[g]),(0,s.useEffect)((()=>{oe(w)}),[w]),(0,s.useEffect)((()=>{le(b)}),[b]),(0,s.useEffect)((()=>{se(x)}),[x]),(0,s.useEffect)((()=>{me(h)}),[h]),(0,s.useEffect)((()=>{be.current!==P&&console.warn("[react-tooltip] Do not change `disableStyleInjection` dynamically.")}),[P]),(0,s.useEffect)((()=>{"undefined"!=typeof window&&window.dispatchEvent(new CustomEvent("react-tooltip-inject-styles",{detail:{disableCore:"core"===P,disableBase:P}}))}),[]),(0,s.useEffect)((()=>{var o;const r=new Set(xe);let l=n;if(!l&&e&&(l=`[data-tooltip-id='${e.replace(/'/g,"\\'")}']`),l)try{document.querySelectorAll(l).forEach((e=>{r.add({current:e})}))}catch(o){console.warn(`[react-tooltip] "${l}" is not a valid CSS selector`)}const i=document.querySelector(`[id='${t}']`);if(i&&r.add({current:i}),!r.size)return()=>null;const s=null!==(o=null!=ge?ge:i)&&void 0!==o?o:_e.current,c=new MutationObserver((e=>{e.forEach((e=>{var t;if(!s||"attributes"!==e.type||!(null===(t=e.attributeName)||void 0===t?void 0:t.startsWith("data-tooltip-")))return;const n=Ee(s);Se(n)}))})),a={attributes:!0,childList:!1,subtree:!1};if(s){const e=Ee(s);Se(e),c.observe(s,a)}return()=>{c.disconnect()}}),[xe,_e,ge,t,n]),(0,s.useEffect)((()=>{(null==C?void 0:C.border)&&console.warn("[react-tooltip] Do not set `style.border`. Use `border` prop instead."),I&&!ve("border",`${I}`)&&console.warn(`[react-tooltip] "${I}" is not a valid \`border\`.`),(null==C?void 0:C.opacity)&&console.warn("[react-tooltip] Do not set `style.opacity`. Use `opacity` prop instead."),B&&!ve("opacity",`${B}`)&&console.warn(`[react-tooltip] "${B}" is not a valid \`opacity\`.`)}),[]);let Ae=p;const Oe=(0,s.useRef)(null);if(l){const e=l({content:(null==ge?void 0:ge.getAttribute("data-tooltip-content"))||V||null,activeAnchor:ge});Ae=e?s.createElement("div",{ref:Oe,className:"react-tooltip-content-wrapper"},e):null}else V&&(Ae=V);K&&(Ae=s.createElement(Te,{content:K}));const Le={forwardRef:M,id:e,anchorId:t,anchorSelect:n,className:de(i,he),classNameArrow:c,content:Ae,contentWrapperRef:Oe,place:G,variant:J,offset:Z,wrapper:ce,events:ue,openOnClick:v,positionStrategy:pe,middlewares:y,delayShow:ee,delayHide:ne,float:re,hidden:ie,noArrow:_,clickable:E,closeOnEsc:S,closeOnScroll:k,closeOnResize:A,openEvents:O,closeEvents:R,globalCloseEvents:T,imperativeModeOnly:L,style:C,position:j,isOpen:D,defaultIsOpen:N,border:I,opacity:B,arrowColor:$,setIsOpen:F,afterShow:H,afterHide:z,activeAnchor:ge,setActiveAnchor:e=>we(e),role:W};return s.createElement(Re,{...Le})}));"undefined"!=typeof window&&window.addEventListener("react-tooltip-inject-styles",(e=>{e.detail.disableCore||pe({css:":root{--rt-color-white:#fff;--rt-color-dark:#222;--rt-color-success:#8dc572;--rt-color-error:#be6464;--rt-color-warning:#f0ad4e;--rt-color-info:#337ab7;--rt-opacity:0.9;--rt-transition-show-delay:0.15s;--rt-transition-closing-delay:0.15s}.core-styles-module_tooltip__3vRRp{position:absolute;top:0;left:0;pointer-events:none;opacity:0;will-change:opacity}.core-styles-module_fixed__pcSol{position:fixed}.core-styles-module_arrow__cvMwQ{position:absolute;background:inherit}.core-styles-module_noArrow__xock6{display:none}.core-styles-module_clickable__ZuTTB{pointer-events:auto}.core-styles-module_show__Nt9eE{opacity:var(--rt-opacity);transition:opacity var(--rt-transition-show-delay)ease-out}.core-styles-module_closing__sGnxF{opacity:0;transition:opacity var(--rt-transition-closing-delay)ease-in}",type:"core"}),e.detail.disableBase||pe({css:"\n.styles-module_tooltip__mnnfp{padding:8px 16px;border-radius:3px;font-size:90%;width:max-content}.styles-module_arrow__K0L3T{width:8px;height:8px}[class*='react-tooltip__place-top']>.styles-module_arrow__K0L3T{transform:rotate(45deg)}[class*='react-tooltip__place-right']>.styles-module_arrow__K0L3T{transform:rotate(135deg)}[class*='react-tooltip__place-bottom']>.styles-module_arrow__K0L3T{transform:rotate(225deg)}[class*='react-tooltip__place-left']>.styles-module_arrow__K0L3T{transform:rotate(315deg)}.styles-module_dark__xNqje{background:var(--rt-color-dark);color:var(--rt-color-white)}.styles-module_light__Z6W-X{background-color:var(--rt-color-white);color:var(--rt-color-dark)}.styles-module_success__A2AKt{background-color:var(--rt-color-success);color:var(--rt-color-white)}.styles-module_warning__SCK0X{background-color:var(--rt-color-warning);color:var(--rt-color-white)}.styles-module_error__JvumD{background-color:var(--rt-color-error);color:var(--rt-color-white)}.styles-module_info__BWdHW{background-color:var(--rt-color-info);color:var(--rt-color-white)}",type:"base"})}));const Ce=window.wp.i18n,je=window.wp.element,De=(e,t="")=>{for(const[n,o]of Object.entries(e)){let e=n;t&&(e+="_"+String(t)),addEventListener(e,(e=>{o(e.detail)}),!1)}};function Ne(e){if("object"==typeof GatherPress)return e.split(".").reduce(((e,t)=>e&&e[t]),GatherPress)}const Pe=window.ReactJSXRuntime,Ie=({onlineEventLinkDefault:e=""})=>{const t=(0,Ce.__)("Online event","gatherpress"),[n,o]=(0,je.useState)(e);return De({setOnlineEventLink:o},Ne("eventDetails.postId")),(0,Pe.jsxs)(l.Flex,{justify:"normal",gap:"3",children:[(0,Pe.jsx)(l.FlexItem,{display:"flex",children:(0,Pe.jsx)(l.Icon,{icon:"video-alt2"})}),(0,Pe.jsxs)(l.FlexItem,{children:[!n&&(0,Pe.jsxs)(Pe.Fragment,{children:[(0,Pe.jsx)("span",{tabIndex:"0",className:"gatherpress-tooltip","data-tooltip-id":"gatherpress-online-event-tooltip","data-tooltip-content":(0,Ce.__)("Link available for attendees only.","gatherpress"),children:t}),(0,Pe.jsx)(Le,{id:"gatherpress-online-event-tooltip"})]}),n&&(0,Pe.jsx)("a",{href:n,rel:"noreferrer",target:"_blank",children:t})]})]})},Be=()=>{const{editPost:e,unlockPostSaving:t}=(0,i.useDispatch)("core/editor"),n=(0,i.useSelect)((e=>e("core/editor").getEditedPostAttribute("meta").gatherpress_online_event_link)),[o,r]=(0,je.useState)(n);return De({setOnlineEventLink:r},Ne("eventDetails.postId")),(0,Pe.jsx)(l.TextControl,{label:(0,Ce.__)("Online event link","gatherpress"),value:o,placeholder:(0,Ce.__)("Add link to online event","gatherpress"),onChange:n=>{(n=>{e({meta:{gatherpress_online_event_link:n}}),r(n),((e,t="")=>{for(const[n,o]of Object.entries(e)){let e=n;t&&(e+="_"+String(t));const r=new CustomEvent(e,{detail:o});dispatchEvent(r)}})({setOnlineEventLink:n},Ne("eventDetails.postId")),t()})(n)}})},$e=e=>{const{isSelected:t}=e,n=t?"none":"block";return(0,Pe.jsxs)("div",{style:{position:"relative"},children:[e.children,(0,Pe.jsx)("div",{style:{position:"absolute",top:"0",right:"0",bottom:"0",left:"0",display:n}})]})},Fe=JSON.parse('{"$schema":"https://schemas.wp.org/trunk/block.json","apiVersion":2,"name":"gatherpress/online-event","version":"1.0.1","title":"Online Event","category":"gatherpress","icon":"video-alt2","example":{},"description":"Utilized for virtual events, offering the capability to share a direct link to an event.","attributes":{"blockId":{"type":"string"}},"supports":{"html":false},"textdomain":"gatherpress","editorScript":"file:./index.js","style":"file:./style-index.css","viewScript":"file:./online-event.js","render":"file:./render.php"}');(0,o.registerBlockType)(Fe,{edit:({isSelected:e})=>{const t=(0,r.useBlockProps)(),n=(0,i.useSelect)((e=>e("core/editor")?.getEditedPostAttribute("meta")?.gatherpress_online_event_link));return(0,Pe.jsxs)(Pe.Fragment,{children:["string"==typeof(0,i.select)("core/editor")?.getCurrentPostType()&&(0,Pe.jsx)(r.InspectorControls,{children:(0,Pe.jsx)(l.PanelBody,{children:(0,Pe.jsx)(l.PanelRow,{children:(0,Pe.jsx)(Be,{})})})}),(0,Pe.jsx)("div",{...t,children:(0,Pe.jsx)($e,{isSelected:e,children:(0,Pe.jsx)(Ie,{onlineEventLinkDefault:n})})})]})},save:()=>null})},6942:(e,t)=>{var n;!function(){"use strict";var o={}.hasOwnProperty;function r(){for(var e="",t=0;t {const{isSelected:t}=e,n=t?"none":"block";return(0,Fe.jsxs)("div",{style:{position:"relative"},children:[e.children,(0,Fe.jsx)("div",{style:{position:"absolute",top:"0",right:"0",bottom:"0",left:"0",display:n}})]})},Ve=JSON.parse('{"$schema":"https://schemas.wp.org/trunk/block.json","apiVersion":2,"name":"gatherpress/rsvp","version":"1.0.1","title":"RSVP","category":"gatherpress","icon":"insert","example":{},"description":"Enables members to easily confirm their attendance for an event.","attributes":{"content":{"type":"string"},"color":{"type":"string"}},"supports":{"html":false},"textdomain":"gatherpress","editorScript":"file:./index.js","style":"file:./style-index.css","viewScript":"file:./rsvp.js","render":"file:./render.php"}');(0,o.registerBlockType)(Ve,{edit:()=>{const e=(0,r.useBlockProps)(),t=He("eventDetails.postId"),n=He("eventDetails.currentUser");return(0,Fe.jsx)("div",{...e,children:(0,Fe.jsx)(We,{children:(0,Fe.jsx)(Ue,{postId:t,currentUser:n,type:"upcoming"})})})},save:()=>null})},5413:(e,t)=>{"use strict";var n;Object.defineProperty(t,"__esModule",{value:!0}),t.Doctype=t.CDATA=t.Tag=t.Style=t.Script=t.Comment=t.Directive=t.Text=t.Root=t.isTag=t.ElementType=void 0,function(e){e.Root="root",e.Text="text",e.Directive="directive",e.Comment="comment",e.Script="script",e.Style="style",e.Tag="tag",e.CDATA="cdata",e.Doctype="doctype"}(n=t.ElementType||(t.ElementType={})),t.isTag=function(e){return e.type===n.Tag||e.type===n.Script||e.type===n.Style},t.Root=n.Root,t.Text=n.Text,t.Directive=n.Directive,t.Comment=n.Comment,t.Script=n.Script,t.Style=n.Style,t.Tag=n.Tag,t.CDATA=n.CDATA,t.Doctype=n.Doctype},1141:function(e,t,n){"use strict";var o=this&&this.__createBinding||(Object.create?function(e,t,n,o){void 0===o&&(o=n);var r=Object.getOwnPropertyDescriptor(t,n);r&&!("get"in r?!t.__esModule:r.writable||r.configurable)||(r={enumerable:!0,get:function(){return t[n]}}),Object.defineProperty(e,o,r)}:function(e,t,n,o){void 0===o&&(o=n),e[o]=t[n]}),r=this&&this.__exportStar||function(e,t){for(var n in e)"default"===n||Object.prototype.hasOwnProperty.call(t,n)||o(t,e,n)};Object.defineProperty(t,"__esModule",{value:!0}),t.DomHandler=void 0;var i=n(5413),s=n(6957);r(n(6957),t);var l={withStartIndices:!1,withEndIndices:!1,xmlMode:!1},a=function(){function e(e,t,n){this.dom=[],this.root=new s.Document(this.dom),this.done=!1,this.tagStack=[this.root],this.lastNode=null,this.parser=null,"function"==typeof t&&(n=t,t=l),"object"==typeof e&&(t=e,e=void 0),this.callback=null!=e?e:null,this.options=null!=t?t:l,this.elementCB=null!=n?n:null}return e.prototype.onparserinit=function(e){this.parser=e},e.prototype.onreset=function(){this.dom=[],this.root=new s.Document(this.dom),this.done=!1,this.tagStack=[this.root],this.lastNode=null,this.parser=null},e.prototype.onend=function(){this.done||(this.done=!0,this.parser=null,this.handleCallback(null))},e.prototype.onerror=function(e){this.handleCallback(e)},e.prototype.onclosetag=function(){this.lastNode=null;var e=this.tagStack.pop();this.options.withEndIndices&&(e.endIndex=this.parser.endIndex),this.elementCB&&this.elementCB(e)},e.prototype.onopentag=function(e,t){var n=this.options.xmlMode?i.ElementType.Tag:void 0,o=new s.Element(e,t,void 0,n);this.addNode(o),this.tagStack.push(o)},e.prototype.ontext=function(e){var t=this.lastNode;if(t&&t.type===i.ElementType.Text)t.data+=e,this.options.withEndIndices&&(t.endIndex=this.parser.endIndex);else{var n=new s.Text(e);this.addNode(n),this.lastNode=n}},e.prototype.oncomment=function(e){if(this.lastNode&&this.lastNode.type===i.ElementType.Comment)this.lastNode.data+=e;else{var t=new s.Comment(e);this.addNode(t),this.lastNode=t}},e.prototype.oncommentend=function(){this.lastNode=null},e.prototype.oncdatastart=function(){var e=new s.Text(""),t=new s.CDATA([e]);this.addNode(t),e.parent=t,this.lastNode=e},e.prototype.oncdataend=function(){this.lastNode=null},e.prototype.onprocessinginstruction=function(e,t){var n=new s.ProcessingInstruction(e,t);this.addNode(n)},e.prototype.handleCallback=function(e){if("function"==typeof this.callback)this.callback(e,this.dom);else if(e)throw e},e.prototype.addNode=function(e){var t=this.tagStack[this.tagStack.length-1],n=t.children[t.children.length-1];this.options.withStartIndices&&(e.startIndex=this.parser.startIndex),this.options.withEndIndices&&(e.endIndex=this.parser.endIndex),t.children.push(e),n&&(e.prev=n,n.next=e),e.parent=t,this.lastNode=null},e}();t.DomHandler=a,t.default=a},6957:function(e,t,n){"use strict";var o,r=this&&this.__extends||(o=function(e,t){return o=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n])},o(e,t)},function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Class extends value "+String(t)+" is not a constructor or null");function __(){this.constructor=e}o(e,t),e.prototype=null===t?Object.create(t):(__.prototype=t.prototype,new __)}),i=this&&this.__assign||function(){return i=Object.assign||function(e){for(var t,n=1,o=arguments.length;n
+
+
+
+ download and install GatherPress Alpha to ensure compatibility and avoid issues.',
+ 'gatherpress'
+ )
+ );
+ ?>
+ 0&&e[u-1][2]>i;u--)e[u]=e[u-1];e[u]=[n,r,i]},o.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return o.d(t,{a:t}),t},o.d=(e,t)=>{for(var n in t)o.o(t,n)&&!o.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},o.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),o.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},(()=>{var e={662:0,394:0};o.O.j=t=>0===e[t];var t=(t,n)=>{var r,i,[s,l,a]=n,c=0;if(s.some((t=>0!==e[t]))){for(r in l)o.o(l,r)&&(o.m[r]=l[r]);if(a)var u=a(o)}for(t&&t(n);c0&&r[p-1][2]>n;p--)r[p]=r[p-1];r[p]=[o,a,n]},t.o=(r,e)=>Object.prototype.hasOwnProperty.call(r,e),(()=>{var r={604:0,739:0};t.O.j=e=>0===r[e];var e=(e,o)=>{var a,n,[s,i,l]=o,v=0;if(s.some((e=>0!==r[e]))){for(a in i)t.o(i,a)&&(t.m[a]=i[a]);if(l)var p=l(t)}for(e&&e(o);v0&&r[p-1][2]>n;p--)r[p]=r[p-1];r[p]=[o,a,n]},t.o=(r,e)=>Object.prototype.hasOwnProperty.call(r,e),(()=>{var r={604:0,739:0};t.O.j=e=>0===r[e];var e=(e,o)=>{var a,n,[s,i,l]=o,v=0;if(s.some((e=>0!==r[e]))){for(a in i)t.o(i,a)&&(t.m[a]=i[a]);if(l)var p=l(t)}for(e&&e(o);v0&&r[p-1][2]>n;p--)r[p]=r[p-1];r[p]=[o,a,n]},t.o=(r,e)=>Object.prototype.hasOwnProperty.call(r,e),(()=>{var r={506:0,835:0};t.O.j=e=>0===r[e];var e=(e,o)=>{var a,n,[s,i,l]=o,v=0;if(s.some((e=>0!==r[e]))){for(a in i)t.o(i,a)&&(t.m[a]=i[a]);if(l)var p=l(t)}for(e&&e(o);v0&&r[p-1][2]>n;p--)r[p]=r[p-1];r[p]=[o,a,n]},t.o=(r,e)=>Object.prototype.hasOwnProperty.call(r,e),(()=>{var r={506:0,835:0};t.O.j=e=>0===r[e];var e=(e,o)=>{var a,n,[s,i,l]=o,v=0;if(s.some((e=>0!==r[e]))){for(a in i)t.o(i,a)&&(t.m[a]=i[a]);if(l)var p=l(t)}for(e&&e(o);v
+
+
+
+
+
+
+
+
+ ');
+ }, 20 );
+ add_action( 'embed_head', 'wp_enqueue_scripts', -10 );
+ add_action( 'embed_head', function() : void {
+ // Override ".dashicon" defaults loaded for oEmbeds.
+ echo '';
+ }, 10 );
+
+ add_action( 'embed_head', function() : void {
+ wp_enqueue_style( 'global-styles' );
+ }, 20 );
+ }
+
+ return $template;
+ } );
+
}
+
+
/**
* Add custom links to the plugin action links in the WordPress plugins list.
*
@@ -389,8 +426,11 @@ public function check_users_can_register(): void {
if (
filter_var( get_option( 'users_can_register' ), FILTER_VALIDATE_BOOLEAN ) ||
filter_var( get_option( 'gatherpress_suppress_site_notification' ), FILTER_VALIDATE_BOOLEAN ) ||
- filter_var( ! current_user_can( 'manage_options' ), FILTER_VALIDATE_BOOLEAN ) ||
- false === strpos( get_current_screen()->id, 'gatherpress' )
+ filter_var( ! current_user_can( 'manage_options' ), FILTER_VALIDATE_BOOLEAN ) || (
+ false === strpos( get_current_screen()->id, 'gatherpress' ) &&
+ false === strpos( get_current_screen()->id, 'options-general' ) &&
+ false === strpos( get_current_screen()->id, 'settings-network' )
+ )
) {
return;
}
@@ -411,4 +451,34 @@ public function check_users_can_register(): void {
);
}
}
+
+ /**
+ * Checks if the GatherPress Alpha plugin is active and renders an admin notice if not.
+ *
+ * This method verifies whether the GatherPress Alpha plugin is currently active.
+ * If the plugin is not active, it renders an admin notice template to inform the user
+ * that the GatherPress Alpha plugin is required for compatibility and development purposes.
+ *
+ * @since 1.0.0
+ *
+ * @return void
+ */
+ public function check_gatherpress_alpha(): void {
+ if (
+ defined( 'GATHERPRESS_ALPHA_VERSION' ) ||
+ filter_var( ! current_user_can( 'install_plugins' ), FILTER_VALIDATE_BOOLEAN ) || (
+ false === strpos( get_current_screen()->id, 'plugins' ) &&
+ false === strpos( get_current_screen()->id, 'plugin-install' ) &&
+ false === strpos( get_current_screen()->id, 'gatherpress' )
+ )
+ ) {
+ return;
+ }
+
+ Utility::render_template(
+ sprintf( '%s/includes/templates/admin/setup/gatherpress-alpha-check.php', GATHERPRESS_CORE_PATH ),
+ array(),
+ true
+ );
+ }
}
diff --git a/includes/core/classes/class-topic.php b/includes/core/classes/class-topic.php
index 86231cb22..afbf70b62 100644
--- a/includes/core/classes/class-topic.php
+++ b/includes/core/classes/class-topic.php
@@ -72,6 +72,8 @@ protected function setup_hooks(): void {
* @return void
*/
public function register_taxonomy(): void {
+ $settings = Settings::get_instance();
+ $rewrite_slug = $settings->get_value( 'general', 'urls', 'topics' );
register_taxonomy(
self::TAXONOMY,
Event::POST_TYPE,
@@ -98,10 +100,34 @@ public function register_taxonomy(): void {
'show_admin_column' => true,
'query_var' => true,
'rewrite' => array(
- 'slug' => _x( 'topic', 'Taxonomy Slug', 'gatherpress' ),
+ 'slug' => $rewrite_slug,
+ 'with_front' => false,
),
'show_in_rest' => true,
)
);
}
+
+ /**
+ * Returns the taxonomy slug localized for the site language and sanitized as URL part.
+ *
+ * Do not use this directly, use get_value( 'general', 'urls', 'topics' ) instead.
+ *
+ * This method switches to the sites default language and gets the translation of 'topics' for the loaded locale.
+ * After that, the method sanitizes the string to be safely used within an URL,
+ * by removing accents, replacing special characters and replacing whitespace with dashes.
+ *
+ * @since 1.0.0
+ *
+ * @return string
+ */
+ public static function get_localized_taxonomy_slug(): string {
+ $switched_locale = switch_to_locale( get_locale() );
+ $slug = _x( 'topic', 'Taxonomy Slug', 'gatherpress' );
+ $slug = sanitize_title( $slug, '', 'save' );
+ if ( $switched_locale ) {
+ restore_previous_locale();
+ }
+ return $slug;
+ }
}
diff --git a/includes/core/classes/class-utility.php b/includes/core/classes/class-utility.php
index aa77da1ee..38b7f34e1 100644
--- a/includes/core/classes/class-utility.php
+++ b/includes/core/classes/class-utility.php
@@ -97,7 +97,7 @@ public static function unprefix_key( string $key ): string {
* @return array An array of time zones with labels as keys and time zone choices as values.
*/
public static function timezone_choices(): array {
- $timezones_raw = explode( PHP_EOL, wp_timezone_choice( 'UTC' ) );
+ $timezones_raw = explode( PHP_EOL, wp_timezone_choice( 'UTC', get_user_locale() ) );
$timezones_clean = array();
$group = null;
diff --git a/includes/core/classes/class-venue.php b/includes/core/classes/class-venue.php
index 146b76439..cf45b0553 100644
--- a/includes/core/classes/class-venue.php
+++ b/includes/core/classes/class-venue.php
@@ -98,6 +98,8 @@ protected function setup_hooks(): void {
* @return void
*/
public function register_post_type(): void {
+ $settings = Settings::get_instance();
+ $rewrite_slug = $settings->get_value( 'general', 'urls', 'venues' );
register_post_type(
self::POST_TYPE,
array(
@@ -131,13 +133,38 @@ public function register_post_type(): void {
'template' => array(
array( 'gatherpress/venue' ),
),
+ 'has_archive' => true,
'rewrite' => array(
- 'slug' => _x( 'venue', 'Post Type Slug', 'gatherpress' ),
+ 'slug' => $rewrite_slug,
+ 'with_front' => false,
),
)
);
}
+ /**
+ * Returns the post type slug localized for the site language and sanitized as URL part.
+ *
+ * Do not use this directly, use get_value( 'general', 'urls', 'venues' ) instead.
+ *
+ * This method switches to the sites default language and gets the translation of 'venues' for the loaded locale.
+ * After that, the method sanitizes the string to be safely used within an URL,
+ * by removing accents, replacing special characters and replacing whitespace with dashes.
+ *
+ * @since 1.0.0
+ *
+ * @return string
+ */
+ public static function get_localized_post_type_slug(): string {
+ $switched_locale = switch_to_locale( get_locale() );
+ $slug = _x( 'venue', 'Post Type Slug', 'gatherpress' );
+ $slug = sanitize_title( $slug, '', 'save' );
+ if ( $switched_locale ) {
+ restore_previous_locale();
+ }
+ return $slug;
+ }
+
/**
* Registers custom meta fields for the Venue post type.
*
@@ -190,7 +217,10 @@ public function register_taxonomy(): void {
self::TAXONOMY,
Event::POST_TYPE,
array(
- 'labels' => array(),
+ 'labels' => array(
+ 'name' => _x( 'Venues', 'Taxonomy General Name', 'gatherpress' ),
+ 'singular_name' => _x( 'Venue', 'Taxonomy Singular Name', 'gatherpress' ),
+ ),
'hierarchical' => false,
'public' => true,
'show_ui' => false,
@@ -261,8 +291,15 @@ public function maybe_update_term_slug( int $post_id, WP_Post $post_after, WP_Po
return;
}
- // Only proceed if the venue post is being published.
- if ( 'publish' !== $post_after->post_status ) {
+ // Only proceed if the venue post is being published or trashed.
+ if ( ! in_array(
+ $post_after->post_status,
+ array(
+ 'publish',
+ 'trash',
+ ),
+ true
+ ) ) {
return;
}
diff --git a/includes/core/classes/settings/class-general.php b/includes/core/classes/settings/class-general.php
index c6d76a15c..6b63be009 100644
--- a/includes/core/classes/settings/class-general.php
+++ b/includes/core/classes/settings/class-general.php
@@ -16,7 +16,9 @@
defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
use GatherPress\Core\Traits\Singleton;
-
+use GatherPress\Core\Event_Setup;
+use GatherPress\Core\Venue;
+use GatherPress\Core\Topic;
/**
* Class General.
*
@@ -103,6 +105,23 @@ protected function get_sections(): array {
),
),
),
+ 'map_platform' => array(
+ 'labels' => array(
+ 'name' => __( 'Mapping Platform', 'gatherpress' ),
+ ),
+ 'description' => __( 'Select the platform you would like to render maps with.', 'gatherpress' ),
+ 'field' => array(
+ 'label' => __( 'Selected Mapping Platform:', 'gatherpress' ),
+ 'type' => 'select',
+ 'options' => array(
+ 'default' => 'osm',
+ 'items' => array(
+ 'osm' => __( 'Open Street Maps', 'gatherpress' ),
+ 'google' => __( 'Google Maps', 'gatherpress' ),
+ ),
+ ),
+ ),
+ ),
'max_attendance_limit' => array(
'labels' => array(
'name' => __( 'Maximum Attendance Limit', 'gatherpress' ),
@@ -237,6 +256,49 @@ protected function get_sections(): array {
),
),
),
+ 'urls' => array(
+ 'name' => __( 'URLs generated by the plugin', 'gatherpress' ),
+ 'description' => __( 'Change permalink bases.', 'gatherpress' ),
+ 'options' => array(
+ 'events' => array(
+ 'labels' => array(
+ 'name' => __( 'Events', 'gatherpress' ),
+ ),
+ 'field' => array(
+ 'type' => 'text',
+ 'options' => array(
+ 'label' => __( 'Permalink base of Events.', 'gatherpress' ),
+ 'default' => Event_Setup::get_localized_post_type_slug(),
+ ),
+ ),
+ ),
+ 'venues' => array(
+ 'labels' => array(
+ 'name' => __( 'Venues', 'gatherpress' ),
+ ),
+ 'field' => array(
+ 'type' => 'text',
+ 'options' => array(
+ 'label' => __( 'Permalink base of Venues.', 'gatherpress' ),
+ 'default' => Venue::get_localized_post_type_slug(),
+ ),
+ ),
+ ),
+ 'topics' => array(
+ 'labels' => array(
+ 'name' => __( 'Topics', 'gatherpress' ),
+ ),
+ 'field' => array(
+ 'type' => 'text',
+ 'options' => array(
+ 'label' => __( 'Permalink base of Topics.', 'gatherpress' ),
+ 'default' => Topic::get_localized_taxonomy_slug(),
+ ),
+ ),
+ ),
+
+ ),
+ ),
);
}
}
diff --git a/includes/data/credits.php b/includes/data/credits.php
index 1e8cd5e8f..ab316830a 100644
--- a/includes/data/credits.php
+++ b/includes/data/credits.php
@@ -4,7 +4,7 @@
defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
return array (
- 'version' => '0.30.0-alpha',
+ 'version' => '0.31.0-alpha',
'project-leaders' =>
array (
0 =>
@@ -46,36 +46,62 @@
96 => '//www.gravatar.com/avatar/eff55f7591ee0908b90dd1724c290d0a?s=96&r=g&d=mm',
),
),
+ 3 =>
+ array (
+ 'id' => 7673952,
+ 'name' => 'Carsten Bach',
+ 'link' => 'https://profiles.wordpress.org/author/carstenbach/',
+ 'slug' => 'carstenbach',
+ 'avatar_urls' =>
+ array (
+ 24 => '//www.gravatar.com/avatar/98eb3a2530e8b074932f8e059d0dadc0?s=24&r=g&d=mm',
+ 48 => '//www.gravatar.com/avatar/98eb3a2530e8b074932f8e059d0dadc0?s=48&r=g&d=mm',
+ 96 => '//www.gravatar.com/avatar/98eb3a2530e8b074932f8e059d0dadc0?s=96&r=g&d=mm',
+ ),
+ ),
),
'gatherpress-team' =>
array (
0 =>
array (
- 'id' => 4555438,
- 'name' => '',
- 'link' => 'https://profiles.wordpress.org/author/jmarx/',
- 'slug' => 'jmarx',
+ 'id' => 130224,
+ 'name' => 'jmarx75',
+ 'link' => 'https://profiles.wordpress.org/author/jmarx75/',
+ 'slug' => 'jmarx75',
'avatar_urls' =>
array (
- 24 => '//www.gravatar.com/avatar/c45f6353d61871317b31fb9048d39b2b?s=24&r=g&d=mm',
- 48 => '//www.gravatar.com/avatar/c45f6353d61871317b31fb9048d39b2b?s=48&r=g&d=mm',
- 96 => '//www.gravatar.com/avatar/c45f6353d61871317b31fb9048d39b2b?s=96&r=g&d=mm',
+ 24 => '//www.gravatar.com/avatar/e4dbd0c1b4a8f180c0d7f92a6909ba56?s=24&r=g&d=mm',
+ 48 => '//www.gravatar.com/avatar/e4dbd0c1b4a8f180c0d7f92a6909ba56?s=48&r=g&d=mm',
+ 96 => '//www.gravatar.com/avatar/e4dbd0c1b4a8f180c0d7f92a6909ba56?s=96&r=g&d=mm',
),
),
1 =>
array (
- 'id' => 16994801,
- 'name' => 'Paul Barthmaier (pbrocks)',
- 'link' => 'https://profiles.wordpress.org/author/pbrocks/',
- 'slug' => 'pbrocks',
+ 'id' => 7268075,
+ 'name' => 'Steve Erdelyi',
+ 'link' => 'https://profiles.wordpress.org/author/stephenerdelyi/',
+ 'slug' => 'stephenerdelyi',
'avatar_urls' =>
array (
- 24 => '//www.gravatar.com/avatar/b6d92ca42584e8419dffc636e809321a?s=24&r=g&d=mm',
- 48 => '//www.gravatar.com/avatar/b6d92ca42584e8419dffc636e809321a?s=48&r=g&d=mm',
- 96 => '//www.gravatar.com/avatar/b6d92ca42584e8419dffc636e809321a?s=96&r=g&d=mm',
+ 24 => '//www.gravatar.com/avatar/96b3db2b51287c4c0f035717b6aac86e?s=24&r=g&d=mm',
+ 48 => '//www.gravatar.com/avatar/96b3db2b51287c4c0f035717b6aac86e?s=48&r=g&d=mm',
+ 96 => '//www.gravatar.com/avatar/96b3db2b51287c4c0f035717b6aac86e?s=96&r=g&d=mm',
),
),
2 =>
+ array (
+ 'id' => 20244435,
+ 'name' => 'Caleb Matteis',
+ 'link' => 'https://profiles.wordpress.org/author/calebthedev/',
+ 'slug' => 'calebthedev',
+ 'avatar_urls' =>
+ array (
+ 24 => '//www.gravatar.com/avatar/9e7fee920b635110a2e6a160d323bdd5?s=24&r=g&d=mm',
+ 48 => '//www.gravatar.com/avatar/9e7fee920b635110a2e6a160d323bdd5?s=48&r=g&d=mm',
+ 96 => '//www.gravatar.com/avatar/9e7fee920b635110a2e6a160d323bdd5?s=96&r=g&d=mm',
+ ),
+ ),
+ 3 =>
array (
'id' => 21156948,
'name' => 'Prayag Mankar',
@@ -88,56 +114,30 @@
96 => '//www.gravatar.com/avatar/ddc43fb192c5a9c58e16c0ccab85b81f?s=96&r=g&d=mm',
),
),
- 3 =>
- array (
- 'id' => 21213947,
- 'name' => 'Bill Van Pelt',
- 'link' => 'https://profiles.wordpress.org/author/linusx007/',
- 'slug' => 'linusx007',
- 'avatar_urls' =>
- array (
- 24 => '//www.gravatar.com/avatar/66ad6f626fb27b53499b0a240f46a8bf?s=24&r=g&d=mm',
- 48 => '//www.gravatar.com/avatar/66ad6f626fb27b53499b0a240f46a8bf?s=48&r=g&d=mm',
- 96 => '//www.gravatar.com/avatar/66ad6f626fb27b53499b0a240f46a8bf?s=96&r=g&d=mm',
- ),
- ),
4 =>
array (
- 'id' => 7268075,
- 'name' => 'Steve Erdelyi',
- 'link' => 'https://profiles.wordpress.org/author/stephenerdelyi/',
- 'slug' => 'stephenerdelyi',
+ 'id' => 16994801,
+ 'name' => 'Paul Barthmaier (pbrocks)',
+ 'link' => 'https://profiles.wordpress.org/author/pbrocks/',
+ 'slug' => 'pbrocks',
'avatar_urls' =>
array (
- 24 => '//www.gravatar.com/avatar/96b3db2b51287c4c0f035717b6aac86e?s=24&r=g&d=mm',
- 48 => '//www.gravatar.com/avatar/96b3db2b51287c4c0f035717b6aac86e?s=48&r=g&d=mm',
- 96 => '//www.gravatar.com/avatar/96b3db2b51287c4c0f035717b6aac86e?s=96&r=g&d=mm',
+ 24 => '//www.gravatar.com/avatar/b6d92ca42584e8419dffc636e809321a?s=24&r=g&d=mm',
+ 48 => '//www.gravatar.com/avatar/b6d92ca42584e8419dffc636e809321a?s=48&r=g&d=mm',
+ 96 => '//www.gravatar.com/avatar/b6d92ca42584e8419dffc636e809321a?s=96&r=g&d=mm',
),
),
5 =>
array (
- 'id' => 7673952,
- 'name' => 'Carsten Bach',
- 'link' => 'https://profiles.wordpress.org/author/carstenbach/',
- 'slug' => 'carstenbach',
- 'avatar_urls' =>
- array (
- 24 => '//www.gravatar.com/avatar/98eb3a2530e8b074932f8e059d0dadc0?s=24&r=g&d=mm',
- 48 => '//www.gravatar.com/avatar/98eb3a2530e8b074932f8e059d0dadc0?s=48&r=g&d=mm',
- 96 => '//www.gravatar.com/avatar/98eb3a2530e8b074932f8e059d0dadc0?s=96&r=g&d=mm',
- ),
- ),
- 6 =>
- array (
- 'id' => 20244435,
- 'name' => 'Caleb Matteis',
- 'link' => 'https://profiles.wordpress.org/author/calebthedev/',
- 'slug' => 'calebthedev',
+ 'id' => 21213947,
+ 'name' => 'Bill Van Pelt',
+ 'link' => 'https://profiles.wordpress.org/author/linusx007/',
+ 'slug' => 'linusx007',
'avatar_urls' =>
array (
- 24 => '//www.gravatar.com/avatar/9e7fee920b635110a2e6a160d323bdd5?s=24&r=g&d=mm',
- 48 => '//www.gravatar.com/avatar/9e7fee920b635110a2e6a160d323bdd5?s=48&r=g&d=mm',
- 96 => '//www.gravatar.com/avatar/9e7fee920b635110a2e6a160d323bdd5?s=96&r=g&d=mm',
+ 24 => '//www.gravatar.com/avatar/66ad6f626fb27b53499b0a240f46a8bf?s=24&r=g&d=mm',
+ 48 => '//www.gravatar.com/avatar/66ad6f626fb27b53499b0a240f46a8bf?s=48&r=g&d=mm',
+ 96 => '//www.gravatar.com/avatar/66ad6f626fb27b53499b0a240f46a8bf?s=96&r=g&d=mm',
),
),
),
@@ -222,6 +222,19 @@
),
),
6 =>
+ array (
+ 'id' => 18639594,
+ 'name' => 'Steve Mosby',
+ 'link' => 'https://profiles.wordpress.org/author/malgra/',
+ 'slug' => 'malgra',
+ 'avatar_urls' =>
+ array (
+ 24 => '//www.gravatar.com/avatar/62a3f0c3953c7f0d04b0d54cf286c600?s=24&r=g&d=mm',
+ 48 => '//www.gravatar.com/avatar/62a3f0c3953c7f0d04b0d54cf286c600?s=48&r=g&d=mm',
+ 96 => '//www.gravatar.com/avatar/62a3f0c3953c7f0d04b0d54cf286c600?s=96&r=g&d=mm',
+ ),
+ ),
+ 7 =>
array (
'id' => 11146216,
'name' => 'meagan hanes',
@@ -234,7 +247,7 @@
96 => '//www.gravatar.com/avatar/052d4e778920f20d9f6611bf5c027528?s=96&r=g&d=mm',
),
),
- 7 =>
+ 8 =>
array (
'id' => 13234268,
'name' => 'Michelle Frechette',
@@ -247,7 +260,7 @@
96 => '//www.gravatar.com/avatar/c6711ad7886201b5e585c96535f2229d?s=96&r=g&d=mm',
),
),
- 8 =>
+ 9 =>
array (
'id' => 14692152,
'name' => 'Laura Byrne',
@@ -260,10 +273,10 @@
96 => '//www.gravatar.com/avatar/9210ecea04529656ea99064634ac636b?s=96&r=g&d=mm',
),
),
- 9 =>
+ 10 =>
array (
'id' => 13994457,
- 'name' => 'Nilo Vélez',
+ 'name' => 'Nilo Velez',
'link' => 'https://profiles.wordpress.org/author/nilovelez/',
'slug' => 'nilovelez',
'avatar_urls' =>
@@ -273,7 +286,7 @@
96 => '//www.gravatar.com/avatar/82a67d2d011ae384612fe6441576cdf5?s=96&r=g&d=mm',
),
),
- 10 =>
+ 11 =>
array (
'id' => 15490728,
'name' => 'Jason Lawton',
@@ -286,7 +299,7 @@
96 => '//www.gravatar.com/avatar/ec5ec8357fa89bb2671bf1ab61b2546b?s=96&r=g&d=mm',
),
),
- 11 =>
+ 12 =>
array (
'id' => 20932248,
'name' => 'prashantabellad',
@@ -299,7 +312,7 @@
96 => '//www.gravatar.com/avatar/57794a51302818489f91bb191adddc40?s=96&r=g&d=mm',
),
),
- 12 =>
+ 13 =>
array (
'id' => 368236,
'name' => 'Pascal Birchler',
diff --git a/includes/templates/admin/settings/fields/select.php b/includes/templates/admin/settings/fields/select.php
new file mode 100644
index 000000000..a847bdb65
--- /dev/null
+++ b/includes/templates/admin/settings/fields/select.php
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+
+ $name,
+ 'value' => ! empty( $value ) ? $value : '',
+ 'suffix' => $suffix,
+);
+?>
+