Merge branch 'trunk' into update/breadcrumb-for-accessibility
This commit is contained in:
commit
4d133b4ca8
|
@ -1,6 +1,5 @@
|
|||
name: Run API tests
|
||||
description: Runs the WooCommerce Core API tests and generates Allure report.
|
||||
permissions: {}
|
||||
|
||||
inputs:
|
||||
report-name:
|
||||
|
@ -8,6 +7,9 @@ inputs:
|
|||
required: true
|
||||
tests:
|
||||
description: Specific tests to run, separated by single whitespace. See https://playwright.dev/docs/test-cli
|
||||
playwright-config:
|
||||
description: Playwright config file to be used
|
||||
default: playwright.config.js
|
||||
|
||||
outputs:
|
||||
result:
|
||||
|
@ -23,7 +25,7 @@ runs:
|
|||
shell: bash
|
||||
run: |
|
||||
pnpm exec playwright test \
|
||||
--config=tests/api-core-tests/playwright.config.js \
|
||||
--config=tests/api-core-tests/${{ inputs.playwright-config }} \
|
||||
${{ inputs.tests }}
|
||||
|
||||
- name: Generate Test report.
|
||||
|
|
|
@ -67,11 +67,11 @@
|
|||
'plugin: woo-ai':
|
||||
- plugins/woo-ai/**/*
|
||||
|
||||
'focus: performance tests [team:Solaris]':
|
||||
'focus: performance tests':
|
||||
- plugins/woocommerce/tests/performance/**/*
|
||||
|
||||
'focus: api tests [team:Solaris]':
|
||||
'focus: api tests':
|
||||
- plugins/woocommerce/tests/api-core-tests/**/*
|
||||
|
||||
'focus: e2e tests [team:Solaris]':
|
||||
'focus: e2e tests':
|
||||
- plugins/woocommerce/tests/e2e-pw/**/*
|
||||
|
|
|
@ -294,6 +294,15 @@ jobs:
|
|||
|
||||
core.setOutput( 'cherry-pick-pr', pr.data.html_url )
|
||||
|
||||
// label PR
|
||||
|
||||
const label = await github.rest.issues.addLabels({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: pr.data.number,
|
||||
labels: ["metric: code freeze exception"],
|
||||
});
|
||||
|
||||
- name: Checkout trunk branch
|
||||
if: steps.changelog.outputs.changelogsToBeDeleted != '' && steps.changelog.outputs.changelogsToBeDeleted != null
|
||||
run: git checkout trunk
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
name: Run tests against PR in an environment with COT enabled
|
||||
name: Run tests against PR in an environment with HPOS disabled
|
||||
on:
|
||||
pull_request:
|
||||
workflow_dispatch:
|
||||
|
@ -10,8 +10,8 @@ concurrency:
|
|||
permissions: {}
|
||||
|
||||
jobs:
|
||||
cot-e2e-tests-run:
|
||||
name: Runs E2E tests with COT enabled.
|
||||
non-hpos-e2e-tests-run:
|
||||
name: Runs E2E tests with HPOS disabled.
|
||||
runs-on: ubuntu-20.04
|
||||
permissions:
|
||||
contents: read
|
||||
|
@ -24,11 +24,9 @@ jobs:
|
|||
- name: Setup WooCommerce Monorepo
|
||||
uses: ./.github/actions/setup-woocommerce-monorepo
|
||||
|
||||
- name: Load docker images and start containers with COT enabled.
|
||||
- name: Load docker images and start containers
|
||||
working-directory: plugins/woocommerce
|
||||
env:
|
||||
ENABLE_HPOS: 1
|
||||
run: pnpm env:test:cot --filter=woocommerce
|
||||
run: pnpm env:test --filter=woocommerce
|
||||
|
||||
- name: Download and install Chromium browser.
|
||||
working-directory: plugins/woocommerce
|
||||
|
@ -39,6 +37,7 @@ jobs:
|
|||
id: run_playwright_e2e_tests
|
||||
env:
|
||||
USE_WP_ENV: 1
|
||||
ENABLE_HPOS: 0
|
||||
working-directory: plugins/woocommerce
|
||||
run: pnpm exec playwright test --config=tests/e2e-pw/playwright.config.js
|
||||
|
||||
|
@ -66,8 +65,8 @@ jobs:
|
|||
if-no-files-found: ignore
|
||||
retention-days: 5
|
||||
|
||||
cot-api-tests-run:
|
||||
name: Runs API tests with COT enabled.
|
||||
non-hpos-api-tests-run:
|
||||
name: Runs API tests with HPOS disabled.
|
||||
runs-on: ubuntu-20.04
|
||||
permissions:
|
||||
contents: read
|
||||
|
@ -80,11 +79,9 @@ jobs:
|
|||
- name: Setup WooCommerce Monorepo
|
||||
uses: ./.github/actions/setup-woocommerce-monorepo
|
||||
|
||||
- name: Load docker images and start containers with COT enabled.
|
||||
- name: Load docker images and start containers
|
||||
working-directory: plugins/woocommerce
|
||||
env:
|
||||
ENABLE_HPOS: 1
|
||||
run: pnpm env:test:cot --filter=woocommerce
|
||||
run: pnpm env:test --filter=woocommerce
|
||||
|
||||
- name: Run Playwright API tests.
|
||||
id: run_playwright_api_tests
|
||||
|
@ -93,6 +90,7 @@ jobs:
|
|||
BASE_URL: http://localhost:8086
|
||||
USER_KEY: admin
|
||||
USER_SECRET: password
|
||||
ENABLE_HPOS: 0
|
||||
run: pnpm exec playwright test --config=tests/api-core-tests/playwright.config.js
|
||||
|
||||
- name: Generate Playwright API Test report.
|
|
@ -31,7 +31,6 @@ jobs:
|
|||
- name: Load docker images and start containers.
|
||||
working-directory: plugins/woocommerce
|
||||
env:
|
||||
ENABLE_HPOS: 0
|
||||
WP_ENV_PHP_VERSION: 7.4
|
||||
run: pnpm run env:test
|
||||
|
||||
|
|
|
@ -155,16 +155,22 @@ jobs:
|
|||
install-filters: woocommerce
|
||||
build: false
|
||||
|
||||
- name: Download and install Chromium browser.
|
||||
working-directory: plugins/woocommerce
|
||||
run: pnpm exec playwright install chromium
|
||||
|
||||
- name: Run API tests
|
||||
id: run-api-composite-action
|
||||
uses: ./.github/actions/tests/run-api-tests
|
||||
with:
|
||||
report-name: ${{ env.API_WP_LATEST_ARTIFACT }}
|
||||
tests: hello
|
||||
playwright-config: ci-release.playwright.config.js
|
||||
env:
|
||||
API_BASE_URL: ${{ secrets.RELEASE_TEST_URL }}
|
||||
USER_KEY: ${{ secrets.RELEASE_TEST_ADMIN_USER }}
|
||||
USER_SECRET: ${{ secrets.RELEASE_TEST_ADMIN_PASSWORD }}
|
||||
UPDATE_WC: ${{ needs.get-tag.outputs.tag }}
|
||||
|
||||
- name: Upload Allure artifacts to bucket
|
||||
if: success() || ( failure() && steps.run-api-composite-action.conclusion == 'failure' )
|
||||
|
|
|
@ -0,0 +1,88 @@
|
|||
name: Send a Slack notification when a PR contains rest api changes
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
types: [labeled]
|
||||
|
||||
permissions: {}
|
||||
|
||||
jobs:
|
||||
send-slack-notification-when-pr-contains-rest-api-changes:
|
||||
if: "${{ github.event.label.name == 'contains: rest api change' && (github.event.pull_request.state == 'open' || github.event.pull_request.merged) }}"
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- name: Wait 2 minutes for other labelling jobs to finish
|
||||
run: sleep 2m
|
||||
shell: bash
|
||||
|
||||
- name: Calculate test date
|
||||
id: calculate_date
|
||||
run: |
|
||||
#!/bin/bash
|
||||
|
||||
# Get the day of the week of the merged PR (0 for Sunday, 1 for Monday, etc.)
|
||||
MERGE_DAY_OF_WEEK=$(date -u -d "${{ github.event.pull_request.merged_at }}" +"%u")
|
||||
|
||||
# Calculate days until the next Thursday after the merge
|
||||
# If the merge is on Thursday, this will give 7 (i.e., next week's Thursday)
|
||||
DAYS_UNTIL_NEXT_THURSDAY=$(( (4 + 7 - MERGE_DAY_OF_WEEK) % 7 ))
|
||||
|
||||
# If DAYS_UNTIL_NEXT_THURSDAY is 0, the merge was on a Thursday, so we set it to 7 to get the next Thursday
|
||||
if [ $DAYS_UNTIL_NEXT_THURSDAY -eq 0 ]; then
|
||||
DAYS_UNTIL_NEXT_THURSDAY=7
|
||||
fi
|
||||
|
||||
# Calculate the date for the next Thursday after the merge
|
||||
THURSDAY_AFTER_MERGE=$(date -u -d "${{ github.event.pull_request.merged_at }} + $DAYS_UNTIL_NEXT_THURSDAY days" +"%Y-%m-%d")
|
||||
WOOAF_RELEASE_DATE=$(date -u -d "${THURSDAY_AFTER_MERGE} + 6 days" +"%Y-%m-%d")
|
||||
TEST_DATE_MESSAGE="Thursday, $THURSDAY_AFTER_MERGE. (Targeting release on $WOOAF_RELEASE_DATE)"
|
||||
echo "TEST_DATE_MESSAGE=${TEST_DATE_MESSAGE}" >> $GITHUB_ENV
|
||||
|
||||
- name: Determine Milestone Date
|
||||
id: get_milestone_date
|
||||
run: |
|
||||
#!/bin/bash
|
||||
|
||||
MILESTONE_TITLE="${{ github.event.pull_request.milestone.title }}"
|
||||
MILESTONE_DATE="Undefined"
|
||||
|
||||
# Mapping of milestone titles to release dates
|
||||
declare -A MILESTONE_DATES
|
||||
MILESTONE_DATES=(
|
||||
["8.0.0"]="2023-08-08"
|
||||
["8.1.0"]="2023-09-12"
|
||||
["8.2.0"]="2023-10-10"
|
||||
["8.3.0"]="2023-11-14"
|
||||
["8.4.0"]="2023-12-12"
|
||||
["8.5.0"]="2024-01-09"
|
||||
["8.6.0"]="2024-02-13"
|
||||
["8.7.0"]="2024-03-12"
|
||||
["8.8.0"]="2024-04-09"
|
||||
["8.9.0"]="2024-05-14"
|
||||
["9.0.0"]="2024-06-11"
|
||||
)
|
||||
|
||||
# Check if the milestone title exists in our predefined list and get the date
|
||||
if [[ -v "MILESTONE_DATES[${MILESTONE_TITLE}]" ]]; then
|
||||
MILESTONE_DATE=${MILESTONE_DATES[${MILESTONE_TITLE}]}
|
||||
fi
|
||||
|
||||
# Export for later steps
|
||||
echo "MILESTONE_DATE=${MILESTONE_DATE}" >> $GITHUB_ENV
|
||||
|
||||
# Notify Slack Step
|
||||
- name: Notify Slack
|
||||
uses: archive/github-actions-slack@d9dae40827adf93bddf939db6552d1e392259d7d
|
||||
id: notify
|
||||
with:
|
||||
slack-bot-user-oauth-access-token: ${{ secrets.TEST_ASSISTANCE_BOT_TOKEN }}
|
||||
slack-channel: ${{ secrets.WOO_CORE_REST_API_CHANGES_SLACK_CHANNEL }}
|
||||
slack-text: |
|
||||
<${{ github.event.pull_request.html_url }}|${{ github.event.pull_request.title }}>
|
||||
*Labels:* ${{ join(github.event.pull_request.labels.*.name, ', ') }}
|
||||
*Monthly Release Milestone:* <${{ github.event.pull_request.milestone.html_url }}|${{ github.event.pull_request.milestone.title }}> (Release Date: ${{ env.MILESTONE_DATE }})
|
||||
*WooAF (weekly) Timeline: this PR can be tested from:* ${{ env.TEST_DATE_MESSAGE }}
|
||||
Please visit the <#${{ secrets.WOO_CORE_RELEASES_SLACK_CHANNEL }}> to obtain the latest WooAF build for testing.
|
||||
slack-optional-unfurl_links: false
|
||||
slack-optional-unfurl_media: false
|
||||
|
|
@ -4,6 +4,7 @@
|
|||
"MD007": { "indent": 4 },
|
||||
"MD013": { "line_length": 9999 },
|
||||
"MD024": { "allow_different_nesting": true },
|
||||
"MD033": { "allowed_elements": ["video"] },
|
||||
"no-hard-tabs": false,
|
||||
"whitespace": false
|
||||
}
|
||||
|
|
129
changelog.txt
129
changelog.txt
|
@ -1,5 +1,134 @@
|
|||
== Changelog ==
|
||||
|
||||
= 8.2.0 2023-10-13 =
|
||||
|
||||
**WooCommerce**
|
||||
|
||||
* Fix - Correctly set 'created_via' for HPOS orders created on the admin. [#40469](https://github.com/woocommerce/woocommerce/pull/40469)
|
||||
* Fix - Fix backwards compatibility issue with `wc_get_orders()` when HPOS is active and the pagination bit is set. [#40551](https://github.com/woocommerce/woocommerce/pull/40551)
|
||||
* Fix - Save hpos order data before clearing the order from cache [#40282](https://github.com/woocommerce/woocommerce/pull/40282)
|
||||
* Fix - Disable WP's post lock on HPOS order edit screen. [#40355](https://github.com/woocommerce/woocommerce/pull/40355)
|
||||
* Fix - Enqueue media scripts for Images block within the product editor, as is required for Images block. [#40356](https://github.com/woocommerce/woocommerce/pull/40356)
|
||||
* Fix - Addressed visual tweaks for CYS in response to feedback from 12th Sept [#40155](https://github.com/woocommerce/woocommerce/pull/40155)
|
||||
* Fix - Address missing order type handling in HPOS compatibility mode sync. [#40279](https://github.com/woocommerce/woocommerce/pull/40279)
|
||||
* Fix - Add Variation options section back to the product blocks template [#39914](https://github.com/woocommerce/woocommerce/pull/39914)
|
||||
* Fix - Avoid a fatal error on the order received page if the order ID is not for a valid order. [#39876](https://github.com/woocommerce/woocommerce/pull/39876)
|
||||
* Fix - Avoid string<>int comparison in products bought query to avoid results with customer_id = 0. [#40030](https://github.com/woocommerce/woocommerce/pull/40030)
|
||||
* Fix - Changed Tax task completion criteria so that it considers both boolean and stringly typed values as expected [#39983](https://github.com/woocommerce/woocommerce/pull/39983)
|
||||
* Fix - Display search results subtitle in HPOS list table view. [#40270](https://github.com/woocommerce/woocommerce/pull/40270)
|
||||
* Fix - Eliminate an unnecessary redirect when the geo hash isalready set to the correct value. [#39634](https://github.com/woocommerce/woocommerce/pull/39634)
|
||||
* Fix - Fix a bug where updating store location doesn't update store currency. [#40142](https://github.com/woocommerce/woocommerce/pull/40142)
|
||||
* Fix - Fix cached refund not deleted when the refund is deleted with HPOS active [#40197](https://github.com/woocommerce/woocommerce/pull/40197)
|
||||
* Fix - Fix changes in order custom fields made from admin not being applied when using the order Update button with HPOS active. [#40278](https://github.com/woocommerce/woocommerce/pull/40278)
|
||||
* Fix - Fix customize store white screen bug in WP 6.3 [#40031](https://github.com/woocommerce/woocommerce/pull/40031)
|
||||
* Fix - Fix customize your store task header button [#40031](https://github.com/woocommerce/woocommerce/pull/40031)
|
||||
* Fix - Fix CYS UI issues [#40269](https://github.com/woocommerce/woocommerce/pull/40269)
|
||||
* Fix - Fix CYS `__experimentalReapplyBlockTypeFilters` is not a function [#40104](https://github.com/woocommerce/woocommerce/pull/40104)
|
||||
* Fix - Fixed missed lint error in Assembler Hub [#39964](https://github.com/woocommerce/woocommerce/pull/39964)
|
||||
* Fix - Fix minor layout shift in the core profiler. [#39898](https://github.com/woocommerce/woocommerce/pull/39898)
|
||||
* Fix - Fix product e2e tests [#39823](https://github.com/woocommerce/woocommerce/pull/39823)
|
||||
* Fix - Fix undismissable notice when using localization for certain messages like "Coupon management has moved" [#39913](https://github.com/woocommerce/woocommerce/pull/39913)
|
||||
* Fix - FIx WC Admin pages are empty for WP 6.2 and below. [#39995](https://github.com/woocommerce/woocommerce/pull/39995)
|
||||
* Fix - Properly convert local time date queries to UTC in the HPOS datastore. [#40146](https://github.com/woocommerce/woocommerce/pull/40146)
|
||||
* Fix - Redirect to Jetpack connect when jetpack-boost is selected. [#40261](https://github.com/woocommerce/woocommerce/pull/40261)
|
||||
* Fix - Remove COT enable requirement from sync and verify command. [#39998](https://github.com/woocommerce/woocommerce/pull/39998)
|
||||
* Fix - Removed references to the un-used Purchase task item in the onboarding task list. [#40121](https://github.com/woocommerce/woocommerce/pull/40121)
|
||||
* Fix - Remove use of woocommerce-page class within WooCommerce Admin pages, replaced with woocommerce-admin-page. [#40218](https://github.com/woocommerce/woocommerce/pull/40218)
|
||||
* Fix - Restore moving to trash functionality within HPOS order edit screen. [#39693](https://github.com/woocommerce/woocommerce/pull/39693)
|
||||
* Fix - update the SqlQuery filter prefix in data.md [#39319](https://github.com/woocommerce/woocommerce/pull/39319)
|
||||
* Fix - Use correct object reference when cloning a cart [#39282](https://github.com/woocommerce/woocommerce/pull/39282)
|
||||
* Fix - [HPOS]Fix duplicate meta handling by passing meta_value|unique in post calls [#40088](https://github.com/woocommerce/woocommerce/pull/40088)
|
||||
* Fix - [HPOS] Modify query to have less characters before the `FROM` keyword. [#40109](https://github.com/woocommerce/woocommerce/pull/40109)
|
||||
* Fix - [HPOS] Support deleting metadata just by meta id. [#40064](https://github.com/woocommerce/woocommerce/pull/40064)
|
||||
* Fix - [HPOS] Use objects method instead of calling datastore directly. [#40158](https://github.com/woocommerce/woocommerce/pull/40158)
|
||||
* Add - Add ability to remove blocks from templates. [#39900](https://github.com/woocommerce/woocommerce/pull/39900)
|
||||
* Add - Add a filter to OrdersTableQuery to allow overriding of HPOS queries. [#39945](https://github.com/woocommerce/woocommerce/pull/39945)
|
||||
* Add - Add after_add_block and after_remove block hooks to the block template API. [#40139](https://github.com/woocommerce/woocommerce/pull/40139)
|
||||
* Add - Add AI wizard business info step for Customize Your Store task [#39979](https://github.com/woocommerce/woocommerce/pull/39979)
|
||||
* Add - Add component to Customize Your Store task. [#40140](https://github.com/woocommerce/woocommerce/pull/40140)
|
||||
* Add - Add customize store - fonts [#40082](https://github.com/woocommerce/woocommerce/pull/40082)
|
||||
* Add - Add customize store AI wizard call for best colour palette suggestions. [#40295](https://github.com/woocommerce/woocommerce/pull/40295)
|
||||
* Add - Add customize store AI wizard call for color palette suggestion [#40237](https://github.com/woocommerce/woocommerce/pull/40237)
|
||||
* Add - Add customize store AI wizard call for font pairing suggestion [#40240](https://github.com/woocommerce/woocommerce/pull/40240)
|
||||
* Add - Add customize store assembler hub onboarding tour [#39981](https://github.com/woocommerce/woocommerce/pull/39981)
|
||||
* Add - Add customize store assembler hub [#39843](https://github.com/woocommerce/woocommerce/pull/39843)
|
||||
* Add - Add customize store color palettes [#40051](https://github.com/woocommerce/woocommerce/pull/40051)
|
||||
* Add - Add customize store transitional screen [#40122](https://github.com/woocommerce/woocommerce/pull/40122)
|
||||
* Add - Added URL navigation support to customize-store feature [#40068](https://github.com/woocommerce/woocommerce/pull/40068)
|
||||
* Add - Add filter woocommerce_hpos_enable_sync_on_read to disable sync on read with HPOS sync enabled. [#40039](https://github.com/woocommerce/woocommerce/pull/40039)
|
||||
* Add - Add has_price param to the variations REST API query. [#40281](https://github.com/woocommerce/woocommerce/pull/40281)
|
||||
* Add - Add header customization to the Assembler Hub [#40107](https://github.com/woocommerce/woocommerce/pull/40107)
|
||||
* Add - Add help text to Name field in Create new category modal [#40059](https://github.com/woocommerce/woocommerce/pull/40059)
|
||||
* Add - Add new e2e test for Shopper My Account Downloads section [#40100](https://github.com/woocommerce/woocommerce/pull/40100)
|
||||
* Add - Add new e2e test to cover My Account Addresses section [#40114](https://github.com/woocommerce/woocommerce/pull/40114)
|
||||
* Add - Add sidebar to customize your store task. [#40136](https://github.com/woocommerce/woocommerce/pull/40136)
|
||||
* Add - Adds new action hook `woocommerce_pay_order_before_payment` to the `checkout/form-pay.php` template. [#37588](https://github.com/woocommerce/woocommerce/pull/37588)
|
||||
* Add - Add support for slug auto generation to the create attribute endpoint [#39827](https://github.com/woocommerce/woocommerce/pull/39827)
|
||||
* Add - Add tags (or general taxonomy ) block [#39966](https://github.com/woocommerce/woocommerce/pull/39966)
|
||||
* Add - Add track events to customize store AI wizard [#40144](https://github.com/woocommerce/woocommerce/pull/40144)
|
||||
* Add - Add track events to customize store transitional page [#40143](https://github.com/woocommerce/woocommerce/pull/40143)
|
||||
* Add - Add Tracks events to Appearance > Themes screen [#40193](https://github.com/woocommerce/woocommerce/pull/40193)
|
||||
* Add - Add tracks to CYS assembler-hub and hide pages sidebar screen [#40156](https://github.com/woocommerce/woocommerce/pull/40156)
|
||||
* Add - Add variable product experiment [#40177](https://github.com/woocommerce/woocommerce/pull/40177)
|
||||
* Add - Add woocommerce_block_template_register action. [#39915](https://github.com/woocommerce/woocommerce/pull/39915)
|
||||
* Add - Create a plugin to enable Variations feature #40027 [#40027](https://github.com/woocommerce/woocommerce/pull/40027)
|
||||
* Add - Implement customize store assembler hub - logo feature [#39932](https://github.com/woocommerce/woocommerce/pull/39932)
|
||||
* Add - Implemented loader design for Customize your store - Design with AI [#40083](https://github.com/woocommerce/woocommerce/pull/40083)
|
||||
* Add - Made ai completion for look and tone more robust and added tracks [#40052](https://github.com/woocommerce/woocommerce/pull/40052)
|
||||
* Add - Records plugin API requests and installation errors to coreprofiler_install_plugin_error separately for the core profiler. [#39899](https://github.com/woocommerce/woocommerce/pull/39899)
|
||||
* Update - Added Marketplace class as basis for Reactified marketplace. [#39121](https://github.com/woocommerce/woocommerce/pull/39121)
|
||||
* Update - Added xstate scaffolding for AI Wizard in customize your store feature [#39863](https://github.com/woocommerce/woocommerce/pull/39863)
|
||||
* Update - Display a custom WooPayments onboarding task header content, when an incentive with server based header is available. [#40034](https://github.com/woocommerce/woocommerce/pull/40034)
|
||||
* Update - Implement customize your store task completion logic [#40267](https://github.com/woocommerce/woocommerce/pull/40267)
|
||||
* Update - Optimize customize store preview frame resize performance [#39930](https://github.com/woocommerce/woocommerce/pull/39930)
|
||||
* Update - Remove core-profiler checks from the tests -- core profiler is enabled by default now. [#40260](https://github.com/woocommerce/woocommerce/pull/40260)
|
||||
* Update - Replace Personalize Your Store task with Choose Your Theme [#40239](https://github.com/woocommerce/woocommerce/pull/40239)
|
||||
* Update - Track coreprofiler_store_extensions_installed_and_activated when async installation is complete [#39921](https://github.com/woocommerce/woocommerce/pull/39921)
|
||||
* Update - Turn off the experimental flag for HPOS. [#39846](https://github.com/woocommerce/woocommerce/pull/39846)
|
||||
* Update - Update Action Scheduler to 3.6.3 [#40147](https://github.com/woocommerce/woocommerce/pull/40147)
|
||||
* Update - Update intro screen for the new Customize Your Store task [#40293](https://github.com/woocommerce/woocommerce/pull/40293)
|
||||
* Update - Update Remote Inbox Notifications to add in and !in comparison operators for comparing values against arrays [#40084](https://github.com/woocommerce/woocommerce/pull/40084)
|
||||
* Update - Update the simple product template implementation to use the product form template API. [#39814](https://github.com/woocommerce/woocommerce/pull/39814)
|
||||
* Update - Update use of preventLeavingProductForm with new function changes. [#40225](https://github.com/woocommerce/woocommerce/pull/40225)
|
||||
* Update - Update WooCommerce Blocks to 10.9.3 [#39895](https://github.com/woocommerce/woocommerce/pull/39895)
|
||||
* Update - Update WooCommerce Blocks to 11.0.0 [#39971](https://github.com/woocommerce/woocommerce/pull/39971)
|
||||
* Update - Update WooCommerce Blocks to 11.1.0 [#40141](https://github.com/woocommerce/woocommerce/pull/40141)
|
||||
* Update - Update WooCommerce Blocks to 11.1.1 [#40300](https://github.com/woocommerce/woocommerce/pull/40300)
|
||||
* Update - Update WooCommerce Blocks to 11.1.2 [#40475](https://github.com/woocommerce/woocommerce/pull/40475)
|
||||
* Update - We have completely redesigned the In-app Marketplace. [#39121](https://github.com/woocommerce/woocommerce/pull/39121)
|
||||
* Dev - Added documentation for the Core Profiler [#39963](https://github.com/woocommerce/woocommerce/pull/39963)
|
||||
* Dev - Add job to post Slack summary of plugin test results in "Smoke test daily" workflow. [#39838](https://github.com/woocommerce/woocommerce/pull/39838)
|
||||
* Dev - Add new E2E test covering shopper product page and make Product-related tests granular (separated test files) [#40132](https://github.com/woocommerce/woocommerce/pull/40132)
|
||||
* Dev - Add notice to "track inventory" toggle #40011 [#40011](https://github.com/woocommerce/woocommerce/pull/40011)
|
||||
* Dev - Add some basic E2E tests for Assembler Hub [#40235](https://github.com/woocommerce/woocommerce/pull/40235)
|
||||
* Dev - Adds test to check required fields on checkout [#40099](https://github.com/woocommerce/woocommerce/pull/40099)
|
||||
* Dev - Bump required PHP version to 7.4 [#39820](https://github.com/woocommerce/woocommerce/pull/39820)
|
||||
* Dev - Cleanup: remove the unused is_feature_visible and show_feature methods. [#39931](https://github.com/woocommerce/woocommerce/pull/39931)
|
||||
* Dev - Fixes and enables API test suite to run on daily CI run against alternate host [#39858](https://github.com/woocommerce/woocommerce/pull/39858)
|
||||
* Dev - Fix flakiness around the `Turn off the new product form` menu item. [#39957](https://github.com/woocommerce/woocommerce/pull/39957)
|
||||
* Dev - Fix for a couple of flaky API tests on daily runs [#39918](https://github.com/woocommerce/woocommerce/pull/39918)
|
||||
* Dev - Improve documentation for the `is_checkout()` function. [#40258](https://github.com/woocommerce/woocommerce/pull/40258)
|
||||
* Dev - Refactored core profiler loader to be more generalizable and moved to @woocommerce/onboarding [#39735](https://github.com/woocommerce/woocommerce/pull/39735)
|
||||
* Dev - Remove "WP Latest-2" from release tests. [#40012](https://github.com/woocommerce/woocommerce/pull/40012)
|
||||
* Dev - Remove legacy PHP version update checks [#39845](https://github.com/woocommerce/woocommerce/pull/39845)
|
||||
* Dev - Run a full reset on API daily test site [#40061](https://github.com/woocommerce/woocommerce/pull/40061)
|
||||
* Dev - Updates Playwright from 1.33 to 1.37.1 [#39815](https://github.com/woocommerce/woocommerce/pull/39815)
|
||||
* Tweak - Add order property to every block in SimpleProductTemplate [#39946](https://github.com/woocommerce/woocommerce/pull/39946)
|
||||
* Tweak - Adds an informative tooltip to the Account Details section of the Direct Bank Transfer settings. [#39860](https://github.com/woocommerce/woocommerce/pull/39860)
|
||||
* Tweak - Fix a minor code typo, no change in functionality [#36402](https://github.com/woocommerce/woocommerce/pull/36402)
|
||||
* Tweak - Make it easier to disable email verification checks for the order confirmation and order pay pages. [#40050](https://github.com/woocommerce/woocommerce/pull/40050)
|
||||
* Tweak - Migrate category field to woocommerce/product-taxonomy-field block [#40021](https://github.com/woocommerce/woocommerce/pull/40021)
|
||||
* Tweak - tweak some of the HPOS Settings UI. [#39912](https://github.com/woocommerce/woocommerce/pull/39912)
|
||||
* Tweak - Tweak tasklist description color to darker [#39903](https://github.com/woocommerce/woocommerce/pull/39903)
|
||||
* Enhancement - Add CLI commands to enable or disable HPOS. [#39865](https://github.com/woocommerce/woocommerce/pull/39865)
|
||||
* Enhancement - Design enhancements for the Attributes tab. [#39987](https://github.com/woocommerce/woocommerce/pull/39987)
|
||||
* Enhancement - Design enhancements for the Inventory tab. [#39962](https://github.com/woocommerce/woocommerce/pull/39962)
|
||||
* Enhancement - Enable HPOS by default for new installs. [#40296](https://github.com/woocommerce/woocommerce/pull/40296)
|
||||
* Enhancement - Improve the existing E2E test to verify one more element on each page load. [#40008](https://github.com/woocommerce/woocommerce/pull/40008)
|
||||
* Enhancement - Update the default setting for the task list progress bar from 0 to 0.25, which gives the progress better visual context when no tasks have been completed. [#39369](https://github.com/woocommerce/woocommerce/pull/39369)
|
||||
* Enhancement - Update Venezuelan currency: Bolívar (Bs.). [#29380](https://github.com/woocommerce/woocommerce/pull/29380)
|
||||
|
||||
|
||||
= 8.1.1 2023-09-18 =
|
||||
|
||||
**WooCommerce**
|
||||
|
|
|
@ -0,0 +1,449 @@
|
|||
{
|
||||
"posts": [
|
||||
{
|
||||
"edit_url": "https://github.com/woocommerce/woocommerce/edit/trunk/docs/style-guide.md",
|
||||
"hash": "e81f1f926568e1792b6814c735c0321dee1356b4f8c053b7a5ee1770440e8052",
|
||||
"url": "https://raw.githubusercontent.com/woocommerce/woocommerce/trunk/docs/style-guide.md",
|
||||
"id": "211490a474b1b2ce6a6fc670b159f3497d6a9054"
|
||||
},
|
||||
{
|
||||
"edit_url": "https://github.com/woocommerce/woocommerce/edit/trunk/docs/README.md",
|
||||
"hash": "b1a13c53d16ba2a1b089a0cf19c5c37a8181f33bdbe0c6ee106cd1c80aef9fa0",
|
||||
"url": "https://raw.githubusercontent.com/woocommerce/woocommerce/trunk/docs/README.md",
|
||||
"id": "2c20e49a2bfd5bfcbb318dedbec96ada77784f14",
|
||||
"links": {
|
||||
"extension-development/building-your-first-extension.md": "bfb30a2379ec5e7c7960192b0a9175191e39aef7",
|
||||
"extension-development/how-to-design-a-simple-extension.md": "c2f4612f31cc3892bfb19c6e9859f2daccdb6fa0",
|
||||
"style-guide.md": "211490a474b1b2ce6a6fc670b159f3497d6a9054",
|
||||
"../plugins/woocommerce/README.md": "827066d08695e5002bf059cd2e9d4d2a0fa58df8",
|
||||
"../plugins/woocommerce/i18n/languages/README.md": "826a4400174812dfabb978c87ff2742bfdf28d62",
|
||||
"../plugins/woocommerce/includes/README.md": "3d07aabeb0926e4c675e5770e78a0cfa537d2f56",
|
||||
"../plugins/woocommerce/lib/README.md": "7c7e05959e4e9dcde4ac0e3e2a13258d7521e731",
|
||||
"../plugins/woocommerce/packages/README.md": "740c206346a48e9dcb2e70efd5a3221992c389dc",
|
||||
"../plugins/woocommerce/src/README.md": "c7444c322c5bb1ff755b2bf3e961babf3a879f4e",
|
||||
"../plugins/woocommerce/src/Admin/RemoteInboxNotifications/README.md": "a46d35b9e8a8c15b89082e0c2c04d83c852d545f",
|
||||
"../plugins/woocommerce/src/Admin/RemoteInboxNotifications/Transformers/README.md": "bbccc83ae18c86679a3b632e7203f6c395987967",
|
||||
"../plugins/woocommerce/src/Blocks/README.md": "532a6602e970797759269b4c588c724551379214",
|
||||
"../plugins/woocommerce/src/Internal/README.md": "67d669be90b641e2273194796e3d9bdfdbd69a7e",
|
||||
"../plugins/woocommerce/src/Internal/Admin/ProductForm/README.md": "1d691e34fd20dd268e8e9f8283f46a595758c33b",
|
||||
"../plugins/woocommerce/tests/README.md": "722532b12b14b2f5c0b8efdd96cca1854bba38c4",
|
||||
"../plugins/woocommerce/tests/api-core-tests/README.md": "b000db6a9a2807a49a3bb47c57bb78326a865c78",
|
||||
"../plugins/woocommerce/tests/e2e/README.md": "c15296a46be7331ed23d791073cdebeb0f4c48c4",
|
||||
"../plugins/woocommerce/tests/e2e-pw/README.md": "103a9a613a34a031b34ca48f0895640dc9fc2b10",
|
||||
"../plugins/woocommerce/tests/performance/README.md": "8c14e3b9fac89bced565b78e96d3a3a89e0a568e",
|
||||
"../plugins/woocommerce/tests/Tools/CodeHacking/README.md": "231d9fc132423f1ecc391aaf1bcb57a3cd749d24",
|
||||
"../plugins/woocommerce-admin/README.md": "9ba7a7e2c4411e01c70d866f8b8b5604484368d8",
|
||||
"../plugins/woocommerce-admin/client/activity-panel/README.md": "2de9812a153a9c9ed90588feacd9ece41ecff93c",
|
||||
"../plugins/woocommerce-admin/client/activity-panel/activity-card/README.md": "c34672cf87665e3ff157c6df3ddf1993fd33e7a4",
|
||||
"../plugins/woocommerce-admin/client/activity-panel/activity-header/README.md": "13e379fd37082d3cba36e76046acfc63ff70ab8a",
|
||||
"../plugins/woocommerce-admin/client/analytics/report/README.md": "84430b89912cb95d31240cd2d00a400b2d904ec4",
|
||||
"../plugins/woocommerce-admin/client/analytics/settings/README.md": "421781cef9f3d0160c1e3892488b21b3f4a2a7f5",
|
||||
"../plugins/woocommerce-admin/client/dashboard/README.md": "f7d6ff3c0f18554161afaa94698fb127f098986f",
|
||||
"../plugins/woocommerce-admin/client/header/README.md": "39d3152fc1be21beee488dddd3f5a90e6af2502a",
|
||||
"../plugins/woocommerce-admin/client/marketing/README.md": "54f1eb4cf5ec67713ce2fdf2b2f1dc28b03e35ef",
|
||||
"../plugins/woocommerce-admin/client/marketing/components/product-icon/README.md": "3fa5081872b79078ad320dd0d9e218ed4148dc4e",
|
||||
"../plugins/woocommerce-admin/client/utils/README.md": "0486d6a8f01b89bf171e21678df5dae9b5791a99",
|
||||
"../plugins/woocommerce-admin/client/wp-admin-scripts/README.md": "641ab0c131d812f0969631b44ed9e8fe3fdb0cba",
|
||||
"../plugins/woocommerce-admin/docs/README.md": "25155a38fc7599a01bfb30eb31a1edb098b59219",
|
||||
"../plugins/woocommerce-admin/docs/examples/README.md": "b5ca126b81199d9da6ae62d5d26c093f88405a06",
|
||||
"../plugins/woocommerce-admin/docs/examples/extensions/README.md": "42a90d07061074d0de1b15aeaf80531f83b2a258",
|
||||
"../plugins/woocommerce-admin/docs/features/README.md": "1ee849cb8dc013ffbfe8ebcb54b8cc83f39d72e4",
|
||||
"../plugins/woocommerce-admin/docs/woocommerce.com/README.md": "ee127fc0f256c3ae546869c602e94b4a6e258be8",
|
||||
"../plugins/woocommerce-beta-tester/README.md": "081da0cc3caba15e926b606082120c2692b71ad4",
|
||||
"../plugins/woocommerce-beta-tester/src/tools/README.md": "aedc38bbe8b29e676a15d252bcb1be38acc86f3c",
|
||||
"../plugins/woocommerce-beta-tester/userscripts/README.md": "d3d94172608c29c4968ee73858ee3575a2cc11ce"
|
||||
}
|
||||
}
|
||||
],
|
||||
"categories": [
|
||||
{
|
||||
"posts": [
|
||||
{
|
||||
"edit_url": "https://github.com/woocommerce/woocommerce/edit/trunk/docs/code-snippets/unhook--remove-woocommerce-emails.md",
|
||||
"hash": "a22ec5c7c7c670e97e34a438d5e13dc3709716484efbecbf49e5917b6da9079d",
|
||||
"url": "https://raw.githubusercontent.com/woocommerce/woocommerce/trunk/docs/code-snippets/unhook--remove-woocommerce-emails.md",
|
||||
"id": "517b5bdeb798c1832c3ba76670e728b7b922d5d1"
|
||||
},
|
||||
{
|
||||
"edit_url": "https://github.com/woocommerce/woocommerce/edit/trunk/docs/code-snippets/rename-a-country.md",
|
||||
"hash": "3929e2145dcaad30a83fda6d82d973028e4463eeb2f6a6ba6ff9cb70c6b52fd5",
|
||||
"url": "https://raw.githubusercontent.com/woocommerce/woocommerce/trunk/docs/code-snippets/rename-a-country.md",
|
||||
"id": "2197550f7fdfbce39155865ba36f1f396a35e4a6"
|
||||
},
|
||||
{
|
||||
"edit_url": "https://github.com/woocommerce/woocommerce/edit/trunk/docs/code-snippets/number-of-products-per-row.md",
|
||||
"hash": "507e7be407716b56fe577109b296b55cdcb48cb2b2e339a761446b4df2d730e9",
|
||||
"url": "https://raw.githubusercontent.com/woocommerce/woocommerce/trunk/docs/code-snippets/number-of-products-per-row.md",
|
||||
"id": "7da8ddcdbc3f427d14b040015fb1de9efde79d19"
|
||||
},
|
||||
{
|
||||
"edit_url": "https://github.com/woocommerce/woocommerce/edit/trunk/docs/code-snippets/change-a-currency-symbol.md",
|
||||
"hash": "4485b212ff7bdf7fd8c23dc589dbbb6263a530623b939b384297f2377b11056f",
|
||||
"url": "https://raw.githubusercontent.com/woocommerce/woocommerce/trunk/docs/code-snippets/change-a-currency-symbol.md",
|
||||
"id": "de0e6701b0e15a209ac6ed3c100b34f67237ea96"
|
||||
},
|
||||
{
|
||||
"edit_url": "https://github.com/woocommerce/woocommerce/edit/trunk/docs/code-snippets/before-login--register-form.md",
|
||||
"hash": "3435f3859ec047566696ae5474df697c99a6e1ab04168ae8f1ca831abc519d67",
|
||||
"url": "https://raw.githubusercontent.com/woocommerce/woocommerce/trunk/docs/code-snippets/before-login--register-form.md",
|
||||
"id": "5acf55bdb90174bc00a10816ca71a8846bd7040f"
|
||||
},
|
||||
{
|
||||
"edit_url": "https://github.com/woocommerce/woocommerce/edit/trunk/docs/code-snippets/adjust-quantity-input-values.md",
|
||||
"hash": "056fb597c07e0e82b92ca8a2c484166f807d3d513fa950cb5c46a8db087fe986",
|
||||
"url": "https://raw.githubusercontent.com/woocommerce/woocommerce/trunk/docs/code-snippets/adjust-quantity-input-values.md",
|
||||
"id": "06d0ddda56838dc22ad94716aca95a1f2a9ad67c"
|
||||
},
|
||||
{
|
||||
"edit_url": "https://github.com/woocommerce/woocommerce/edit/trunk/docs/code-snippets/add-or-modify-states.md",
|
||||
"hash": "d61d5051439b0cbf949be64958c8101a7c6487672a7b79dd3f528e9c1a5b408e",
|
||||
"url": "https://raw.githubusercontent.com/woocommerce/woocommerce/trunk/docs/code-snippets/add-or-modify-states.md",
|
||||
"id": "10568c46b0baa2f8ea01a8cd9dd6b2d65d35aafc"
|
||||
},
|
||||
{
|
||||
"edit_url": "https://github.com/woocommerce/woocommerce/edit/trunk/docs/code-snippets/add-a-currency-symbol.md",
|
||||
"hash": "0053a87328ee04a168c5657df26cf18f219d30669b000300ace4284ea2333186",
|
||||
"url": "https://raw.githubusercontent.com/woocommerce/woocommerce/trunk/docs/code-snippets/add-a-currency-symbol.md",
|
||||
"id": "6d63d431fa1d66af7b3b47861ccc940775eba397"
|
||||
},
|
||||
{
|
||||
"edit_url": "https://github.com/woocommerce/woocommerce/edit/trunk/docs/code-snippets/add-a-country.md",
|
||||
"hash": "9305a5ed51cc0174e19e68ebc94801c5e7d6e62e820d106f35175540b0531d10",
|
||||
"url": "https://raw.githubusercontent.com/woocommerce/woocommerce/trunk/docs/code-snippets/add-a-country.md",
|
||||
"id": "7c591c3bd31cb2942fdcb4f77da167bc9ec36207"
|
||||
}
|
||||
],
|
||||
"categories": []
|
||||
},
|
||||
{
|
||||
"category_title": "Contributing",
|
||||
"posts": [
|
||||
{
|
||||
"edit_url": "https://github.com/woocommerce/woocommerce/edit/trunk/docs/contributing/deciding-pr-high-impact.md",
|
||||
"hash": "6d9ddea0e44e1ab9f7b12183069c7fde51df26c9bcad15d8b6f9d3ab17ee1fe0",
|
||||
"url": "https://raw.githubusercontent.com/woocommerce/woocommerce/trunk/docs/contributing/deciding-pr-high-impact.md",
|
||||
"id": "cee3a746887c88f92966bb72ec1847aa5d97cebd"
|
||||
}
|
||||
],
|
||||
"categories": []
|
||||
},
|
||||
{
|
||||
"category_title": "Data-management",
|
||||
"posts": [
|
||||
{
|
||||
"edit_url": "https://github.com/woocommerce/woocommerce/edit/trunk/docs/data-management/data-stores.md",
|
||||
"hash": "7af9424c5b3fdfa5b30b658f0c3a452ac12d67390b58e9c23ef3bc71412b2a92",
|
||||
"url": "https://raw.githubusercontent.com/woocommerce/woocommerce/trunk/docs/data-management/data-stores.md",
|
||||
"id": "72609f6c4fecccf2881c76bb8f21fc6a2d3cfef5"
|
||||
},
|
||||
{
|
||||
"edit_url": "https://github.com/woocommerce/woocommerce/edit/trunk/docs/data-management/crud-objects.md",
|
||||
"hash": "9b687cd323893ed0fc012ad82e67a329ea0f41c312017bfdf3015ab7ef51a23a",
|
||||
"url": "https://raw.githubusercontent.com/woocommerce/woocommerce/trunk/docs/data-management/crud-objects.md",
|
||||
"id": "0214be4dc9e0ddcc6d6a175fcd2f2b9fd4c8b042"
|
||||
}
|
||||
],
|
||||
"categories": []
|
||||
},
|
||||
{
|
||||
"posts": [
|
||||
{
|
||||
"edit_url": "https://github.com/woocommerce/woocommerce/edit/trunk/docs/extension-development/tools-for-low-code-development.md",
|
||||
"hash": "5989c60346c29c019332b7e2faee0dfcddf063db2d12f22f7755525e99c8ba4a",
|
||||
"url": "https://raw.githubusercontent.com/woocommerce/woocommerce/trunk/docs/extension-development/tools-for-low-code-development.md",
|
||||
"id": "9db13086ff88d75fc5d5cd7bd36820b2d372b288"
|
||||
},
|
||||
{
|
||||
"edit_url": "https://github.com/woocommerce/woocommerce/edit/trunk/docs/extension-development/readme.md",
|
||||
"hash": "e22a09b0d39adf37cd19fa57263e1195646f766396a36571411c54c64c6ba5a1",
|
||||
"url": "https://raw.githubusercontent.com/woocommerce/woocommerce/trunk/docs/extension-development/readme.md",
|
||||
"id": "4946a26f3f2ba63d5db65033a90b6dda3a43a4ee"
|
||||
},
|
||||
{
|
||||
"edit_url": "https://github.com/woocommerce/woocommerce/edit/trunk/docs/extension-development/how-to-design-a-simple-extension.md",
|
||||
"hash": "893c9361b6a1f6cd8a83dc9a4500c9b3050d66ef6d567fddf56d68de01d182a1",
|
||||
"url": "https://raw.githubusercontent.com/woocommerce/woocommerce/trunk/docs/extension-development/how-to-design-a-simple-extension.md",
|
||||
"id": "c2f4612f31cc3892bfb19c6e9859f2daccdb6fa0"
|
||||
},
|
||||
{
|
||||
"edit_url": "https://github.com/woocommerce/woocommerce/edit/trunk/docs/extension-development/how-to-add-your-own-store-management-links.md",
|
||||
"hash": "59dfa1f941a2fafaccedf2dd9be5bc1ee8c34b7320c6589c860ad98403bcd273",
|
||||
"url": "https://raw.githubusercontent.com/woocommerce/woocommerce/trunk/docs/extension-development/how-to-add-your-own-store-management-links.md",
|
||||
"id": "461423141956d0653582aa15956a7b0401301cf6"
|
||||
},
|
||||
{
|
||||
"edit_url": "https://github.com/woocommerce/woocommerce/edit/trunk/docs/extension-development/handling-merchant-onboarding.md",
|
||||
"hash": "e4a8358de815e378beb07426fd5687a0e91792f70a697574edd5031bf073c08d",
|
||||
"url": "https://raw.githubusercontent.com/woocommerce/woocommerce/trunk/docs/extension-development/handling-merchant-onboarding.md",
|
||||
"id": "878874b744cea792a439935c67ac833a5f7d8796"
|
||||
},
|
||||
{
|
||||
"edit_url": "https://github.com/woocommerce/woocommerce/edit/trunk/docs/extension-development/handling-deactivation-and-uninstallation.md",
|
||||
"hash": "cfc8cdf9e9a41e69cf40dcc1548cf7b0231c51c33c504ee800dd7525afe6d483",
|
||||
"url": "https://raw.githubusercontent.com/woocommerce/woocommerce/trunk/docs/extension-development/handling-deactivation-and-uninstallation.md",
|
||||
"id": "93a623f5b7ff808c92541941787bdc2101518f5a"
|
||||
},
|
||||
{
|
||||
"edit_url": "https://github.com/woocommerce/woocommerce/edit/trunk/docs/extension-development/extension-developer-handbook.md",
|
||||
"hash": "ff87298651dff8672b0c0da8693b53cb19d1fe7e65f04a947029aeec9cc9896f",
|
||||
"url": "https://raw.githubusercontent.com/woocommerce/woocommerce/trunk/docs/extension-development/extension-developer-handbook.md",
|
||||
"id": "9f22e410b1ff4f6e5c22f6b4567c1a676d037295"
|
||||
},
|
||||
{
|
||||
"edit_url": "https://github.com/woocommerce/woocommerce/edit/trunk/docs/extension-development/development-environment.md",
|
||||
"hash": "811f43ef03b40b48ad72a9d787031cb10d5a17b5f4ef4a2d5c0fa4977b2d43df",
|
||||
"url": "https://raw.githubusercontent.com/woocommerce/woocommerce/trunk/docs/extension-development/development-environment.md",
|
||||
"id": "188b18434a7e844978d4d25a4b1fbc74004294d5"
|
||||
},
|
||||
{
|
||||
"edit_url": "https://github.com/woocommerce/woocommerce/edit/trunk/docs/extension-development/building-your-first-extension.md",
|
||||
"hash": "2aad1fe83142ff55197f3bc560fafbe2c1279ccf9bb727fea5257eed447ba694",
|
||||
"url": "https://raw.githubusercontent.com/woocommerce/woocommerce/trunk/docs/extension-development/building-your-first-extension.md",
|
||||
"id": "bfb30a2379ec5e7c7960192b0a9175191e39aef7"
|
||||
}
|
||||
],
|
||||
"categories": []
|
||||
},
|
||||
{
|
||||
"posts": [
|
||||
{
|
||||
"edit_url": "https://github.com/woocommerce/woocommerce/edit/trunk/docs/getting-started/readme.md",
|
||||
"hash": "8aa7cd66683478dff1f37c767f154d35e6b78a738b604d0bc2ae31a10f920ba6",
|
||||
"url": "https://raw.githubusercontent.com/woocommerce/woocommerce/trunk/docs/getting-started/readme.md",
|
||||
"id": "2145ad4acea5e37b1ff4354bf44a8af9d10c750a"
|
||||
},
|
||||
{
|
||||
"edit_url": "https://github.com/woocommerce/woocommerce/edit/trunk/docs/getting-started/developer-tools.md",
|
||||
"hash": "860d227350f472b610351bf416953bf9401bf0df296ee8ebe2af9c7a9d20fc57",
|
||||
"url": "https://raw.githubusercontent.com/woocommerce/woocommerce/trunk/docs/getting-started/developer-tools.md",
|
||||
"id": "3d8c7c1a9187dd7c96d2561bccfcfa88a8d0102a"
|
||||
},
|
||||
{
|
||||
"edit_url": "https://github.com/woocommerce/woocommerce/edit/trunk/docs/getting-started/developer-resources.md",
|
||||
"hash": "e5417528667f6afb2de5ed1b4f7073a63268e72e163bd67a8a1daeda1e623eb0",
|
||||
"url": "https://raw.githubusercontent.com/woocommerce/woocommerce/trunk/docs/getting-started/developer-resources.md",
|
||||
"id": "0923cb0175b15041bcecf8f9dbc60828052e1fec"
|
||||
},
|
||||
{
|
||||
"edit_url": "https://github.com/woocommerce/woocommerce/edit/trunk/docs/getting-started/debugging.md",
|
||||
"hash": "e8407732d22ffa183db83e5875e6709bdc8dd7ac47a05280590c4b5f1021fea9",
|
||||
"url": "https://raw.githubusercontent.com/woocommerce/woocommerce/trunk/docs/getting-started/debugging.md",
|
||||
"id": "b28ccc6fa293efebd716b510df0331fb222b8a1b",
|
||||
"links": {
|
||||
"../utilities/logging.md": "f673f50bdd83d5d0d7fd8d9976828f8736809510"
|
||||
}
|
||||
}
|
||||
],
|
||||
"categories": []
|
||||
},
|
||||
{
|
||||
"posts": [
|
||||
{
|
||||
"edit_url": "https://github.com/woocommerce/woocommerce/edit/trunk/docs/high-performance-order-storage/readme.md",
|
||||
"hash": "aada6bfad51c9f68ddb61e6475aae137e6b2d91839afa001aa3862ecd651093b",
|
||||
"url": "https://raw.githubusercontent.com/woocommerce/woocommerce/trunk/docs/high-performance-order-storage/readme.md",
|
||||
"id": "214c00235e4efed0a786fd704c4bfde25952a669"
|
||||
},
|
||||
{
|
||||
"edit_url": "https://github.com/woocommerce/woocommerce/edit/trunk/docs/high-performance-order-storage/hpos-overview.md",
|
||||
"hash": "a7504d828aed93aa68fbaff338406682fa6169f9401b2c4de6e750d7f51c7416",
|
||||
"url": "https://raw.githubusercontent.com/woocommerce/woocommerce/trunk/docs/high-performance-order-storage/hpos-overview.md",
|
||||
"id": "380a11e440eb17bc76fb606fecce4ce82fc9b0cb"
|
||||
}
|
||||
],
|
||||
"categories": []
|
||||
},
|
||||
{
|
||||
"posts": [
|
||||
{
|
||||
"edit_url": "https://github.com/woocommerce/woocommerce/edit/trunk/docs/product-editor-development/common-tasks.md",
|
||||
"hash": "a7725479ff8b34f8069f3a8262502dc82354ea50d6ccd3760c5c7f7a9ae58fe2",
|
||||
"url": "https://raw.githubusercontent.com/woocommerce/woocommerce/trunk/docs/product-editor-development/common-tasks.md",
|
||||
"id": "c09542004d78254458250704f3a68cfeb9fa7a7c"
|
||||
}
|
||||
],
|
||||
"categories": []
|
||||
},
|
||||
{
|
||||
"posts": [
|
||||
{
|
||||
"edit_url": "https://github.com/woocommerce/woocommerce/edit/trunk/docs/quality-and-best-practices/readme.md",
|
||||
"hash": "7afc464833ea0eb33127e98cb92f951bcb4a5d9006898e56db9d1f36006970cf",
|
||||
"url": "https://raw.githubusercontent.com/woocommerce/woocommerce/trunk/docs/quality-and-best-practices/readme.md",
|
||||
"id": "f12729345d42760bd61a4a4cfdcebf6dbf2daac4"
|
||||
},
|
||||
{
|
||||
"edit_url": "https://github.com/woocommerce/woocommerce/edit/trunk/docs/quality-and-best-practices/performance-optimization.md",
|
||||
"hash": "cc54a9af29f80e413536f46e70bc17512c92de536375bded23e4893a3e95e262",
|
||||
"url": "https://raw.githubusercontent.com/woocommerce/woocommerce/trunk/docs/quality-and-best-practices/performance-optimization.md",
|
||||
"id": "280d9d16382ef5374226629751cff7fceefbfa62"
|
||||
},
|
||||
{
|
||||
"edit_url": "https://github.com/woocommerce/woocommerce/edit/trunk/docs/quality-and-best-practices/grammar-punctuation-capitalization.md",
|
||||
"hash": "cea26a41342f5e67bb3313c935726da68647827a60c2fb034f3e64dd783496bd",
|
||||
"url": "https://raw.githubusercontent.com/woocommerce/woocommerce/trunk/docs/quality-and-best-practices/grammar-punctuation-capitalization.md",
|
||||
"id": "85d910730d1daa03c86c42f2d4cbd2e146cec83c"
|
||||
},
|
||||
{
|
||||
"edit_url": "https://github.com/woocommerce/woocommerce/edit/trunk/docs/quality-and-best-practices/coding-standards.md",
|
||||
"hash": "332efc3cccdde767237087abba302fcc371d510e5f287d439de49fe99a5445cc",
|
||||
"url": "https://raw.githubusercontent.com/woocommerce/woocommerce/trunk/docs/quality-and-best-practices/coding-standards.md",
|
||||
"id": "3a47d9e0da6c415606b7ee87bb65ed24f4630be1"
|
||||
}
|
||||
],
|
||||
"categories": []
|
||||
},
|
||||
{
|
||||
"posts": [
|
||||
{
|
||||
"edit_url": "https://github.com/woocommerce/woocommerce/edit/trunk/docs/reference-code/readme.md",
|
||||
"hash": "49a289229235989dcb8fa990af7e5017ae37569d6103dfd044ee2d95f250f596",
|
||||
"url": "https://raw.githubusercontent.com/woocommerce/woocommerce/trunk/docs/reference-code/readme.md",
|
||||
"id": "1934f96989f9b62e2caf7fd0ac7deb2292f161ce"
|
||||
}
|
||||
],
|
||||
"categories": []
|
||||
},
|
||||
{
|
||||
"posts": [
|
||||
{
|
||||
"edit_url": "https://github.com/woocommerce/woocommerce/edit/trunk/docs/reporting/readme.md",
|
||||
"hash": "117ccaf1bf931f7a98486ac0b506c48dd4834a2f2acd76f8936a9bf6ba93171b",
|
||||
"url": "https://raw.githubusercontent.com/woocommerce/woocommerce/trunk/docs/reporting/readme.md",
|
||||
"id": "fc4ef6d8e26fc46ef6c9da5e0d860cf051928e12"
|
||||
},
|
||||
{
|
||||
"edit_url": "https://github.com/woocommerce/woocommerce/edit/trunk/docs/reporting/extending-woocommerce-admin-reports.md",
|
||||
"hash": "860c37ab2d1de9744d838e6d3b11eeadb6e6cb11afffa8dfc11021240661d843",
|
||||
"url": "https://raw.githubusercontent.com/woocommerce/woocommerce/trunk/docs/reporting/extending-woocommerce-admin-reports.md",
|
||||
"id": "9960520d4548fd3647c5bbc7ed4d4fcc6a76cfce"
|
||||
},
|
||||
{
|
||||
"edit_url": "https://github.com/woocommerce/woocommerce/edit/trunk/docs/reporting/adding-columns-to-analytics-reports-and-csv-downloads.md",
|
||||
"hash": "e8265405615834b04a02f5406c38e3be8acdd01116b66f08f25f99a86a580948",
|
||||
"url": "https://raw.githubusercontent.com/woocommerce/woocommerce/trunk/docs/reporting/adding-columns-to-analytics-reports-and-csv-downloads.md",
|
||||
"id": "10cabd954ae223ac83f84223611f6d82361f9d9d",
|
||||
"links": {
|
||||
"extending-woocommerce-admin-reports.md": "9960520d4548fd3647c5bbc7ed4d4fcc6a76cfce"
|
||||
}
|
||||
}
|
||||
],
|
||||
"categories": []
|
||||
},
|
||||
{
|
||||
"posts": [
|
||||
{
|
||||
"edit_url": "https://github.com/woocommerce/woocommerce/edit/trunk/docs/rest-api/readme.md",
|
||||
"hash": "895a1986fd30f437c1bc2aaa618d6a06a98c65511cd257077302c2d1225787d9",
|
||||
"url": "https://raw.githubusercontent.com/woocommerce/woocommerce/trunk/docs/rest-api/readme.md",
|
||||
"id": "128b41ed5e9a0ed13a51de3196bd06c0297b2f33"
|
||||
},
|
||||
{
|
||||
"edit_url": "https://github.com/woocommerce/woocommerce/edit/trunk/docs/rest-api/getting-started.md",
|
||||
"hash": "b0bb28f6eed57c7d57dde75e8093771450db4666cbfab16d35387c39cd8d1e20",
|
||||
"url": "https://raw.githubusercontent.com/woocommerce/woocommerce/trunk/docs/rest-api/getting-started.md",
|
||||
"id": "10f52db2464ea2f373eff9a45ce9e8ff40214122",
|
||||
"links": {
|
||||
"_media/permalinks.webp": "5ac10f14cd0ca3ae45a9c089d659fee3ea4d9f22",
|
||||
"_media/keys.png": "7a29fcb3f0b565f4f6983f1e12200d2c4d62907b",
|
||||
"_media/postman.png": "b100bbf70f8889c26fcde6a6daca29be796071de",
|
||||
"_media/insomnia.png": "a50683984998ab518b4b05433ffb1803f2ac135f",
|
||||
"_media/sslerror.png": "5b6825fb0aba7ed55e1641880701c2afd1744ce1",
|
||||
"_media/postman-ssl.png": "7e3523b0340acf908e98ac320f822d00a0710ac5",
|
||||
"_media/insomnia-ssl.png": "84e6406407498b9936d6ef1df5e4c4cc78f75b00"
|
||||
}
|
||||
}
|
||||
],
|
||||
"categories": [
|
||||
{
|
||||
"category_title": "_media",
|
||||
"categories": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"posts": [
|
||||
{
|
||||
"edit_url": "https://github.com/woocommerce/woocommerce/edit/trunk/docs/security/security-best-practices.md",
|
||||
"hash": "ded14bf9c1b5402c9896c795c4c4cbe6165d465de56009c32559f854446bafda",
|
||||
"url": "https://raw.githubusercontent.com/woocommerce/woocommerce/trunk/docs/security/security-best-practices.md",
|
||||
"id": "ee399e729785fec50b90d73b231d321b34ab5ff9"
|
||||
},
|
||||
{
|
||||
"edit_url": "https://github.com/woocommerce/woocommerce/edit/trunk/docs/security/reporting-security-issues.md",
|
||||
"hash": "4a748990a0e3207c9f0828c585c1d2edce14bafee9afc331d43bda0b8ee09aa6",
|
||||
"url": "https://raw.githubusercontent.com/woocommerce/woocommerce/trunk/docs/security/reporting-security-issues.md",
|
||||
"id": "48caba58b4e5b44fc418bb80cf03aa48f87e4cc8"
|
||||
},
|
||||
{
|
||||
"edit_url": "https://github.com/woocommerce/woocommerce/edit/trunk/docs/security/readme.md",
|
||||
"hash": "b484a4886068a33cd8114066262e95a2c8036f1e11d09f0dc63141cd36d85e95",
|
||||
"url": "https://raw.githubusercontent.com/woocommerce/woocommerce/trunk/docs/security/readme.md",
|
||||
"id": "8b4aa089616cbeeedfec301eee17b5a00f669154"
|
||||
}
|
||||
],
|
||||
"categories": []
|
||||
},
|
||||
{
|
||||
"posts": [
|
||||
{
|
||||
"edit_url": "https://github.com/woocommerce/woocommerce/edit/trunk/docs/theme-development/theme-design-ux-guidelines.md",
|
||||
"hash": "bcab4deb86172df46ff775a23b921f8fb4aadd5b5c96085451609a3863642efc",
|
||||
"url": "https://raw.githubusercontent.com/woocommerce/woocommerce/trunk/docs/theme-development/theme-design-ux-guidelines.md",
|
||||
"id": "1abe0b1ff5e3990387c7da7fa5a147430b3282f7"
|
||||
},
|
||||
{
|
||||
"edit_url": "https://github.com/woocommerce/woocommerce/edit/trunk/docs/theme-development/marketplace-guidelines.md",
|
||||
"hash": "5ca562b2f4cabefe47b0d08334f39d56e8d3e6dc31ea347000d3bb221e51d0a1",
|
||||
"url": "https://raw.githubusercontent.com/woocommerce/woocommerce/trunk/docs/theme-development/marketplace-guidelines.md",
|
||||
"id": "f39a348d787fd0cf4a390e70e6f0cbd36b27a283"
|
||||
}
|
||||
],
|
||||
"categories": []
|
||||
},
|
||||
{
|
||||
"posts": [
|
||||
{
|
||||
"edit_url": "https://github.com/woocommerce/woocommerce/edit/trunk/docs/tutorials/readme.md",
|
||||
"hash": "2ca52b9289180adad5d59865ca45c50098119b420662d727d739243e6a98131a",
|
||||
"url": "https://raw.githubusercontent.com/woocommerce/woocommerce/trunk/docs/tutorials/readme.md",
|
||||
"id": "0741650e7ad7567b84f776db7ddad2b8f5a598ea"
|
||||
},
|
||||
{
|
||||
"edit_url": "https://github.com/woocommerce/woocommerce/edit/trunk/docs/tutorials/adding-actions-and-filters.md",
|
||||
"hash": "fa6bc021c918aa168023a90e683832455dfa35abbb2561470b08002f1281356f",
|
||||
"url": "https://raw.githubusercontent.com/woocommerce/woocommerce/trunk/docs/tutorials/adding-actions-and-filters.md",
|
||||
"id": "3f4d6dcdbc181b11c97c438132ec13a0a8484524"
|
||||
},
|
||||
{
|
||||
"edit_url": "https://github.com/woocommerce/woocommerce/edit/trunk/docs/tutorials/adding-a-custom-field-to-variable-products.md",
|
||||
"hash": "a6b654234e7c7f1fc3f9be49b7d00187d6f271e2d699971bade3cf9a728a780a",
|
||||
"url": "https://raw.githubusercontent.com/woocommerce/woocommerce/trunk/docs/tutorials/adding-a-custom-field-to-variable-products.md",
|
||||
"id": "f0a7a4a194a6e0aee6f939791f3eaebf36aebb27"
|
||||
}
|
||||
],
|
||||
"categories": []
|
||||
},
|
||||
{
|
||||
"category_title": "Utilities",
|
||||
"posts": [
|
||||
{
|
||||
"edit_url": "https://github.com/woocommerce/woocommerce/edit/trunk/docs/utilities/logging.md",
|
||||
"hash": "8912094df57a66c047fe2177be815a40024b461a10ddd61ed297c4b2c2919d64",
|
||||
"url": "https://raw.githubusercontent.com/woocommerce/woocommerce/trunk/docs/utilities/logging.md",
|
||||
"id": "f673f50bdd83d5d0d7fd8d9976828f8736809510",
|
||||
"links": {
|
||||
"_media/log-critical.jpg": "cc802f94ac4cf125a66bc6bb77bf95b80bf4fbed"
|
||||
}
|
||||
}
|
||||
],
|
||||
"categories": [
|
||||
{
|
||||
"category_title": "_media",
|
||||
"categories": []
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"hash": "fc6ee378adfa92b706b9d0813f541bf6e8029634c0dd6623000f76047316f0af"
|
||||
}
|
|
@ -0,0 +1,110 @@
|
|||
# Settings API
|
||||
|
||||
The WooCommerce Settings API is used by extensions to display, save, and load settings. The best way to make use of the API in your extension is to create a class that extends the `WC_Settings_API` class:
|
||||
|
||||
```php
|
||||
class My_Extension_Settings extends WC_Settings_API {
|
||||
//
|
||||
}
|
||||
```
|
||||
|
||||
## Defining form fields
|
||||
|
||||
You can define your fields using a method called `init_form_fields` in your class constructor:
|
||||
|
||||
```php
|
||||
$this->init_form_fields();
|
||||
```
|
||||
|
||||
You must have your settings defined before you can load them. Setting definitions go in the `form_fields` array:
|
||||
|
||||
```php
|
||||
/**
|
||||
* Initialise gateway settings form fields.
|
||||
*/
|
||||
function init_form_fields() {
|
||||
$this->form_fields = array(
|
||||
'title' => array(
|
||||
'title' => __( 'Title', 'your-text-domain' ),
|
||||
'type' => 'text',
|
||||
'description' => __( 'This controls the title which the user sees during checkout.', 'your-text-domain' ),
|
||||
'default' => __( 'PayPal', 'your-text-domain' )
|
||||
),
|
||||
'description' => array(
|
||||
'title' => __( 'Description', 'your-text-domain' ),
|
||||
'type' => 'textarea',
|
||||
'description' => __( 'This controls the description which the user sees during checkout.', 'your-text-domain' ),
|
||||
'default' => __( "Pay via PayPal; you can pay with your credit card if you don't have a PayPal account", 'your-text-domain' )
|
||||
)
|
||||
);
|
||||
} // End init_form_fields()
|
||||
```
|
||||
|
||||
(Make sure your class initializes the `form_fields` property so that the "Creation of dynamic property" error is not thrown in PHP 8.2+)
|
||||
|
||||
In the above example we define two settings, Title and Description. Title is a text box, whereas Description is a textarea. Notice how you can define a default value and a description for the setting itself.
|
||||
|
||||
Setting definitions use the following format:
|
||||
|
||||
```php
|
||||
'setting_name' => array(
|
||||
'title' => 'Title for your setting shown on the settings page',
|
||||
'description' => 'Description for your setting shown on the settings page',
|
||||
'type' => 'text|password|textarea|checkbox|select|multiselect',
|
||||
'default' => 'Default value for the setting',
|
||||
'class' => 'Class for the input element',
|
||||
'css' => 'CSS rules added inline on the input element',
|
||||
'label' => 'Label', // For checkbox inputs only.
|
||||
'options' => array( // Array of options for select/multiselect inputs only.
|
||||
'key' => 'value'
|
||||
),
|
||||
)
|
||||
```
|
||||
|
||||
## Displaying your settings
|
||||
|
||||
Create a method called `admin_options` containing the following:
|
||||
|
||||
```php
|
||||
function admin_options() {
|
||||
?>
|
||||
<h2><?php esc_html_e( 'Your plugin name', 'your-text-domain' ); ?></h2>
|
||||
<table class="form-table">
|
||||
<?php $this->generate_settings_html(); ?>
|
||||
</table>
|
||||
<?php
|
||||
}
|
||||
```
|
||||
|
||||
This will output your settings in the correct format.
|
||||
|
||||
## Saving your settings
|
||||
|
||||
To have your settings save, add your class's `process_admin_options` method to the appropriate `_update_options_` hook. For example, payment gateways should use the payment gateway hook:
|
||||
|
||||
```php
|
||||
add_action( 'woocommerce_update_options_payment_gateways', array( $this, 'process_admin_options' ) );
|
||||
```
|
||||
|
||||
Other types of plugins have similar hooks:
|
||||
|
||||
```php
|
||||
add_action( 'woocommerce_update_options_shipping_methods', array( $this, 'process_admin_options' ) );
|
||||
```
|
||||
|
||||
## Loading your settings
|
||||
|
||||
In the constructor you can load the settings you previously defined:
|
||||
|
||||
```php
|
||||
// Load the settings.
|
||||
$this->init_settings();
|
||||
```
|
||||
|
||||
After that you can load your settings from the settings API. The `init_settings` method above populates the settings variable for you:
|
||||
|
||||
```php
|
||||
// Define user set variables
|
||||
$this->title = $this->settings['title'];
|
||||
$this->description = $this->settings['description'];
|
||||
```
|
|
@ -0,0 +1,38 @@
|
|||
# Product Editor Development Handbook
|
||||
|
||||
> ⚠️ **Notice:** This documentation is currently a **work in progress**. Please be aware that some sections might be incomplete or subject to change. We appreciate your patience and welcome any contributions!
|
||||
|
||||
This handbook is a guide for extension developers looking to add support for the new product editor in their extensions. The product editor uses [Gutenberg's Block Editor](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-editor), which is going to help WooCommerce evolve alongside the WordPress ecosystem.
|
||||
|
||||
The product editor's UI consists of Groups (currently rendered as tabs), Sections, and Fields, which are all blocks.
|
||||
|
||||
![Product editor structure](https://woocommerce.files.wordpress.com/2023/09/groups-sections-fields.jpg)
|
||||
|
||||
The form's structure is defined in PHP using a Template, which is a tree structure of blocks. The template can be modified by using the Template API to add new Groups, Sections, and Fields as well as remove existing ones.
|
||||
|
||||
Many extensibility implementations can be done using only the PHP-based Block Template API alongside our library of [generic blocks](../../packages/js/product-editor/src/blocks/generic/README.md). More complex interactivity can be implemented using JavaScript and React (the same library used to implement the core blocks used in the product editor). [@woocommerce/create-product-editor-block](../../packages/js/create-product-editor-block/README.md) can help scaffold a development environment with JavaScript and React.
|
||||
|
||||
## Declaring compatibility with the product editor
|
||||
|
||||
To declare compatibility with the product editor, add the following to your plugin's root PHP file:
|
||||
|
||||
```php
|
||||
use Automattic\WooCommerce\Utilities\FeaturesUtil;
|
||||
|
||||
add_action(
|
||||
'before_woocommerce_init',
|
||||
function() {
|
||||
if ( class_exists( FeaturesUtil::class ) ) {
|
||||
FeaturesUtil::declare_compatibility( 'product_block_editor', plugin_basename( __FILE__ ), true );
|
||||
}
|
||||
}
|
||||
);
|
||||
```
|
||||
|
||||
Please note that this check is currently not being enforced: the product editor can still be enabled even without this declaration. However, we might enforce this in the future, so it is recommended to declare compatibility as soon as possible.
|
||||
|
||||
## Related documentation
|
||||
|
||||
- [Examples on Template API usage](../../plugins/woocommerce/src/Admin/Features/ProductBlockEditor/ProductTemplates/README.md)
|
||||
- [Related hooks and Template API documentation](../../plugins/woocommerce/src/Admin/BlockTemplates/README.md)
|
||||
- [Generic blocks documentation](../../packages/js/product-editor/src/blocks/generic/README.md)
|
|
@ -0,0 +1,62 @@
|
|||
# CSS/Sass Naming Conventions
|
||||
|
||||
Table of Contents:
|
||||
|
||||
- [Introduction](#introduction)
|
||||
- [Prefixing](#prefixing)
|
||||
- [Class names](#class-names)
|
||||
- [Example](#example)
|
||||
- [TL;DR](#tldr)
|
||||
|
||||
## Introduction
|
||||
|
||||
Our guidelines are based on those used in [Calypso](https://github.com/Automattic/wp-calypso), which itself follows the [BEM methodology](https://getbem.com/).
|
||||
|
||||
Refer to the [Calypso CSS/Sass Coding Guidelines](https://wpcalypso.wordpress.com/devdocs/docs/coding-guidelines/css.md) for full details.
|
||||
|
||||
Read more about [BEM key concepts](https://en.bem.info/methodology/key-concepts/).
|
||||
|
||||
There are a few differences in WooCommerce which are outlined below.
|
||||
|
||||
## Prefixing
|
||||
|
||||
As a WordPress plugin WooCommerce has to play nicely with WordPress core and other plugins/themes. To minimize conflict potential, all classes should be prefixed with `.woocommerce-`.
|
||||
|
||||
## Class names
|
||||
|
||||
When naming classes, remember:
|
||||
|
||||
- **Block** - Standalone entity that is meaningful on its own. Such as the name of a component.
|
||||
- **Element** - Parts of a block and have no standalone meaning. They are semantically tied to its block.
|
||||
- **Modifier** - Flags on blocks or elements. Use them to change appearance or behavior.
|
||||
|
||||
### Example
|
||||
|
||||
```css
|
||||
/* Block */
|
||||
.woocommerce-loop {}
|
||||
|
||||
/* Nested block */
|
||||
.woocommerce-loop-product {}
|
||||
|
||||
/* Modifier */
|
||||
.woocommerce-loop-product--sale {}
|
||||
|
||||
/* Element */
|
||||
.woocommerce-loop-product__link {}
|
||||
|
||||
/* Element */
|
||||
.woocommerce-loop-product__button-add-to-cart {}
|
||||
|
||||
/* Modifier */
|
||||
.woocommerce-loop-product__button-add-to-cart--added {}
|
||||
```
|
||||
|
||||
**Note:** `.woocommerce-loop-product` is not named as such because the block is nested within `.woocommerce-loop`. It's to be specific so that we can have separate classes for single products, cart products, etc. **Nested blocks do not need to inherit their parents full name.**
|
||||
|
||||
## TL;DR
|
||||
|
||||
- Follow the [WordPress Coding standards for CSS](https://make.wordpress.org/core/handbook/best-practices/coding-standards/css/) unless it contradicts anything here.
|
||||
- Follow [Calypso guidelines for CSS](https://wpcalypso.wordpress.com/devdocs/docs/coding-guidelines/css.md).
|
||||
- Use BEM for [class names](https://en.bem.info/methodology/naming-convention/).
|
||||
- Prefix all class names.
|
|
@ -0,0 +1,88 @@
|
|||
# Naming Conventions
|
||||
|
||||
Table of Contents:
|
||||
|
||||
- [PHP](#php)
|
||||
- [`/src`](#src)
|
||||
- [`/includes`](#includes)
|
||||
- [JS](#js)
|
||||
- [CSS and SASS](#css-and-sass)
|
||||
|
||||
## PHP
|
||||
|
||||
WooCommerce core generally follows [WordPress PHP naming conventions](https://make.wordpress.org/core/handbook/best-practices/coding-standards/php/#naming-conventions).
|
||||
|
||||
There are some additional conventions that apply, depending on the location of the code.
|
||||
|
||||
### `/src`
|
||||
|
||||
Classes defined inside `/src` follow the [PSR-4](https://www.php-fig.org/psr/psr-4/) standard. See the [README for `/src`](../../plugins/woocommerce/src/README.md) for more information.
|
||||
|
||||
The following conventions apply to this directory:
|
||||
|
||||
- No class name prefix is needed, as all classes in this location live within the `Automattic\WooCommerce` namespace.
|
||||
- Classes are named using `CamelCase` convention.
|
||||
- Functions are named using `snake_case` convention.
|
||||
- Class file names should match the class name. They do not need a `class-` prefix.
|
||||
- The namespace should match the directory structure.
|
||||
- Hooks are prefixed with `woocommerce_`.
|
||||
- Hooks are named using `snake_case` convention.
|
||||
|
||||
For example, the class defined in `src/Util/StringUtil.php` should be named `StringUtil` and should be in the `Automattic\WooCommerce\Util` namespace.
|
||||
|
||||
### `/includes`
|
||||
|
||||
The `/includes` directory contains legacy code that does not follow the PSR-4 standard. See the [README for `/includes`](../../plugins/woocommerce/includes/README.md) for more information.
|
||||
|
||||
The following conventions apply to this directory:
|
||||
|
||||
- Class names are prefixed with `WC_`.
|
||||
- Classes are named using `Upper_Snake_Case` convention.
|
||||
- Functions are prefixed with `wc_`.
|
||||
- Functions are named using `snake_case` convention.
|
||||
- Hooks are prefixed with `woocommerce_`.
|
||||
- Hooks are named using `snake_case` convention.
|
||||
|
||||
Class name examples:
|
||||
|
||||
- `WC_Cache_Helper`
|
||||
- `WC_Cart`
|
||||
|
||||
Function name examples:
|
||||
|
||||
- `wc_get_product()`
|
||||
- `wc_is_active_theme()`
|
||||
|
||||
Hook name examples (actions or filters):
|
||||
|
||||
- `woocommerce_after_checkout_validation`
|
||||
- `woocommerce_get_formatted_order_total`
|
||||
|
||||
## JS
|
||||
|
||||
WooCommerce core follows [WordPress JS naming conventions](https://developer.wordpress.org/coding-standards/wordpress-coding-standards/javascript/#naming-conventions).
|
||||
|
||||
As with PHP, function, class, and hook names should be prefixed, but the convention for JS is slightly different.
|
||||
|
||||
- Global class names are prefixed with `WC`. Class names exported from modules are not prefixed.
|
||||
- Classes are named using `UpperCamelCase` convention.
|
||||
- Global function names are prefixed with `wc`. Function names exported from modules are not prefixed.
|
||||
- Functions are named using `camelCase` convention.
|
||||
- Hooks names are prefixed with `woocommerce`.
|
||||
- Hooks are named using `camelCase` convention.
|
||||
|
||||
Global class name example:
|
||||
|
||||
- `WCOrdersTable`
|
||||
|
||||
Global function name example:
|
||||
|
||||
- `wcSettings()`
|
||||
|
||||
Hook name example (actions or filters):
|
||||
|
||||
- `woocommerceTracksEventProperties`
|
||||
|
||||
## CSS and SASS
|
||||
|
||||
See [CSS/Sass Naming Conventions](./css-sass-naming-conventions.md).
|
|
@ -0,0 +1,138 @@
|
|||
# Writing high quality testing instructions
|
||||
|
||||
## Introduction
|
||||
|
||||
Having clear testing Instructions on pull requests is the first level of quality engineering in WooCommerce, which is key for testing early and minimizing the impact of unexpected effects in the upcoming versions of WooCommerce.
|
||||
|
||||
This page contains the following sections:
|
||||
|
||||
- [What is a test?](#what-is-a-test)
|
||||
- [What to cover with the testing instructions](#what-to-cover-with-the-testing-instructions)
|
||||
- [Flow to write good testing instructions](#flow-to-write-good-testing-instructions)
|
||||
- [Examples](#examples)
|
||||
|
||||
## What is a test?
|
||||
|
||||
A test is a method that we can use to check that something meets certain criteria. It is typically defined as a procedure which contains the steps required to put the system under test in a certain state before executing the action to be checked. Therefore, a test consists of the following stages:
|
||||
|
||||
- **Preconditions:** All the steps that need to be performed to put the system in the desired state before executing the action we want to check. A test could have many preconditions.
|
||||
- **Action:** This is the exact step that causes the change we want to check in the system. It should be only one because each test should ideally cover one thing at a time.
|
||||
- **Validation:** Relates to the steps to be performed in order to validate the result of performing the action in the system. A test could validate more than one thing.
|
||||
|
||||
For example, in the process of adding an item to the cart:
|
||||
|
||||
- The **preconditions** would be all the steps involved in:
|
||||
- The product creation process.
|
||||
- Logging as a shopper.
|
||||
- Heading to the shop page where the products are listed.
|
||||
- The **action** would be clicking the _"Add to cart"_ button in the desired product.
|
||||
- The **validation** stage would include checking that the cart icon (if any) shows 1 more item and the product we selected is now included in the cart.
|
||||
|
||||
Specifying the preconditions, actions and validations can be quite beneficial when understanding the scope of a test, because:
|
||||
|
||||
- The **preconditions** describe what we have to do so that we can execute the test successfully.
|
||||
- The **action** lets us know the purpose of the test, in other words, it is the key to understanding what we need to test.
|
||||
- The **validation** stage lets us know what to expect when executing the test.
|
||||
|
||||
In this context, we will refer to testing instructions as the tests we need to execute in order to validate that the changes delivered in a pull request or release work as expected. This means the testing instructions could refer to a test or more, involving the happy path and potential edge cases.
|
||||
|
||||
## What to cover with the testing instructions
|
||||
|
||||
As stated in the previous section, a test (in our context, a testing instruction) is a method to check that a new change or set of changes meets certain criteria.
|
||||
|
||||
Therefore, a PR could have testing instructions for multiple scenarios, in fact, it is recommended to include testing instructions for as many scenarios as needed to cover the changes introduced in the PR. In other words, please **add as many testing instructions as needed to cover the acceptance criteria**, understanding acceptance criteria as _the conditions that a software product must satisfy to be accepted by a user, customer or other stakeholders_ or, in the context of a PR, the conditions that this PR must satisfy to be accepted by users, developers and the WooCommerce community as per requirements.
|
||||
|
||||
## Flow to write good testing instructions
|
||||
|
||||
1. **Outline the user flows** you want to cover.
|
||||
2. **Define the environment** where the testing instructions should be executed (server, PHP version, WP version, required plugins, etc), and start writing the testing instructions as if you were starting from a fresh install.
|
||||
3. Identify the **preconditions**, **action** and **validation** steps.
|
||||
4. Write **as many preconditions as you need** to explain how to set up the state of WooCommerce so that you can execute the desired action to test every flow.
|
||||
1. Try to be detailed when explaining the interactions the user needs to perform in WooCommerce.
|
||||
2. If there are several preconditions for a user flow that is explained in a public guide, feel free to simply link the guide in the testing instructions instead of writing several steps. For example, _"Enable dev mode in WooCommerce Payments by following the steps mentioned [here](https://woocommerce.com/document/woocommerce-payments/testing-and-troubleshooting/dev-mode/)"_.
|
||||
5. Write **the action step**, which should cover the specific action that we want to test as part of this user flow.
|
||||
6. Write **as many validation steps** as needed in order to assess that the actual result meets expectations.
|
||||
1. Bear in mind to check only the steps needed to validate that this change works.
|
||||
|
||||
### Considerations for writing high-quality testing instructions
|
||||
|
||||
- Define the testing instructions in a way that they can be **understood and followed by everybody**, even for people new to WooCommerce.
|
||||
- Make sure to describe every detail and **avoid assuming knowledge**, the spectrum of readers might be wide and some people would not know the concepts behind what is being assumed. For example, instead of saying _“Enable the [x] experiment”_, say something like:
|
||||
|
||||
```text
|
||||
- Install the WooCommerce Beta Tester plugin.
|
||||
- Go to `Tools > WCA Test Helper > Experiments`.
|
||||
- Toggle the [x] experiment.
|
||||
```
|
||||
|
||||
- Always try to explain in detail **where the user should head to**, for example instead of saying “Go to the Orders page as admin”, say “Go to [url]” or even “Go to WooCommerce > Orders”.
|
||||
- Try to use real test data. For example, instead of saying _"Enter a name for the product"_, say something like _"Enter 'Blue T-Shirt' as the product name"_. This will make it more self-explanatory and remove potential doubts related to assuming knowledge.
|
||||
- Make sure you **keep your testing instructions updated** if they become obsolete as part of a new commit.
|
||||
- If the testing instructions require to add custom code, please **provide the code snippet**.
|
||||
- If the testing instructions require to install a plugin, please **provide a link to this plugin, or the zip file** to install it.
|
||||
- If the testing instructions require to hit an API endpoint, please provide the **link to the endpoint documentation**.
|
||||
- Ideally **provide screenshots and/or videos** that supported what the testing instructions are explaining. If you are using links to collaborative tools then also provide an equivalent screenshot/video for those who do not have access.
|
||||
|
||||
## Examples
|
||||
|
||||
### Good quality testing instructions
|
||||
|
||||
#### Example 1
|
||||
|
||||
![Sample of good quality instructions](https://woocommerce.files.wordpress.com/2023/10/213682695-3dc51613-b836-4e7e-93ef-f75078ab48ac.png)
|
||||
|
||||
#### Example 2
|
||||
|
||||
![Another sample of good quality instructions](https://woocommerce.files.wordpress.com/2023/10/213682778-b552ab07-a518-48a7-9358-16adc5762aca.png)
|
||||
|
||||
### Improving real testing instructions
|
||||
|
||||
In this section, you will see some real examples of testing instructions that have room for improvement (before) and how we can tweak them (after).
|
||||
|
||||
Before:
|
||||
|
||||
![Instructions needing improvement](https://woocommerce.files.wordpress.com/2023/10/213682262-25bec5c3-154c-45ec-aa3d-d3e07f52669e.png)
|
||||
|
||||
After:
|
||||
|
||||
![Improved instructions](https://woocommerce.files.wordpress.com/2023/10/213682303-1b12ab97-f27a-41cb-a8db-da8a78d18840.png)
|
||||
|
||||
Improvements:
|
||||
|
||||
![Changes made](https://woocommerce.files.wordpress.com/2023/10/213682323-0ecc998d-69ab-4201-8daa-820b948315e8.png)
|
||||
|
||||
Before:
|
||||
|
||||
![Instructions needing improvement](https://woocommerce.files.wordpress.com/2023/10/213682396-8c52d20e-1fca-4ac1-8345-f381c15a102a.png)
|
||||
|
||||
After:
|
||||
|
||||
![Improved instructions](https://woocommerce.files.wordpress.com/2023/10/213682480-c01e0e84-5969-4456-8f43-70cbb8509e8d.png)
|
||||
|
||||
Improvements:
|
||||
|
||||
![Changes made](https://woocommerce.files.wordpress.com/2023/10/213682597-8d06e638-35dd-4ff8-9236-63c6ec5d05b8.jpg)
|
||||
|
||||
Before:
|
||||
|
||||
![Screenshot 2023-02-02 at 16 07 29](https://woocommerce.files.wordpress.com/2023/10/216365611-b540a814-3b8f-40f3-ae64-81018b9f97fb.png)
|
||||
|
||||
After:
|
||||
|
||||
![Screenshot 2023-02-02 at 16 22 31](https://woocommerce.files.wordpress.com/2023/10/216366043-967e5daa-6a23-4ab8-adda-5f3082d1ebf7.png)
|
||||
|
||||
Improvements:
|
||||
|
||||
![Screenshot 2023-02-02 at 16 09 24](https://woocommerce.files.wordpress.com/2023/10/216366152-b331648d-bcef-443b-b126-de2621a20862.png)
|
||||
|
||||
Before:
|
||||
|
||||
![Screenshot 2023-02-02 at 17 25 07](https://woocommerce.files.wordpress.com/2023/10/216388785-8806ea74-62e6-42da-8887-c8e291e7dfe2-1.png)
|
||||
|
||||
After:
|
||||
|
||||
![Screenshot 2023-02-02 at 17 49 22](https://woocommerce.files.wordpress.com/2023/10/216388842-e5ab433e-d288-4306-862f-72f6f81ab2cd.png)
|
||||
|
||||
Improvements:
|
||||
|
||||
![Screenshot 2023-02-02 at 17 39 23](https://woocommerce.files.wordpress.com/2023/10/216388874-c5b21fc3-f693-4a7e-a58a-c5d1b6606682.png)
|
|
@ -52,6 +52,56 @@ How-to guides are focused and specific, providing instructions on how to accompl
|
|||
>
|
||||
> [Divio Framework on How-to-Guide Writing](https://documentation.divio.com/how-to-guides/)
|
||||
|
||||
## Custom Linting Rules
|
||||
|
||||
At WooCommerce, we're dedicated to maintaining a consistent and high-quality standard for our technical documentation. Our documents primarily adhere to the linting rules provided by `markdownlint`. To assist our contributors, we've detailed our custom configurations and exceptions below.
|
||||
|
||||
Note: While we've outlined specific rules above, all other default linting rules from `markdownlint` apply unless otherwise stated. We've only highlighted custom configurations or exceptions here. For a complete list of `markdownlint` rules, you can refer to [this link](https://github.com/DavidAnson/markdownlint/blob/3561fc3f38b05b3c55f44e371c2cd9bda194598a/doc/Rules.md).
|
||||
|
||||
1. **Headings Style**:
|
||||
- Use the ATX-style (`#`) for headers.
|
||||
|
||||
```markdown
|
||||
# This is an H1
|
||||
## This is an H2
|
||||
```
|
||||
|
||||
[Reference: MD003](https://github.com/DavidAnson/markdownlint/blob/3561fc3f38b05b3c55f44e371c2cd9bda194598a/doc/Rules.md#md003---heading-style)
|
||||
|
||||
2. **List Indentation**:
|
||||
- Indent list items with 4 spaces.
|
||||
|
||||
```markdown
|
||||
- Item 1
|
||||
- Subitem 1.1
|
||||
```
|
||||
|
||||
[Reference: MD007]([https://github.com/DavidAnson/markdownlint/blob/main/doc/Rules.md](https://github.com/DavidAnson/markdownlint/blob/3561fc3f38b05b3c55f44e371c2cd9bda194598a/doc/Rules.md)#md007---unordered-list-indentation)
|
||||
|
||||
3. **Line Length**:
|
||||
- No specific restriction on the line length, but keep paragraphs and sentences readable.
|
||||
|
||||
[Reference: MD013](https://github.com/DavidAnson/markdownlint/blob/main/doc/Rules.md#md013---line-length)
|
||||
|
||||
4. **Multiple Headings with the Same Content**:
|
||||
- Multiple headings with the same content are permissible as long as they are not siblings.
|
||||
|
||||
[Reference: MD024](https://github.com/DavidAnson/markdownlint/blob/3561fc3f38b05b3c55f44e371c2cd9bda194598a/doc/Rules.md#md024---no-multiple-headings-with-the-same-content)
|
||||
|
||||
5. **Inline HTML**:
|
||||
- Only the `video` element is allowed when using inline HTML.
|
||||
|
||||
```markdown
|
||||
<video src="path_to_video.mp4" controls></video>
|
||||
```
|
||||
|
||||
[Reference: MD033](https://github.com/DavidAnson/markdownlint/blob/3561fc3f38b05b3c55f44e371c2cd9bda194598a/doc/Rules.md#md033---inline-html)
|
||||
|
||||
6. **Tabs and Whitespace**:
|
||||
- We're flexible with the use of hard tabs and trailing whitespace. However, for consistency, we recommend using spaces over tabs and avoiding trailing whitespaces.
|
||||
|
||||
[Reference: no-hard-tabs & whitespace](https://github.com/DavidAnson/markdownlint/blob/3561fc3f38b05b3c55f44e371c2cd9bda194598a/doc/Rules.md)
|
||||
|
||||
## Formatting
|
||||
|
||||
### Visual style
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
Significance: patch
|
||||
Type: dev
|
||||
Comment: This is just a change to developer commands.
|
||||
|
|
@ -78,7 +78,8 @@
|
|||
"changelog": "composer exec -- changelogger",
|
||||
"clean": "pnpm exec rimraf tsconfig.tsbuildinfo build build-*",
|
||||
"build": "pnpm -w exec turbo run turbo:build --filter=$npm_package_name",
|
||||
"test": "pnpm -w exec turbo run turbo:test --filter=$npm_package_name",
|
||||
"test": "pnpm test:js",
|
||||
"test:js": "pnpm -w exec turbo run turbo:test --filter=$npm_package_name --",
|
||||
"lint": "eslint --output-file eslint_report.json --format json src",
|
||||
"build:js": "tsc --project tsconfig.json && tsc --project tsconfig-cjs.json",
|
||||
"build:css": "webpack",
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
Significance: patch
|
||||
Type: dev
|
||||
Comment: This is just a change to developer commands.
|
||||
|
|
@ -32,7 +32,8 @@
|
|||
"scripts": {
|
||||
"turbo:build": "pnpm run clean && npm run compile",
|
||||
"turbo:test": "jest",
|
||||
"test": "pnpm -w exec turbo run turbo:test --filter=$npm_package_name",
|
||||
"test": "pnpm test:js",
|
||||
"test:js": "pnpm -w exec turbo run turbo:test --filter=$npm_package_name",
|
||||
"prepare": "composer install",
|
||||
"changelog": "composer exec -- changelogger",
|
||||
"clean": "rm -rf ./dist ./tsconfig.tsbuildinfo",
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
Significance: patch
|
||||
Type: dev
|
||||
Comment: This is just a change to developer commands.
|
||||
|
|
@ -65,7 +65,8 @@
|
|||
"changelog": "composer exec -- changelogger",
|
||||
"clean": "pnpm exec rimraf tsconfig.tsbuildinfo build build-*",
|
||||
"build": "pnpm -w exec turbo run turbo:build --filter=$npm_package_name",
|
||||
"test": "pnpm -w exec turbo run turbo:test --filter=$npm_package_name",
|
||||
"test": "pnpm test:js",
|
||||
"test:js": "pnpm -w exec turbo run turbo:test --filter=$npm_package_name",
|
||||
"lint": "eslint --output-file eslint_report.json --format json src",
|
||||
"build:js": "tsc --project tsconfig.json && tsc --project tsconfig-cjs.json",
|
||||
"build:css": "webpack",
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
Significance: minor
|
||||
Type: add
|
||||
|
||||
Set button optional in MediaUploader component
|
|
@ -0,0 +1,4 @@
|
|||
Significance: minor
|
||||
Type: add
|
||||
|
||||
Image gallery and media uploader now support initial selected images.
|
|
@ -0,0 +1,4 @@
|
|||
Significance: patch
|
||||
Type: tweak
|
||||
|
||||
Small condition change in the date time picker to avoid edge case where inputControl is null.
|
|
@ -0,0 +1,4 @@
|
|||
Significance: patch
|
||||
Type: fix
|
||||
|
||||
Fix invalid focus state of the experimental select control
|
|
@ -0,0 +1,4 @@
|
|||
Significance: patch
|
||||
Type: tweak
|
||||
|
||||
Add z-index=1 to tour-kit close btn to ensure it's clickable
|
|
@ -0,0 +1,4 @@
|
|||
Significance: patch
|
||||
Type: fix
|
||||
|
||||
Add class back in for increase specificity of css for dropdown button.
|
|
@ -0,0 +1,4 @@
|
|||
Significance: patch
|
||||
Type: dev
|
||||
Comment: This is just a change to developer commands.
|
||||
|
|
@ -153,7 +153,8 @@
|
|||
"prepare": "composer install",
|
||||
"changelog": "composer exec -- changelogger",
|
||||
"build": "pnpm -w exec turbo run turbo:build --filter=$npm_package_name",
|
||||
"test": "pnpm -w exec turbo run turbo:test --filter=$npm_package_name",
|
||||
"test": "pnpm test:js",
|
||||
"test:js": "pnpm -w exec turbo run turbo:test --filter=$npm_package_name",
|
||||
"lint": "eslint --output-file eslint_report.json --format json --ext=js,ts,tsx src",
|
||||
"build:js": "tsc --project tsconfig.json && tsc --project tsconfig-cjs.json",
|
||||
"build:css": "webpack",
|
||||
|
|
|
@ -265,7 +265,11 @@ export const DateTimePickerControl = forwardRef(
|
|||
}, [ onBlur ] );
|
||||
|
||||
const callOnBlurIfDropdownIsNotOpening = useCallback( ( willOpen ) => {
|
||||
if ( ! willOpen && typeof onBlurRef.current === 'function' ) {
|
||||
if (
|
||||
! willOpen &&
|
||||
typeof onBlurRef.current === 'function' &&
|
||||
inputControl.current
|
||||
) {
|
||||
// in case the component is blurred before a debounced
|
||||
// change has been processed, immediately set the input string
|
||||
// to the current value of the input field, so that
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
.woocommerce-dropdown-button {
|
||||
.components-button.woocommerce-dropdown-button {
|
||||
background-color: $studio-white;
|
||||
position: relative;
|
||||
border: 1px solid $gray-700;
|
||||
|
|
|
@ -17,13 +17,14 @@
|
|||
}
|
||||
.woocommerce-experimental-select-control__popover-menu {
|
||||
.components-popover__content {
|
||||
max-height: 300px;
|
||||
overflow-y: scroll;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
.woocommerce-experimental-select-control__popover-menu-container {
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
max-height: 300px;
|
||||
overflow-y: scroll;
|
||||
|
||||
> .category-field-dropdown__item:not(:first-child) {
|
||||
.category-field-dropdown__item-content {
|
||||
|
|
|
@ -15,6 +15,7 @@ import {
|
|||
useEffect,
|
||||
createElement,
|
||||
Fragment,
|
||||
useRef,
|
||||
} from '@wordpress/element';
|
||||
import { chevronDown } from '@wordpress/icons';
|
||||
|
||||
|
@ -138,11 +139,13 @@ function SelectControl< ItemType = DefaultItemType >( {
|
|||
const instanceId = useInstanceId(
|
||||
SelectControl,
|
||||
'woocommerce-experimental-select-control'
|
||||
);
|
||||
) as string;
|
||||
|
||||
const innerInputClassName =
|
||||
'woocommerce-experimental-select-control__input';
|
||||
|
||||
const selectControlWrapperRef = useRef< HTMLDivElement >( null );
|
||||
|
||||
let selectedItems = selected === null ? [] : selected;
|
||||
selectedItems = Array.isArray( selectedItems )
|
||||
? selectedItems
|
||||
|
@ -186,6 +189,7 @@ function SelectControl< ItemType = DefaultItemType >( {
|
|||
openMenu,
|
||||
closeMenu,
|
||||
} = useCombobox< ItemType | null >( {
|
||||
id: instanceId,
|
||||
initialSelectedItem: singleSelectedItem,
|
||||
inputValue,
|
||||
items: filteredItems,
|
||||
|
@ -246,12 +250,15 @@ function SelectControl< ItemType = DefaultItemType >( {
|
|||
} );
|
||||
|
||||
const isEventOutside = ( event: React.FocusEvent ) => {
|
||||
const inputClasses = event?.target?.className;
|
||||
const selectControlWrapperElement = selectControlWrapperRef.current;
|
||||
const menuElement = document.getElementById( `${ instanceId }-menu` );
|
||||
const parentPopoverMenuElement = menuElement?.closest(
|
||||
'.woocommerce-experimental-select-control__popover-menu'
|
||||
);
|
||||
|
||||
return (
|
||||
! document
|
||||
.querySelector( '.' + instanceId )
|
||||
?.contains( event.relatedTarget ) &&
|
||||
! inputClasses.includes( innerInputClassName )
|
||||
! selectControlWrapperElement?.contains( event.relatedTarget ) &&
|
||||
! parentPopoverMenuElement?.contains( event.relatedTarget )
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -276,10 +283,11 @@ function SelectControl< ItemType = DefaultItemType >( {
|
|||
|
||||
return (
|
||||
<div
|
||||
id={ instanceId }
|
||||
ref={ selectControlWrapperRef }
|
||||
className={ classnames(
|
||||
'woocommerce-experimental-select-control',
|
||||
className,
|
||||
instanceId,
|
||||
{
|
||||
'is-read-only': isReadOnly,
|
||||
'is-focused': isFocused,
|
||||
|
|
|
@ -15,6 +15,7 @@ export type ImageGalleryItemProps = {
|
|||
id?: string;
|
||||
alt: string;
|
||||
isCover?: boolean;
|
||||
isDraggable?: boolean;
|
||||
src: string;
|
||||
displayToolbar?: boolean;
|
||||
className?: string;
|
||||
|
@ -26,6 +27,7 @@ export const ImageGalleryItem: React.FC< ImageGalleryItemProps > = ( {
|
|||
id,
|
||||
alt,
|
||||
isCover = false,
|
||||
isDraggable = true,
|
||||
src,
|
||||
className = '',
|
||||
onClick = () => null,
|
||||
|
@ -33,7 +35,7 @@ export const ImageGalleryItem: React.FC< ImageGalleryItemProps > = ( {
|
|||
children,
|
||||
}: ImageGalleryItemProps ) => (
|
||||
<ConditionalWrapper
|
||||
condition={ isCover }
|
||||
condition={ ! isDraggable }
|
||||
wrapper={ ( wrappedChildren ) => (
|
||||
<NonSortableItem>{ wrappedChildren }</NonSortableItem>
|
||||
) }
|
||||
|
@ -48,15 +50,15 @@ export const ImageGalleryItem: React.FC< ImageGalleryItemProps > = ( {
|
|||
>
|
||||
{ children }
|
||||
|
||||
{ isCover ? (
|
||||
<>
|
||||
<Pill>{ __( 'Cover', 'woocommerce' ) }</Pill>
|
||||
<img alt={ alt } src={ src } id={ id } />
|
||||
</>
|
||||
) : (
|
||||
{ isDraggable ? (
|
||||
<SortableHandle>
|
||||
<img alt={ alt } src={ src } id={ id } />
|
||||
</SortableHandle>
|
||||
) : (
|
||||
<>
|
||||
{ isCover && <Pill>{ __( 'Cover', 'woocommerce' ) }</Pill> }
|
||||
<img alt={ alt } src={ src } id={ id } />
|
||||
</>
|
||||
) }
|
||||
</div>
|
||||
</ConditionalWrapper>
|
||||
|
|
|
@ -25,6 +25,7 @@ import { ImageGalleryToolbarDropdown } from './image-gallery-toolbar-dropdown';
|
|||
export type ImageGalleryToolbarProps = {
|
||||
childIndex: number;
|
||||
allowDragging?: boolean;
|
||||
value?: number;
|
||||
moveItem: ( fromIndex: number, toIndex: number ) => void;
|
||||
removeItem: ( removeIndex: number ) => void;
|
||||
replaceItem: (
|
||||
|
@ -44,6 +45,7 @@ export const ImageGalleryToolbar: React.FC< ImageGalleryToolbarProps > = ( {
|
|||
replaceItem,
|
||||
setToolBarItem,
|
||||
lastChild,
|
||||
value,
|
||||
MediaUploadComponent = MediaUpload,
|
||||
}: ImageGalleryToolbarProps ) => {
|
||||
const moveNext = () => {
|
||||
|
@ -105,6 +107,7 @@ export const ImageGalleryToolbar: React.FC< ImageGalleryToolbarProps > = ( {
|
|||
{ isCoverItem && (
|
||||
<ToolbarGroup className="woocommerce-image-gallery__toolbar-media">
|
||||
<MediaUploadComponent
|
||||
value={ value }
|
||||
onSelect={ ( media ) =>
|
||||
replaceItem( childIndex, media as MediaItem )
|
||||
}
|
||||
|
|
|
@ -100,12 +100,11 @@ export const ImageGallery: React.FC< ImageGalleryProps > = ( {
|
|||
>
|
||||
{ orderedChildren.map( ( child, childIndex ) => {
|
||||
const isToolbarVisible = child.key === activeToolbarKey;
|
||||
const isCoverItem = ( childIndex === 0 ) as boolean;
|
||||
|
||||
return cloneElement(
|
||||
child,
|
||||
{
|
||||
isCover: isCoverItem,
|
||||
isDraggable: allowDragging && ! child.props.isCover,
|
||||
className: classnames( {
|
||||
'is-toolbar-visible': isToolbarVisible,
|
||||
} ),
|
||||
|
@ -152,6 +151,7 @@ export const ImageGallery: React.FC< ImageGalleryProps > = ( {
|
|||
},
|
||||
isToolbarVisible ? (
|
||||
<ImageGalleryToolbar
|
||||
value={ child.props.id }
|
||||
allowDragging={ allowDragging }
|
||||
childIndex={ childIndex }
|
||||
lastChild={
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
*/
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { Button, DropZone, FormFileUpload } from '@wordpress/components';
|
||||
import { createElement } from 'react';
|
||||
import { Fragment, createElement } from 'react';
|
||||
import {
|
||||
MediaItem,
|
||||
MediaUpload,
|
||||
|
@ -25,6 +25,7 @@ type MediaUploaderProps = {
|
|||
props: MediaUpload.Props< T >
|
||||
) => JSX.Element;
|
||||
multipleSelect?: boolean | string;
|
||||
value?: number | number[];
|
||||
onSelect?: (
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
value: ( { id: number } & { [ k: string ]: any } ) | MediaItem[]
|
||||
|
@ -35,8 +36,8 @@ type MediaUploaderProps = {
|
|||
file: File;
|
||||
} ) => void;
|
||||
onMediaGalleryOpen?: () => void;
|
||||
onUpload?: ( files: MediaItem[] ) => void;
|
||||
onFileUploadChange?: ( files: MediaItem[] ) => void;
|
||||
onUpload?: ( files: MediaItem | MediaItem[] ) => void;
|
||||
onFileUploadChange?: ( files: MediaItem | MediaItem[] ) => void;
|
||||
uploadMedia?: ( options: UploadMediaOptions ) => Promise< void >;
|
||||
};
|
||||
|
||||
|
@ -48,6 +49,7 @@ export const MediaUploader = ( {
|
|||
maxUploadFileSize = 10000000,
|
||||
MediaUploadComponent = MediaUpload,
|
||||
multipleSelect = false,
|
||||
value,
|
||||
onError = () => null,
|
||||
onFileUploadChange = () => null,
|
||||
onMediaGalleryOpen = () => null,
|
||||
|
@ -55,19 +57,21 @@ export const MediaUploader = ( {
|
|||
onSelect = () => null,
|
||||
uploadMedia = wpUploadMedia,
|
||||
}: MediaUploaderProps ) => {
|
||||
const getFormFileUploadAcceptedFiles = () =>
|
||||
allowedMediaTypes.map( ( type ) => `${ type }/*` );
|
||||
const multiple = Boolean( multipleSelect );
|
||||
|
||||
return (
|
||||
<FormFileUpload
|
||||
accept={ getFormFileUploadAcceptedFiles().toString() }
|
||||
multiple={ true }
|
||||
accept={ allowedMediaTypes.toString() }
|
||||
multiple={ multiple }
|
||||
onChange={ ( { currentTarget } ) => {
|
||||
uploadMedia( {
|
||||
allowedTypes: allowedMediaTypes,
|
||||
filesList: currentTarget.files as FileList,
|
||||
onError,
|
||||
onFileChange: onFileUploadChange,
|
||||
maxUploadFileSize,
|
||||
onError,
|
||||
onFileChange( files ) {
|
||||
onFileUploadChange( multiple ? files : files[ 0 ] );
|
||||
},
|
||||
} );
|
||||
} }
|
||||
render={ ( { openFileDialog } ) => (
|
||||
|
@ -94,11 +98,13 @@ export const MediaUploader = ( {
|
|||
</div>
|
||||
|
||||
<MediaUploadComponent
|
||||
value={ value }
|
||||
onSelect={ onSelect }
|
||||
allowedTypes={ allowedMediaTypes }
|
||||
// @ts-expect-error - TODO multiple also accepts string.
|
||||
multiple={ multipleSelect }
|
||||
render={ ( { open } ) => (
|
||||
render={ ( { open } ) =>
|
||||
buttonText ? (
|
||||
<Button
|
||||
variant="secondary"
|
||||
onClick={ () => {
|
||||
|
@ -108,17 +114,25 @@ export const MediaUploader = ( {
|
|||
>
|
||||
{ buttonText }
|
||||
</Button>
|
||||
) }
|
||||
) : (
|
||||
<Fragment />
|
||||
)
|
||||
}
|
||||
/>
|
||||
|
||||
{ hasDropZone && (
|
||||
<DropZone
|
||||
onFilesDrop={ ( files ) =>
|
||||
onFilesDrop={ ( droppedFiles ) =>
|
||||
uploadMedia( {
|
||||
filesList: files,
|
||||
onError,
|
||||
onFileChange: onUpload,
|
||||
allowedTypes: allowedMediaTypes,
|
||||
filesList: droppedFiles,
|
||||
maxUploadFileSize,
|
||||
onError,
|
||||
onFileChange( files ) {
|
||||
onUpload(
|
||||
multiple ? files : files[ 0 ]
|
||||
);
|
||||
},
|
||||
} )
|
||||
}
|
||||
/>
|
||||
|
|
|
@ -40,6 +40,8 @@
|
|||
height: 16px;
|
||||
min-width: 16px;
|
||||
padding: 0;
|
||||
z-index: 1;
|
||||
|
||||
svg {
|
||||
fill: #1e1e1e;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
Significance: patch
|
||||
Type: dev
|
||||
Comment: This is just a change to developer commands.
|
||||
|
|
@ -40,7 +40,8 @@
|
|||
"changelog": "composer exec -- changelogger",
|
||||
"clean": "pnpm exec rimraf tsconfig.tsbuildinfo build build-*",
|
||||
"build": "pnpm -w exec turbo run turbo:build --filter=$npm_package_name",
|
||||
"test": "pnpm -w exec turbo run turbo:test --filter=$npm_package_name",
|
||||
"test": "pnpm test:js",
|
||||
"test:js": "pnpm -w exec turbo run turbo:test --filter=$npm_package_name",
|
||||
"lint": "eslint --output-file eslint_report.json --format json src",
|
||||
"start": "concurrently \"tsc --project tsconfig.json --watch\" \"tsc --project tsconfig-cjs.json --watch\"",
|
||||
"prepack": "pnpm run clean && pnpm run build",
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
Significance: patch
|
||||
Type: dev
|
||||
Comment: This is just a change to developer commands.
|
||||
|
|
@ -43,7 +43,8 @@
|
|||
"changelog": "composer exec -- changelogger",
|
||||
"clean": "pnpm exec rimraf tsconfig.tsbuildinfo build build-*",
|
||||
"build": "pnpm -w exec turbo run turbo:build --filter=$npm_package_name",
|
||||
"test": "pnpm -w exec turbo run turbo:test --filter=$npm_package_name",
|
||||
"test": "pnpm test:js",
|
||||
"test:js": "pnpm -w exec turbo run turbo:test --filter=$npm_package_name",
|
||||
"lint": "eslint --output-file eslint_report.json --format json src",
|
||||
"start": "concurrently \"tsc --project tsconfig.json --watch\" \"tsc --project tsconfig-cjs.json --watch\"",
|
||||
"prepack": "pnpm run clean && pnpm run build",
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
Significance: patch
|
||||
Type: dev
|
||||
Comment: This is just a change to developer commands.
|
||||
|
|
@ -79,7 +79,8 @@
|
|||
"changelog": "composer exec -- changelogger",
|
||||
"clean": "pnpm exec rimraf tsconfig.tsbuildinfo build build-*",
|
||||
"build": "pnpm -w exec turbo run turbo:build --filter=$npm_package_name",
|
||||
"test": "pnpm -w exec turbo run turbo:test --filter=$npm_package_name",
|
||||
"test": "pnpm test:js",
|
||||
"test:js": "pnpm -w exec turbo run turbo:test --filter=$npm_package_name",
|
||||
"lint": "eslint --output-file eslint_report.json --format json src",
|
||||
"build:js": "tsc --project tsconfig.json && tsc --project tsconfig-cjs.json",
|
||||
"build:css": "webpack",
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
Significance: minor
|
||||
Type: add
|
||||
|
||||
Add name and parent_id to the ProductVariation type definition
|
|
@ -0,0 +1,4 @@
|
|||
Significance: patch
|
||||
Type: dev
|
||||
Comment: This is just a change to developer commands.
|
||||
|
|
@ -86,7 +86,8 @@
|
|||
"changelog": "composer exec -- changelogger",
|
||||
"clean": "pnpm exec rimraf tsconfig.tsbuildinfo build build-*",
|
||||
"build": "pnpm -w exec turbo run turbo:build --filter=$npm_package_name",
|
||||
"test": "pnpm -w exec turbo run turbo:test --filter=$npm_package_name",
|
||||
"test": "pnpm test:js",
|
||||
"test:js": "pnpm -w exec turbo run turbo:test --filter=$npm_package_name",
|
||||
"lint": "eslint --output-file eslint_report.json --format json src",
|
||||
"start": "concurrently \"tsc --project tsconfig.json --watch\" \"tsc --project tsconfig-cjs.json --watch\"",
|
||||
"prepack": "pnpm run clean && pnpm run build",
|
||||
|
|
|
@ -55,7 +55,7 @@ export interface ProductVariationImage {
|
|||
|
||||
export type ProductVariation = Omit<
|
||||
Product,
|
||||
'name' | 'slug' | 'attributes' | 'images' | 'manage_stock'
|
||||
'slug' | 'attributes' | 'images' | 'manage_stock'
|
||||
> & {
|
||||
attributes: ProductVariationAttribute[];
|
||||
/**
|
||||
|
@ -70,6 +70,10 @@ export type ProductVariation = Omit<
|
|||
* @default false
|
||||
*/
|
||||
manage_stock: boolean | 'parent';
|
||||
/**
|
||||
* The product id this variation belongs to
|
||||
*/
|
||||
parent_id: number;
|
||||
};
|
||||
|
||||
type Query = Omit< ProductQuery, 'name' >;
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
Significance: patch
|
||||
Type: dev
|
||||
Comment: This is just a change to developer commands.
|
||||
|
|
@ -63,7 +63,8 @@
|
|||
"changelog": "composer exec -- changelogger",
|
||||
"clean": "pnpm exec rimraf tsconfig.tsbuildinfo build build-*",
|
||||
"build": "pnpm -w exec turbo run turbo:build --filter=$npm_package_name",
|
||||
"test": "pnpm -w exec turbo run turbo:test --filter=$npm_package_name",
|
||||
"test": "pnpm test:js",
|
||||
"test:js": "pnpm -w exec turbo run turbo:test --filter=$npm_package_name",
|
||||
"lint": "eslint --output-file eslint_report.json --format json src",
|
||||
"start": "concurrently \"tsc --project tsconfig.json --watch\" \"tsc --project tsconfig-cjs.json --watch\"",
|
||||
"prepack": "pnpm run clean && pnpm run build",
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
Significance: patch
|
||||
Type: dev
|
||||
Comment: This is just a change to developer commands.
|
||||
|
|
@ -89,7 +89,8 @@
|
|||
"changelog": "composer exec -- changelogger",
|
||||
"clean": "pnpm exec rimraf tsconfig.tsbuildinfo build build-*",
|
||||
"build": "pnpm -w exec turbo run turbo:build --filter=$npm_package_name",
|
||||
"test": "pnpm -w exec turbo run turbo:test --filter=$npm_package_name",
|
||||
"test": "pnpm test:js",
|
||||
"test:js": "pnpm -w exec turbo run turbo:test --filter=$npm_package_name",
|
||||
"lint": "eslint --output-file eslint_report.json --format json src",
|
||||
"build:js": "tsc --project tsconfig.json && tsc --project tsconfig-cjs.json",
|
||||
"build:css": "webpack",
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
Significance: patch
|
||||
Type: dev
|
||||
Comment: This is just a change to developer commands.
|
||||
|
|
@ -61,7 +61,8 @@
|
|||
"changelog": "composer exec -- changelogger",
|
||||
"clean": "pnpm exec rimraf tsconfig.tsbuildinfo build build-*",
|
||||
"build": "pnpm -w exec turbo run turbo:build --filter=$npm_package_name",
|
||||
"test": "pnpm -w exec turbo run turbo:test --filter=$npm_package_name",
|
||||
"test": "pnpm test:js",
|
||||
"test:js": "pnpm -w exec turbo run turbo:test --filter=$npm_package_name",
|
||||
"lint": "eslint --output-file eslint_report.json --format json src",
|
||||
"start": "concurrently \"tsc --project tsconfig.json --watch\" \"tsc --project tsconfig-cjs.json --watch\"",
|
||||
"prepack": "pnpm run clean && pnpm run build",
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
module.exports = {
|
||||
extends: [ 'plugin:@woocommerce/eslint-plugin/recommended' ],
|
||||
root: true,
|
||||
};
|
|
@ -0,0 +1 @@
|
|||
package-lock=false
|
|
@ -0,0 +1,3 @@
|
|||
# Changelog
|
||||
|
||||
This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
@ -0,0 +1,314 @@
|
|||
# @woocommerce/expression-evaluation
|
||||
|
||||
Evaluation of JavaScript-like expressions in an optional context.
|
||||
|
||||
Examples of simple expressions:
|
||||
|
||||
```js
|
||||
1 + 2
|
||||
```
|
||||
|
||||
```js
|
||||
foo === 'bar'
|
||||
```
|
||||
|
||||
```js
|
||||
foo ? 'bar' : 'baz'
|
||||
```
|
||||
|
||||
Examples of complex expressions:
|
||||
|
||||
```js
|
||||
foo.bar.baz === 'qux'
|
||||
```
|
||||
|
||||
```js
|
||||
foo.bar
|
||||
&& ( foo.bar.baz === 'qux' || foo.baz === 'quux' )
|
||||
```
|
||||
|
||||
```js
|
||||
foo.bar
|
||||
&& ( foo.baz === "qux" || foo.baz === "quux" )
|
||||
&& ( foo.quux > 1 && foo.quux <= 5 )
|
||||
```
|
||||
|
||||
```js
|
||||
foo.bar
|
||||
&& ( foo.baz === "qux" || foo.baz === "quux" )
|
||||
&& ( foo.quux > 1 && foo.quux <= 5 )
|
||||
? "boo"
|
||||
: "baa"
|
||||
```
|
||||
|
||||
```js
|
||||
foo
|
||||
+ 5
|
||||
/* This is a comment */
|
||||
* ( bar ? baz : qux )
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
### evaluate
|
||||
|
||||
Evaluates an expression in an optional context.
|
||||
|
||||
#### Usage
|
||||
|
||||
```js
|
||||
import { evaluate } from '@woocommerce/expression-evaluation';
|
||||
|
||||
const result = evaluate( '1 + foo', { foo: 2 } );
|
||||
|
||||
console.log( result ); // 3
|
||||
```
|
||||
|
||||
#### Parameters
|
||||
|
||||
- _expression_ `string`: The expression to evaluate.
|
||||
- _context_ `Object`: Optional. The context to evaluate the expression in. Variables in the expression will be looked up in this object.
|
||||
|
||||
#### Returns
|
||||
|
||||
- `any`: The result of the expression evaluation.
|
||||
|
||||
## Expression syntax
|
||||
|
||||
### Grammar and types
|
||||
|
||||
The expression syntax is based on JavaScript. The formal grammar is defined in [parser.ts](./src/parser.ts).
|
||||
|
||||
An expression consists of a single statement.
|
||||
|
||||
Features like `if` statements, `for` loops, function calls, and variable assignments, are not supported.
|
||||
|
||||
The following types are supported:
|
||||
|
||||
- `null`
|
||||
- Boolean: `true` and `false`
|
||||
- Number: An integer or floating point number.
|
||||
- String: A sequence of characters that represent text.
|
||||
|
||||
### Literals
|
||||
|
||||
Values in an expression can be written as literals.
|
||||
|
||||
#### null
|
||||
|
||||
```js
|
||||
null
|
||||
```
|
||||
|
||||
#### Boolean
|
||||
|
||||
```js
|
||||
true
|
||||
false
|
||||
```
|
||||
|
||||
#### Number
|
||||
|
||||
```js
|
||||
1
|
||||
5.23
|
||||
-9
|
||||
```
|
||||
|
||||
#### String
|
||||
|
||||
String literals can be written with single or double quotes. This can be helpful if the string contains a single or double quote.
|
||||
|
||||
```js
|
||||
'foo'
|
||||
"foo"
|
||||
'foo "bar"'
|
||||
"foo 'bar'"
|
||||
```
|
||||
|
||||
Quotes can be escaped with a backslash.
|
||||
|
||||
```js
|
||||
'foo \'bar\''
|
||||
"foo \"bar\""
|
||||
```
|
||||
|
||||
### Context variables
|
||||
|
||||
Variables can be used in an expression. The value of a variable is looked up in the context.
|
||||
|
||||
```js
|
||||
const result = evaluate( 'foo', { foo: 1 } );
|
||||
|
||||
console.log( result ); // 1
|
||||
```
|
||||
|
||||
Nested properties can be accessed with the dot operator.
|
||||
|
||||
```js
|
||||
const result = evaluate( 'foo.bar', { foo: { bar: 1 } } );
|
||||
|
||||
console.log( result ); // 1
|
||||
```
|
||||
|
||||
### Operators
|
||||
|
||||
The following operators are supported.
|
||||
|
||||
#### Comparison operators
|
||||
|
||||
##### Equal (`==`)
|
||||
|
||||
Returns `true` if the operands are equal.
|
||||
|
||||
```js
|
||||
1 == 1
|
||||
```
|
||||
|
||||
##### Not equal (`!=`)
|
||||
|
||||
Returns `true` if the operands are not equal.
|
||||
|
||||
```js
|
||||
1 != 2
|
||||
```
|
||||
|
||||
##### Strict equal (`===`)
|
||||
|
||||
Returns `true` if the operands are equal and of the same type.
|
||||
|
||||
```js
|
||||
1 === 1
|
||||
```
|
||||
|
||||
##### Strict not equal (`!==`)
|
||||
|
||||
Returns `true` if the operands are not equal and/or not of the same type.
|
||||
|
||||
```js
|
||||
1 !== "1"
|
||||
```
|
||||
|
||||
##### Greater than (`>`)
|
||||
|
||||
Returns `true` if the left operand is greater than the right operand.
|
||||
|
||||
```js
|
||||
2 > 1
|
||||
```
|
||||
|
||||
##### Greater than or equal (`>=`)
|
||||
|
||||
Returns `true` if the left operand is greater than or equal to the right operand.
|
||||
|
||||
```js
|
||||
2 >= 2
|
||||
```
|
||||
|
||||
##### Less than (`<`)
|
||||
|
||||
Returns `true` if the left operand is less than the right operand.
|
||||
|
||||
```js
|
||||
1 < 2
|
||||
```
|
||||
|
||||
##### Less than or equal (`<=`)
|
||||
|
||||
Returns `true` if the left operand is less than or equal to the right operand.
|
||||
|
||||
```js
|
||||
2 <= 2
|
||||
```
|
||||
|
||||
#### Arithmetic operators
|
||||
|
||||
##### Addition (`+`)
|
||||
|
||||
Returns the sum of two operands.
|
||||
|
||||
```js
|
||||
1 + 2
|
||||
```
|
||||
|
||||
##### Subtraction (`-`)
|
||||
|
||||
Returns the difference of two operands.
|
||||
|
||||
```js
|
||||
2 - 1
|
||||
```
|
||||
|
||||
##### Multiplication (`*`)
|
||||
|
||||
Returns the product of two operands.
|
||||
|
||||
```js
|
||||
2 * 3
|
||||
```
|
||||
|
||||
##### Division (`/`)
|
||||
|
||||
Returns the quotient of two operands.
|
||||
|
||||
```js
|
||||
6 / 2
|
||||
```
|
||||
|
||||
##### Modulus (`%`)
|
||||
|
||||
Returns the remainder of two operands.
|
||||
|
||||
```js
|
||||
5 % 2
|
||||
```
|
||||
|
||||
##### Negation (`-`)
|
||||
|
||||
Returns the negation of an operand.
|
||||
|
||||
```js
|
||||
-1
|
||||
```
|
||||
|
||||
#### Logical operators
|
||||
|
||||
##### Logical AND (`&&`)
|
||||
|
||||
Returns `true` if both operands are `true`.
|
||||
|
||||
```js
|
||||
true && true
|
||||
```
|
||||
|
||||
##### Logical OR (`||`)
|
||||
|
||||
Returns `true` if either operand is `true`.
|
||||
|
||||
```js
|
||||
true || false
|
||||
```
|
||||
|
||||
##### Logical NOT (`!`)
|
||||
|
||||
Returns `true` if the operand is `false`.
|
||||
|
||||
```js
|
||||
!false
|
||||
```
|
||||
|
||||
#### Conditional (ternary) operator
|
||||
|
||||
Returns the first value if the condition is `true`, otherwise it returns the second value.
|
||||
|
||||
```js
|
||||
true ? 1 : 2
|
||||
```
|
||||
|
||||
### Comments
|
||||
|
||||
Comments can be used to document an expression. Comments are treated as whitespace and are ignored by the parser.
|
||||
|
||||
```js
|
||||
/* This is a comment */
|
||||
```
|
|
@ -0,0 +1,3 @@
|
|||
module.exports = {
|
||||
extends: '../internal-js-tests/babel.config.js',
|
||||
};
|
|
@ -0,0 +1,4 @@
|
|||
Significance: minor
|
||||
Type: add
|
||||
|
||||
Initial @woocommerce/expression-evaluation package.
|
|
@ -0,0 +1,32 @@
|
|||
{
|
||||
"name": "woocommerce/expression-evaluation",
|
||||
"description": "WooCommerce expression evaluation library",
|
||||
"type": "library",
|
||||
"license": "GPL-3.0-or-later",
|
||||
"minimum-stability": "dev",
|
||||
"require-dev": {
|
||||
"automattic/jetpack-changelogger": "3.3.0"
|
||||
},
|
||||
"config": {
|
||||
"platform": {
|
||||
"php": "7.2"
|
||||
}
|
||||
},
|
||||
"extra": {
|
||||
"changelogger": {
|
||||
"formatter": {
|
||||
"filename": "../../../tools/changelogger/class-package-formatter.php"
|
||||
},
|
||||
"types": {
|
||||
"fix": "Fixes an existing bug",
|
||||
"add": "Adds functionality",
|
||||
"update": "Update existing functionality",
|
||||
"dev": "Development related task",
|
||||
"tweak": "A minor adjustment to the codebase",
|
||||
"performance": "Address performance issues",
|
||||
"enhancement": "Improve existing functionality"
|
||||
},
|
||||
"changelog": "CHANGELOG.md"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,483 @@
|
|||
{
|
||||
"_readme": [
|
||||
"This file locks the dependencies of your project to a known state",
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "76226c5737d8666789d8a162710469da",
|
||||
"packages": [],
|
||||
"packages-dev": [
|
||||
{
|
||||
"name": "automattic/jetpack-changelogger",
|
||||
"version": "v3.3.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Automattic/jetpack-changelogger.git",
|
||||
"reference": "8f63c829b8d1b0d7b1d5de93510d78523ed18959"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/Automattic/jetpack-changelogger/zipball/8f63c829b8d1b0d7b1d5de93510d78523ed18959",
|
||||
"reference": "8f63c829b8d1b0d7b1d5de93510d78523ed18959",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.6",
|
||||
"symfony/console": "^3.4 || ^5.2 || ^6.0",
|
||||
"symfony/process": "^3.4 || ^5.2 || ^6.0",
|
||||
"wikimedia/at-ease": "^1.2 || ^2.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"wikimedia/testing-access-wrapper": "^1.0 || ^2.0",
|
||||
"yoast/phpunit-polyfills": "1.0.4"
|
||||
},
|
||||
"bin": [
|
||||
"bin/changelogger"
|
||||
],
|
||||
"type": "project",
|
||||
"extra": {
|
||||
"autotagger": true,
|
||||
"branch-alias": {
|
||||
"dev-trunk": "3.3.x-dev"
|
||||
},
|
||||
"mirror-repo": "Automattic/jetpack-changelogger",
|
||||
"version-constants": {
|
||||
"::VERSION": "src/Application.php"
|
||||
},
|
||||
"changelogger": {
|
||||
"link-template": "https://github.com/Automattic/jetpack-changelogger/compare/${old}...${new}"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Automattic\\Jetpack\\Changelog\\": "lib",
|
||||
"Automattic\\Jetpack\\Changelogger\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"GPL-2.0-or-later"
|
||||
],
|
||||
"description": "Jetpack Changelogger tool. Allows for managing changelogs by dropping change files into a changelog directory with each PR.",
|
||||
"support": {
|
||||
"source": "https://github.com/Automattic/jetpack-changelogger/tree/v3.3.0"
|
||||
},
|
||||
"time": "2022-12-26T13:49:01+00:00"
|
||||
},
|
||||
{
|
||||
"name": "psr/log",
|
||||
"version": "1.1.4",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/php-fig/log.git",
|
||||
"reference": "d49695b909c3b7628b6289db5479a1c204601f11"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/php-fig/log/zipball/d49695b909c3b7628b6289db5479a1c204601f11",
|
||||
"reference": "d49695b909c3b7628b6289db5479a1c204601f11",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.1.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Psr\\Log\\": "Psr/Log/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "PHP-FIG",
|
||||
"homepage": "https://www.php-fig.org/"
|
||||
}
|
||||
],
|
||||
"description": "Common interface for logging libraries",
|
||||
"homepage": "https://github.com/php-fig/log",
|
||||
"keywords": [
|
||||
"log",
|
||||
"psr",
|
||||
"psr-3"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/php-fig/log/tree/1.1.4"
|
||||
},
|
||||
"time": "2021-05-03T11:20:27+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/console",
|
||||
"version": "3.4.x-dev",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/console.git",
|
||||
"reference": "a10b1da6fc93080c180bba7219b5ff5b7518fe81"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/console/zipball/a10b1da6fc93080c180bba7219b5ff5b7518fe81",
|
||||
"reference": "a10b1da6fc93080c180bba7219b5ff5b7518fe81",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^5.5.9|>=7.0.8",
|
||||
"symfony/debug": "~2.8|~3.0|~4.0",
|
||||
"symfony/polyfill-mbstring": "~1.0"
|
||||
},
|
||||
"conflict": {
|
||||
"symfony/dependency-injection": "<3.4",
|
||||
"symfony/process": "<3.3"
|
||||
},
|
||||
"provide": {
|
||||
"psr/log-implementation": "1.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"psr/log": "~1.0",
|
||||
"symfony/config": "~3.3|~4.0",
|
||||
"symfony/dependency-injection": "~3.4|~4.0",
|
||||
"symfony/event-dispatcher": "~2.8|~3.0|~4.0",
|
||||
"symfony/lock": "~3.4|~4.0",
|
||||
"symfony/process": "~3.3|~4.0"
|
||||
},
|
||||
"suggest": {
|
||||
"psr/log": "For using the console logger",
|
||||
"symfony/event-dispatcher": "",
|
||||
"symfony/lock": "",
|
||||
"symfony/process": ""
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Symfony\\Component\\Console\\": ""
|
||||
},
|
||||
"exclude-from-classmap": [
|
||||
"/Tests/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Fabien Potencier",
|
||||
"email": "fabien@symfony.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Symfony Console Component",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/console/tree/3.4"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://symfony.com/sponsor",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/fabpot",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2020-10-24T10:57:07+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/debug",
|
||||
"version": "4.4.x-dev",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/debug.git",
|
||||
"reference": "1a692492190773c5310bc7877cb590c04c2f05be"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/debug/zipball/1a692492190773c5310bc7877cb590c04c2f05be",
|
||||
"reference": "1a692492190773c5310bc7877cb590c04c2f05be",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.1.3",
|
||||
"psr/log": "^1|^2|^3"
|
||||
},
|
||||
"conflict": {
|
||||
"symfony/http-kernel": "<3.4"
|
||||
},
|
||||
"require-dev": {
|
||||
"symfony/http-kernel": "^3.4|^4.0|^5.0"
|
||||
},
|
||||
"default-branch": true,
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Symfony\\Component\\Debug\\": ""
|
||||
},
|
||||
"exclude-from-classmap": [
|
||||
"/Tests/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Fabien Potencier",
|
||||
"email": "fabien@symfony.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Provides tools to ease debugging PHP code",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/debug/tree/v4.4.44"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://symfony.com/sponsor",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/fabpot",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"abandoned": "symfony/error-handler",
|
||||
"time": "2022-07-28T16:29:46+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-mbstring",
|
||||
"version": "1.x-dev",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-mbstring.git",
|
||||
"reference": "42292d99c55abe617799667f454222c54c60e229"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/42292d99c55abe617799667f454222c54c60e229",
|
||||
"reference": "42292d99c55abe617799667f454222c54c60e229",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.1"
|
||||
},
|
||||
"provide": {
|
||||
"ext-mbstring": "*"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-mbstring": "For best performance"
|
||||
},
|
||||
"default-branch": true,
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.28-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
"url": "https://github.com/symfony/polyfill"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"files": [
|
||||
"bootstrap.php"
|
||||
],
|
||||
"psr-4": {
|
||||
"Symfony\\Polyfill\\Mbstring\\": ""
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Nicolas Grekas",
|
||||
"email": "p@tchwork.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Symfony polyfill for the Mbstring extension",
|
||||
"homepage": "https://symfony.com",
|
||||
"keywords": [
|
||||
"compatibility",
|
||||
"mbstring",
|
||||
"polyfill",
|
||||
"portable",
|
||||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.28.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://symfony.com/sponsor",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/fabpot",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2023-07-28T09:04:16+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/process",
|
||||
"version": "3.4.x-dev",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/process.git",
|
||||
"reference": "b8648cf1d5af12a44a51d07ef9bf980921f15fca"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/process/zipball/b8648cf1d5af12a44a51d07ef9bf980921f15fca",
|
||||
"reference": "b8648cf1d5af12a44a51d07ef9bf980921f15fca",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^5.5.9|>=7.0.8"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Symfony\\Component\\Process\\": ""
|
||||
},
|
||||
"exclude-from-classmap": [
|
||||
"/Tests/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Fabien Potencier",
|
||||
"email": "fabien@symfony.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Symfony Process Component",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/process/tree/3.4"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://symfony.com/sponsor",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/fabpot",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2020-10-24T10:57:07+00:00"
|
||||
},
|
||||
{
|
||||
"name": "wikimedia/at-ease",
|
||||
"version": "v2.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/wikimedia/at-ease.git",
|
||||
"reference": "013ac61929797839c80a111a3f1a4710d8248e7a"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/wikimedia/at-ease/zipball/013ac61929797839c80a111a3f1a4710d8248e7a",
|
||||
"reference": "013ac61929797839c80a111a3f1a4710d8248e7a",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.6.99"
|
||||
},
|
||||
"require-dev": {
|
||||
"jakub-onderka/php-console-highlighter": "0.3.2",
|
||||
"jakub-onderka/php-parallel-lint": "1.0.0",
|
||||
"mediawiki/mediawiki-codesniffer": "22.0.0",
|
||||
"mediawiki/minus-x": "0.3.1",
|
||||
"ockcyp/covers-validator": "0.5.1 || 0.6.1",
|
||||
"phpunit/phpunit": "4.8.36 || ^6.5"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"files": [
|
||||
"src/Wikimedia/Functions.php"
|
||||
],
|
||||
"psr-4": {
|
||||
"Wikimedia\\AtEase\\": "src/Wikimedia/AtEase/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"GPL-2.0-or-later"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Tim Starling",
|
||||
"email": "tstarling@wikimedia.org"
|
||||
},
|
||||
{
|
||||
"name": "MediaWiki developers",
|
||||
"email": "wikitech-l@lists.wikimedia.org"
|
||||
}
|
||||
],
|
||||
"description": "Safe replacement to @ for suppressing warnings.",
|
||||
"homepage": "https://www.mediawiki.org/wiki/at-ease",
|
||||
"support": {
|
||||
"source": "https://github.com/wikimedia/at-ease/tree/master"
|
||||
},
|
||||
"time": "2018-10-10T15:39:06+00:00"
|
||||
}
|
||||
],
|
||||
"aliases": [],
|
||||
"minimum-stability": "dev",
|
||||
"stability-flags": [],
|
||||
"prefer-stable": false,
|
||||
"prefer-lowest": false,
|
||||
"platform": [],
|
||||
"platform-dev": [],
|
||||
"platform-overrides": {
|
||||
"php": "7.2"
|
||||
},
|
||||
"plugin-api-version": "2.6.0"
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"rootDir": "./src",
|
||||
"preset": "../node_modules/@woocommerce/internal-js-tests/jest-preset.js"
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
{
|
||||
"name": "@woocommerce/expression-evaluation",
|
||||
"version": "0.0.1",
|
||||
"description": "Library for evaluating expressions.",
|
||||
"author": "Automattic",
|
||||
"license": "GPL-3.0-or-later",
|
||||
"keywords": [
|
||||
"wordpress",
|
||||
"woocommerce",
|
||||
"expression",
|
||||
"evalution"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^16.14.1",
|
||||
"pnpm": "^8.6.7"
|
||||
},
|
||||
"homepage": "https://github.com/woocommerce/woocommerce/tree/trunk/packages/js/expression-evaluation/README.md",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/woocommerce/woocommerce.git"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/woocommerce/woocommerce/issues"
|
||||
},
|
||||
"main": "build/index.js",
|
||||
"module": "build-module/index.js",
|
||||
"types": "build-types",
|
||||
"react-native": "src/index",
|
||||
"dependencies": {
|
||||
"@wordpress/i18n": "wp-6.0",
|
||||
"peggy": "^3.0.2"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"scripts": {
|
||||
"turbo:build": "tsc --project tsconfig.json && tsc --project tsconfig-cjs.json",
|
||||
"turbo:test": "jest --config ./jest.config.json",
|
||||
"prepare": "composer install",
|
||||
"changelog": "composer exec -- changelogger",
|
||||
"clean": "pnpm exec rimraf tsconfig.tsbuildinfo build build-*",
|
||||
"build": "pnpm -w exec turbo run turbo:build --filter=$npm_package_name",
|
||||
"test": "pnpm -w exec turbo run turbo:test --filter=$npm_package_name",
|
||||
"lint": "eslint --output-file eslint_report.json --format json src",
|
||||
"start": "concurrently \"tsc --project tsconfig.json --watch\" \"tsc --project tsconfig-cjs.json --watch\"",
|
||||
"prepack": "pnpm run clean && pnpm run build",
|
||||
"lint:fix": "eslint src --fix",
|
||||
"test-staged": "jest --bail --config ./jest.config.json --findRelatedTests"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.17.5",
|
||||
"@types/jest": "^27.4.1",
|
||||
"@woocommerce/eslint-plugin": "workspace:*",
|
||||
"@woocommerce/internal-js-tests": "workspace:*",
|
||||
"concurrently": "^7.0.0",
|
||||
"eslint": "^8.32.0",
|
||||
"jest": "^27.5.1",
|
||||
"jest-cli": "^27.5.1",
|
||||
"rimraf": "^3.0.2",
|
||||
"ts-jest": "^27.1.3",
|
||||
"typescript": "^5.1.6"
|
||||
},
|
||||
"lint-staged": {
|
||||
"*.(t|j)s?(x)": [
|
||||
"pnpm lint:fix",
|
||||
"pnpm test-staged"
|
||||
]
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
|
||||
import { parser } from './parser';
|
||||
|
||||
export function evaluate( expression: string, context = {} ) {
|
||||
return parser.parse( expression, { context } );
|
||||
}
|
|
@ -0,0 +1,404 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import * as peggy from 'peggy';
|
||||
|
||||
const grammar = `
|
||||
{{
|
||||
function evaluateUnaryExpression( operator, operand ) {
|
||||
switch ( operator ) {
|
||||
case '!':
|
||||
return !operand;
|
||||
break;
|
||||
case '-':
|
||||
return -operand;
|
||||
break;
|
||||
case '+':
|
||||
return +operand;
|
||||
break;
|
||||
default:
|
||||
return undefined;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function evaluateBinaryExpression( head, tail ) {
|
||||
return tail.reduce( ( leftOperand, tailElement ) => {
|
||||
const operator = tailElement[ 1 ];
|
||||
const rightOperand = tailElement[ 3 ];
|
||||
|
||||
switch ( operator ) {
|
||||
case '&&':
|
||||
return leftOperand && rightOperand;
|
||||
break;
|
||||
case '||':
|
||||
return leftOperand || rightOperand;
|
||||
break;
|
||||
case '===':
|
||||
return leftOperand === rightOperand;
|
||||
break;
|
||||
case '!==':
|
||||
return leftOperand !== rightOperand;
|
||||
break;
|
||||
case '==':
|
||||
return leftOperand == rightOperand;
|
||||
break;
|
||||
case '!=':
|
||||
return leftOperand != rightOperand;
|
||||
break;
|
||||
case '<=':
|
||||
return leftOperand <= rightOperand;
|
||||
break;
|
||||
case '<':
|
||||
return leftOperand < rightOperand;
|
||||
break;
|
||||
case '>=':
|
||||
return leftOperand >= rightOperand;
|
||||
break;
|
||||
case '>':
|
||||
return leftOperand > rightOperand;
|
||||
break;
|
||||
case '+':
|
||||
return leftOperand + rightOperand;
|
||||
break;
|
||||
case '-':
|
||||
return leftOperand - rightOperand;
|
||||
break;
|
||||
case '*':
|
||||
return leftOperand * rightOperand;
|
||||
break;
|
||||
case '/':
|
||||
return leftOperand / rightOperand;
|
||||
break;
|
||||
case '%':
|
||||
return leftOperand % rightOperand;
|
||||
break;
|
||||
default:
|
||||
return undefined;
|
||||
break;
|
||||
}
|
||||
}, head );
|
||||
}
|
||||
}}
|
||||
|
||||
Start
|
||||
= Expression
|
||||
|
||||
SourceCharacter
|
||||
= .
|
||||
|
||||
WhiteSpace
|
||||
= " "
|
||||
/ "\\t"
|
||||
|
||||
LineTerminator
|
||||
= "\\n"
|
||||
/ "\\r"
|
||||
/ "\\u2028"
|
||||
/ "\\u2029"
|
||||
|
||||
LineTerminatorSequence
|
||||
= "\\n"
|
||||
/ "\\r\\n"
|
||||
/ "\\r"
|
||||
/ "\\u2028"
|
||||
/ "\\u2029"
|
||||
|
||||
Comment "comment"
|
||||
= MultiLineComment
|
||||
|
||||
MultiLineComment
|
||||
= "/*" (!"*/" SourceCharacter)* "*/"
|
||||
|
||||
__ "skipped"
|
||||
= (WhiteSpace / LineTerminatorSequence / Comment)*
|
||||
|
||||
IdentifierPath
|
||||
= variable:Identifier accessor:(__ "." __ Identifier)* {
|
||||
const path = variable.split( '.' );
|
||||
let result = path.reduce( ( nextObject, propertyName ) => nextObject[ propertyName ], options.context );
|
||||
|
||||
for ( let i = 0; i < accessor.length; i++ ) {
|
||||
result = result[ accessor[ i ][ 3 ] ];
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Identifier
|
||||
= !ReservedWord name:IdentifierName {
|
||||
return name;
|
||||
}
|
||||
|
||||
IdentifierName
|
||||
= first:IdentifierStart rest:IdentifierPart* {
|
||||
return text();
|
||||
}
|
||||
|
||||
IdentifierStart
|
||||
= [a-zA-Z]
|
||||
/ "_"
|
||||
/ "$"
|
||||
|
||||
IdentifierPart
|
||||
= IdentifierStart
|
||||
|
||||
ReservedWord
|
||||
= NullLiteral
|
||||
/ BooleanLiteral
|
||||
|
||||
// Literals
|
||||
|
||||
Literal
|
||||
= NullLiteral
|
||||
/ BooleanLiteral
|
||||
/ NumericLiteral
|
||||
/ StringLiteral
|
||||
|
||||
NullLiteral
|
||||
= NullToken { return null; }
|
||||
|
||||
BooleanLiteral
|
||||
= "true" { return true; }
|
||||
/ "false" { return false; }
|
||||
|
||||
NumericLiteral
|
||||
= literal:HexIntegerLiteral !(IdentifierStart / DecimalDigit) {
|
||||
return literal;
|
||||
}
|
||||
/ literal:DecimalLiteral !(IdentifierStart / DecimalDigit) {
|
||||
return literal;
|
||||
}
|
||||
|
||||
HexIntegerLiteral
|
||||
= "0x"i digits:$HexDigit+ {
|
||||
return parseInt( digits, 16 );
|
||||
}
|
||||
|
||||
HexDigit
|
||||
= [0-9a-f]i
|
||||
|
||||
DecimalLiteral
|
||||
= DecimalIntegerLiteral "." DecimalDigit* ExponentPart? {
|
||||
return parseFloat( text() );
|
||||
}
|
||||
/ "." DecimalDigit+ ExponentPart? {
|
||||
return parseFloat( text() );
|
||||
}
|
||||
/ DecimalIntegerLiteral ExponentPart? {
|
||||
return parseFloat( text() );
|
||||
}
|
||||
|
||||
DecimalIntegerLiteral
|
||||
= "0"
|
||||
/ NonZeroDigit DecimalDigit*
|
||||
|
||||
DecimalDigit
|
||||
= [0-9]
|
||||
|
||||
NonZeroDigit
|
||||
= [1-9]
|
||||
|
||||
ExponentPart
|
||||
= ExponentIndicator SignedInteger
|
||||
|
||||
ExponentIndicator
|
||||
= "e"i
|
||||
|
||||
SignedInteger
|
||||
= [+-]? DecimalDigit+
|
||||
|
||||
StringLiteral
|
||||
= '"' chars:DoubleQuotedStringCharacter* '"' {
|
||||
return chars.join( '' );
|
||||
}
|
||||
/ "'" chars:SingleQuotedStringCharacter* "'" {
|
||||
return chars.join( '' );
|
||||
}
|
||||
|
||||
DoubleQuotedStringCharacter
|
||||
= !('"' / "\\\\" / LineTerminator) SourceCharacter {
|
||||
return text();
|
||||
}
|
||||
/ "\\\\" escapeSequence:EscapeSequence {
|
||||
return escapeSequence;
|
||||
}
|
||||
/ LineContinuation
|
||||
|
||||
SingleQuotedStringCharacter
|
||||
= !("'" / "\\\\" / LineTerminator) SourceCharacter {
|
||||
return text();
|
||||
}
|
||||
/ "\\\\" escapeSequence:EscapeSequence {
|
||||
return escapeSequence;
|
||||
}
|
||||
/ LineContinuation
|
||||
|
||||
LineContinuation
|
||||
= "\\\\" LineTerminatorSequence {
|
||||
return '';
|
||||
}
|
||||
|
||||
EscapeSequence
|
||||
= CharacterEscapeSequence
|
||||
/ "0" !DecimalDigit {
|
||||
return "\\0";
|
||||
}
|
||||
/ HexEscapeSequence
|
||||
/ UnicodeEscapeSequence
|
||||
|
||||
CharacterEscapeSequence
|
||||
= SingleEscapeCharacter
|
||||
/ NonEscapeCharacter
|
||||
|
||||
SingleEscapeCharacter
|
||||
= "'"
|
||||
/ '"'
|
||||
/ "\\\\"
|
||||
/ "b" {
|
||||
return "\\b";
|
||||
}
|
||||
/ "f" {
|
||||
return "\\f";
|
||||
}
|
||||
/ "n" {
|
||||
return "\\n";
|
||||
}
|
||||
/ "r" {
|
||||
return "\\r";
|
||||
}
|
||||
/ "t" {
|
||||
return "\\t";
|
||||
}
|
||||
/ "v" {
|
||||
return "\\v";
|
||||
}
|
||||
|
||||
NonEscapeCharacter
|
||||
= (!EscapeCharacter / LineTerminator) SourceCharacter {
|
||||
return text();
|
||||
}
|
||||
|
||||
EscapeCharacter
|
||||
= SingleEscapeCharacter
|
||||
/ DecimalDigit
|
||||
/ "x"
|
||||
/ "u"
|
||||
|
||||
HexEscapeSequence
|
||||
= "x" digits:$(HexDigit HexDigit) {
|
||||
return String.fromCharCode( parseInt( digits, 16 ) );
|
||||
}
|
||||
|
||||
UnicodeEscapeSequence
|
||||
= "u" digits:$(HexDigit HexDigit HexDigit HexDigit) {
|
||||
return String.fromCharCode( parseInt( digits, 16 ) );
|
||||
}
|
||||
|
||||
// Tokens
|
||||
|
||||
NullToken
|
||||
= "null" !IdentifierPart
|
||||
|
||||
TrueToken
|
||||
= "true" !IdentifierPart
|
||||
|
||||
FalseToken
|
||||
= "false" !IdentifierPart
|
||||
|
||||
// Expressions
|
||||
|
||||
PrimaryExpression
|
||||
= IdentifierPath
|
||||
/ Literal
|
||||
/ "(" __ expression:Expression __ ")" {
|
||||
return expression;
|
||||
}
|
||||
|
||||
UnaryExpression
|
||||
= PrimaryExpression
|
||||
/ operator:UnaryOperator __ operand:UnaryExpression {
|
||||
return evaluateUnaryExpression( operator, operand );
|
||||
}
|
||||
|
||||
UnaryOperator
|
||||
= "!"
|
||||
/ "-"
|
||||
/ "+"
|
||||
|
||||
MultiplicativeExpression
|
||||
= head:UnaryExpression tail:(__ MultiplicativeOperator __ UnaryExpression)* {
|
||||
return evaluateBinaryExpression( head, tail );
|
||||
}
|
||||
|
||||
MultiplicativeOperator
|
||||
= "*"
|
||||
/ "/"
|
||||
/ "%"
|
||||
|
||||
AdditiveExpression
|
||||
= head:MultiplicativeExpression tail:(__ AdditiveOperator __ MultiplicativeExpression)* {
|
||||
return evaluateBinaryExpression( head, tail );
|
||||
}
|
||||
|
||||
AdditiveOperator
|
||||
= "+"
|
||||
/ "-"
|
||||
|
||||
RelationalExpression
|
||||
= head:AdditiveExpression tail:(__ RelationalOperator __ AdditiveExpression)* {
|
||||
return evaluateBinaryExpression( head, tail );
|
||||
}
|
||||
|
||||
RelationalOperator
|
||||
= "<="
|
||||
/ "<"
|
||||
/ ">="
|
||||
/ ">"
|
||||
|
||||
EqualityExpression
|
||||
= head:RelationalExpression tail:(__ EqualityOperator __ RelationalExpression)* {
|
||||
return evaluateBinaryExpression( head, tail );
|
||||
}
|
||||
|
||||
EqualityOperator
|
||||
= "==="
|
||||
/ "!=="
|
||||
/ "=="
|
||||
/ "!="
|
||||
|
||||
LogicalAndExpression
|
||||
= head:EqualityExpression tail:(__ LogicalAndOperator __ EqualityExpression)* {
|
||||
return evaluateBinaryExpression( head, tail );
|
||||
}
|
||||
|
||||
LogicalAndOperator
|
||||
= "&&"
|
||||
|
||||
LogicalOrExpression
|
||||
= head:LogicalAndExpression tail:(__ LogicalOrOperator __ LogicalAndExpression)* {
|
||||
return evaluateBinaryExpression( head, tail );
|
||||
}
|
||||
|
||||
LogicalOrOperator
|
||||
= "||"
|
||||
|
||||
ConditionalExpression
|
||||
= condition:LogicalOrExpression __ ConditionalTrueOperator __ expressionIfTrue:ConditionalExpression __ ConditionalFalseOperator __ expressionIfFalse:ConditionalExpression {
|
||||
return condition ? expressionIfTrue : expressionIfFalse;
|
||||
}
|
||||
/ LogicalOrExpression
|
||||
|
||||
ConditionalTrueOperator
|
||||
= "?"
|
||||
|
||||
ConditionalFalseOperator
|
||||
= ":"
|
||||
|
||||
Expression
|
||||
= __ expression:ConditionalExpression __ {
|
||||
return expression;
|
||||
}
|
||||
`;
|
||||
|
||||
export const parser = peggy.generate( grammar );
|
|
@ -0,0 +1,482 @@
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
|
||||
import { evaluate } from '../';
|
||||
|
||||
describe( 'evaluate', () => {
|
||||
it( 'should evaluate a null literal', () => {
|
||||
const result = evaluate( 'null' );
|
||||
|
||||
expect( result ).toEqual( null );
|
||||
} );
|
||||
|
||||
it( 'should evaluate a boolean true literal', () => {
|
||||
const result = evaluate( 'true' );
|
||||
|
||||
expect( result ).toEqual( true );
|
||||
} );
|
||||
|
||||
it( 'should evaluate a boolean false literal', () => {
|
||||
const result = evaluate( 'false' );
|
||||
|
||||
expect( result ).toEqual( false );
|
||||
} );
|
||||
|
||||
it( 'should evaluate a numeric integer literal', () => {
|
||||
const result = evaluate( '23' );
|
||||
|
||||
expect( result ).toEqual( 23 );
|
||||
} );
|
||||
|
||||
it( 'should evaluate a signed negative integer literal', () => {
|
||||
const result = evaluate( '-1' );
|
||||
|
||||
expect( result ).toEqual( -1 );
|
||||
} );
|
||||
|
||||
it( 'should evaluate a signed positive integer literal', () => {
|
||||
const result = evaluate( '+1' );
|
||||
|
||||
expect( result ).toEqual( 1 );
|
||||
} );
|
||||
|
||||
it( 'should evaluate a numeric floating point literal', () => {
|
||||
const result = evaluate( '5.23' );
|
||||
|
||||
expect( result ).toEqual( 5.23 );
|
||||
} );
|
||||
|
||||
it( 'should evaluate a signed negative floating point literal', () => {
|
||||
const result = evaluate( '-9.95' );
|
||||
|
||||
expect( result ).toEqual( -9.95 );
|
||||
} );
|
||||
|
||||
it( 'should evaluate a signed positive floating point literal', () => {
|
||||
const result = evaluate( '+9.95' );
|
||||
|
||||
expect( result ).toEqual( 9.95 );
|
||||
} );
|
||||
|
||||
it( 'should evaluate a numeric hexadecimal literal', () => {
|
||||
const result = evaluate( '0x23' );
|
||||
|
||||
expect( result ).toEqual( 35 );
|
||||
} );
|
||||
|
||||
it( 'should evaluate a string literal with double quotes', () => {
|
||||
const result = evaluate( '"foo"' );
|
||||
|
||||
expect( result ).toEqual( 'foo' );
|
||||
} );
|
||||
|
||||
it( 'should evaluate a string literal with double quotes and single quotes', () => {
|
||||
const result = evaluate( '"foo \'bar\'"' );
|
||||
|
||||
expect( result ).toEqual( "foo 'bar'" );
|
||||
} );
|
||||
|
||||
it( 'should evaluate a string literal with double quotes and escaped double quotes', () => {
|
||||
const result = evaluate( '"foo \\"bar\\""' );
|
||||
|
||||
expect( result ).toEqual( 'foo "bar"' );
|
||||
} );
|
||||
|
||||
it( 'should evaluate a string literal with double quotes and escaped backslashes', () => {
|
||||
// eslint-disable-next-line prettier/prettier
|
||||
const result = evaluate( '"foo \\\\\\"bar\\\\\\""' );
|
||||
|
||||
expect( result ).toEqual( 'foo \\"bar\\"' );
|
||||
} );
|
||||
|
||||
it( 'should evaluate a string literal with single quotes', () => {
|
||||
const result = evaluate( "'foo'" );
|
||||
|
||||
expect( result ).toEqual( 'foo' );
|
||||
} );
|
||||
|
||||
it( 'should evaluate a string literal with single quotes and double quotes', () => {
|
||||
// eslint-disable-next-line prettier/prettier
|
||||
const result = evaluate( "'foo \"bar\"'" );
|
||||
|
||||
expect( result ).toEqual( 'foo "bar"' );
|
||||
} );
|
||||
|
||||
it( 'should evaluate a string literal with single quotes and escaped single quotes', () => {
|
||||
const result = evaluate( "'foo \\'bar\\''" );
|
||||
|
||||
expect( result ).toEqual( "foo 'bar'" );
|
||||
} );
|
||||
|
||||
it( 'should evaluate a string literal with single quotes and escaped backslashes', () => {
|
||||
// eslint-disable-next-line prettier/prettier
|
||||
const result = evaluate( "'foo \\\\\\'bar\\\\\\''" );
|
||||
|
||||
expect( result ).toEqual( "foo \\'bar\\'" );
|
||||
} );
|
||||
|
||||
it( 'should evaluate a literal with whitespace around it', () => {
|
||||
const result = evaluate( ' 23 ' );
|
||||
|
||||
expect( result ).toEqual( 23 );
|
||||
} );
|
||||
|
||||
it( 'should evaluate a top-level context property', () => {
|
||||
const result = evaluate( 'foo', {
|
||||
foo: 'bar',
|
||||
} );
|
||||
|
||||
expect( result ).toEqual( 'bar' );
|
||||
} );
|
||||
|
||||
it( 'should evaluate a top-level context property with whitespace', () => {
|
||||
const result = evaluate( ' foo ', {
|
||||
foo: 'bar',
|
||||
} );
|
||||
|
||||
expect( result ).toEqual( 'bar' );
|
||||
} );
|
||||
|
||||
it( 'should evaluate a nested context property', () => {
|
||||
const result = evaluate( 'foo.bar', {
|
||||
foo: {
|
||||
bar: 'baz',
|
||||
},
|
||||
} );
|
||||
|
||||
expect( result ).toEqual( 'baz' );
|
||||
} );
|
||||
|
||||
it( 'should evaluate a nested context property with whitespace', () => {
|
||||
const result = evaluate( 'foo. bar', {
|
||||
foo: {
|
||||
bar: 'baz',
|
||||
},
|
||||
} );
|
||||
|
||||
expect( result ).toEqual( 'baz' );
|
||||
} );
|
||||
|
||||
it( 'should evaluate a nested context property with multiple lines', () => {
|
||||
const result = evaluate(
|
||||
`foo.
|
||||
bar`,
|
||||
{
|
||||
foo: {
|
||||
bar: 'baz',
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
expect( result ).toEqual( 'baz' );
|
||||
} );
|
||||
|
||||
it( 'should evaluate a NOT expression', () => {
|
||||
const result = evaluate( '!foo', {
|
||||
foo: true,
|
||||
} );
|
||||
|
||||
expect( result ).toEqual( false );
|
||||
} );
|
||||
|
||||
it( 'should evaluate a double NOT expression', () => {
|
||||
const result = evaluate( '!!foo', {
|
||||
foo: true,
|
||||
} );
|
||||
|
||||
expect( result ).toEqual( true );
|
||||
} );
|
||||
|
||||
it( 'should evaluate a NOT expression with parentheses', () => {
|
||||
const result = evaluate( '!( foo )', {
|
||||
foo: true,
|
||||
} );
|
||||
|
||||
expect( result ).toEqual( false );
|
||||
} );
|
||||
|
||||
it( 'should evaluate a NOT expression with parentheses and spaces', () => {
|
||||
const result = evaluate( '! ( foo ) ', {
|
||||
foo: true,
|
||||
} );
|
||||
|
||||
expect( result ).toEqual( false );
|
||||
} );
|
||||
|
||||
it( 'should evaluate a multiplication expression', () => {
|
||||
const result = evaluate( 'foo * 2', {
|
||||
foo: 2,
|
||||
} );
|
||||
|
||||
expect( result ).toEqual( 4 );
|
||||
} );
|
||||
|
||||
it( 'should evaluate a division expression', () => {
|
||||
const result = evaluate( 'foo / 2', {
|
||||
foo: 4,
|
||||
} );
|
||||
|
||||
expect( result ).toEqual( 2 );
|
||||
} );
|
||||
|
||||
it( 'should evaluate a modulo expression', () => {
|
||||
const result = evaluate( 'foo % 2', {
|
||||
foo: 5,
|
||||
} );
|
||||
|
||||
expect( result ).toEqual( 1 );
|
||||
} );
|
||||
|
||||
it( 'should evaluate an addition expression', () => {
|
||||
const result = evaluate( 'foo + 2', {
|
||||
foo: 3,
|
||||
} );
|
||||
|
||||
expect( result ).toEqual( 5 );
|
||||
} );
|
||||
|
||||
it( 'should evaluate a subtraction expression', () => {
|
||||
const result = evaluate( 'foo - 2', {
|
||||
foo: 5,
|
||||
} );
|
||||
|
||||
expect( result ).toEqual( 3 );
|
||||
} );
|
||||
|
||||
it( 'should evaluate a complex arithmetic expression', () => {
|
||||
const result = evaluate( 'foo * 2 + 1', {
|
||||
foo: 3,
|
||||
} );
|
||||
|
||||
expect( result ).toEqual( 7 );
|
||||
} );
|
||||
|
||||
it( 'should evaluate a complex arithmetic expression with parenthesis', () => {
|
||||
const result = evaluate( 'foo * (2 + 1)', {
|
||||
foo: 3,
|
||||
} );
|
||||
|
||||
expect( result ).toEqual( 9 );
|
||||
} );
|
||||
|
||||
it( 'should evaluate a less than or equal expression', () => {
|
||||
const result = evaluate( 'foo <= 1', {
|
||||
foo: 1,
|
||||
} );
|
||||
|
||||
expect( result ).toEqual( true );
|
||||
} );
|
||||
|
||||
it( 'should evaluate a less than expression', () => {
|
||||
const result = evaluate( 'foo < 1', {
|
||||
foo: 1,
|
||||
} );
|
||||
|
||||
expect( result ).toEqual( false );
|
||||
} );
|
||||
|
||||
it( 'should evaluate a greater than or equal expression', () => {
|
||||
const result = evaluate( 'foo >= 1', {
|
||||
foo: 1,
|
||||
} );
|
||||
|
||||
expect( result ).toEqual( true );
|
||||
} );
|
||||
|
||||
it( 'should evaluate a greater than expression', () => {
|
||||
const result = evaluate( 'foo > 1', {
|
||||
foo: 1,
|
||||
} );
|
||||
|
||||
expect( result ).toEqual( false );
|
||||
} );
|
||||
|
||||
it( 'should evaluate an strict equality expression', () => {
|
||||
const result = evaluate( 'foo === "bar"', {
|
||||
foo: 'bar',
|
||||
} );
|
||||
|
||||
expect( result ).toEqual( true );
|
||||
} );
|
||||
|
||||
it( 'should evaluate an strict inequality expression', () => {
|
||||
const result = evaluate( 'foo !== "bar"', {
|
||||
foo: 'bar',
|
||||
} );
|
||||
|
||||
expect( result ).toEqual( false );
|
||||
} );
|
||||
|
||||
it( 'should evaluate an equality expression', () => {
|
||||
const result = evaluate( 'foo == "bar"', {
|
||||
foo: 'bar',
|
||||
} );
|
||||
|
||||
expect( result ).toEqual( true );
|
||||
} );
|
||||
|
||||
it( 'should evaluate an inequality expression', () => {
|
||||
const result = evaluate( 'foo != "bar"', {
|
||||
foo: 'bar',
|
||||
} );
|
||||
|
||||
expect( result ).toEqual( false );
|
||||
} );
|
||||
|
||||
it( 'should evaluate a conditional expression that is true', () => {
|
||||
const result = evaluate( 'foo ? "bar" : "baz"', {
|
||||
foo: true,
|
||||
} );
|
||||
|
||||
expect( result ).toEqual( 'bar' );
|
||||
} );
|
||||
|
||||
it( 'should evaluate a conditional expression that is false', () => {
|
||||
const result = evaluate( 'foo ? "bar" : "baz"', {
|
||||
foo: false,
|
||||
} );
|
||||
|
||||
expect( result ).toEqual( 'baz' );
|
||||
} );
|
||||
|
||||
it( 'should evaluate a logical OR expression', () => {
|
||||
const result = evaluate( 'foo || bar', {
|
||||
foo: true,
|
||||
bar: false,
|
||||
} );
|
||||
|
||||
expect( result ).toEqual( true );
|
||||
} );
|
||||
|
||||
it( 'should evaluate a logical AND expression', () => {
|
||||
const result = evaluate( 'foo && bar', {
|
||||
foo: true,
|
||||
bar: false,
|
||||
} );
|
||||
|
||||
expect( result ).toEqual( false );
|
||||
} );
|
||||
|
||||
it( 'should evaluate a multiline expression', () => {
|
||||
const result = evaluate(
|
||||
`foo
|
||||
|| bar
|
||||
|| baz`,
|
||||
{
|
||||
foo: false,
|
||||
bar: false,
|
||||
baz: true,
|
||||
}
|
||||
);
|
||||
|
||||
expect( result ).toEqual( true );
|
||||
} );
|
||||
|
||||
it( 'should evaluate a complex expression', () => {
|
||||
const result = evaluate(
|
||||
`foo.bar
|
||||
&& ( foo.baz === "qux" || foo.baz === "quux" )`,
|
||||
{
|
||||
foo: {
|
||||
bar: true,
|
||||
baz: 'quux',
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
expect( result ).toEqual( true );
|
||||
} );
|
||||
|
||||
it( 'should evaluate a complex expression with arithmetic, relational, and logical operators', () => {
|
||||
const result = evaluate(
|
||||
`foo.bar
|
||||
&& ( foo.baz === "qux" || foo.baz === "quux" )
|
||||
&& ( foo.quux > 1 && foo.quux <= 5 )`,
|
||||
{
|
||||
foo: {
|
||||
bar: true,
|
||||
baz: 'quux',
|
||||
quux: 10,
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
expect( result ).toEqual( false );
|
||||
} );
|
||||
|
||||
it( 'should evaluate a complex expression with conditional, arithmetic, relational, and logical operators', () => {
|
||||
const result = evaluate(
|
||||
`foo.bar
|
||||
&& ( foo.baz === "qux" || foo.baz === "quux" )
|
||||
&& ( foo.quux > 1 && foo.quux <= 5 )
|
||||
? "boo"
|
||||
: "baa"`,
|
||||
{
|
||||
foo: {
|
||||
bar: true,
|
||||
baz: 'quux',
|
||||
quux: 10,
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
expect( result ).toEqual( 'baa' );
|
||||
} );
|
||||
|
||||
it( 'should evaluate an expression with needless parentheses', () => {
|
||||
const result = evaluate( '(((foo)))', {
|
||||
foo: true,
|
||||
} );
|
||||
|
||||
expect( result ).toEqual( true );
|
||||
} );
|
||||
|
||||
it( 'should evaluate an expression with a multiline comment at the end', () => {
|
||||
const result = evaluate( 'foo /* + 23 */', {
|
||||
foo: 5,
|
||||
} );
|
||||
|
||||
expect( result ).toEqual( 5 );
|
||||
} );
|
||||
|
||||
it( 'should evaluate an expression with a multiline comment at the beginning', () => {
|
||||
const result = evaluate( '/* 23 + */ foo', {
|
||||
foo: 5,
|
||||
} );
|
||||
|
||||
expect( result ).toEqual( 5 );
|
||||
} );
|
||||
|
||||
it( 'should evaluate an expression with a multiline comment in the middle', () => {
|
||||
const result = evaluate( 'foo + /* 23 */ bar', {
|
||||
foo: 5,
|
||||
bar: 3,
|
||||
} );
|
||||
|
||||
expect( result ).toEqual( 8 );
|
||||
} );
|
||||
|
||||
it( 'should evaluate a multiline expression with a multiline comment', () => {
|
||||
const result = evaluate(
|
||||
`foo
|
||||
/*
|
||||
+ bar
|
||||
+ boo
|
||||
*/
|
||||
+ baz`,
|
||||
{
|
||||
foo: 5,
|
||||
bar: 23,
|
||||
boo: 6,
|
||||
baz: 3,
|
||||
}
|
||||
);
|
||||
|
||||
expect( result ).toEqual( 8 );
|
||||
} );
|
||||
|
||||
it( 'should throw an error if the expression is invalid', () => {
|
||||
expect( () => evaluate( '= 1' ) ).toThrow();
|
||||
} );
|
||||
} );
|
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"extends": "../tsconfig-cjs",
|
||||
"compilerOptions": {
|
||||
"declaration": true,
|
||||
"outDir": "build",
|
||||
"typeRoots": [
|
||||
"./typings",
|
||||
"./node_modules/@types"
|
||||
]
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"extends": "../tsconfig",
|
||||
"compilerOptions": {
|
||||
"rootDir": "src",
|
||||
"outDir": "build-module",
|
||||
"declaration": true,
|
||||
"declarationMap": true,
|
||||
"declarationDir": "./build-types",
|
||||
"typeRoots": [
|
||||
"./typings",
|
||||
"./node_modules/@types"
|
||||
]
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
module.exports = {
|
||||
extends: [ 'plugin:@woocommerce/eslint-plugin/recommended' ],
|
||||
root: true,
|
||||
overrides: [
|
||||
{
|
||||
files: [ '**/*.js', '**/*.jsx', '**/*.tsx' ],
|
||||
rules: {
|
||||
'react/react-in-jsx-scope': 'off',
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
|
@ -0,0 +1 @@
|
|||
package-lock=false
|
|
@ -0,0 +1,4 @@
|
|||
# @woocommerce/integrate-plugin
|
||||
|
||||
Integrate plugin is a tool to help existing WordPress plugins get set up with JavaScript & React in order to extend and create Blocks.
|
||||
The tool can also be used for scaffolding block examples.
|
|
@ -0,0 +1,3 @@
|
|||
module.exports = {
|
||||
extends: '../internal-js-tests/babel.config.js',
|
||||
};
|
|
@ -0,0 +1,3 @@
|
|||
#!/usr/bin/env node
|
||||
|
||||
require( '../build' );
|
|
@ -0,0 +1,3 @@
|
|||
# Changelog
|
||||
|
||||
This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
@ -0,0 +1,4 @@
|
|||
Significance: minor
|
||||
Type: add
|
||||
|
||||
Add initial scripts for integrate plugin to get plugin details.
|
|
@ -0,0 +1,4 @@
|
|||
Significance: minor
|
||||
Type: add
|
||||
|
||||
Initial version of @woocommerce/block-templates package. Adds registerWooBlockType and useWooBlockProps.
|
|
@ -0,0 +1,4 @@
|
|||
Significance: patch
|
||||
Type: dev
|
||||
Comment: This is just a change to developer commands.
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
{
|
||||
"name": "woocommerce/block-templates",
|
||||
"description": "WooCommerce Admin block templates component library",
|
||||
"type": "library",
|
||||
"license": "GPL-3.0-or-later",
|
||||
"minimum-stability": "dev",
|
||||
"require-dev": {
|
||||
"automattic/jetpack-changelogger": "3.3.0"
|
||||
},
|
||||
"config": {
|
||||
"platform": {
|
||||
"php": "7.2"
|
||||
}
|
||||
},
|
||||
"extra": {
|
||||
"changelogger": {
|
||||
"formatter": {
|
||||
"filename": "../../../tools/changelogger/class-package-formatter.php"
|
||||
},
|
||||
"types": {
|
||||
"fix": "Fixes an existing bug",
|
||||
"add": "Adds functionality",
|
||||
"update": "Update existing functionality",
|
||||
"dev": "Development related task",
|
||||
"tweak": "A minor adjustment to the codebase",
|
||||
"performance": "Address performance issues",
|
||||
"enhancement": "Improve existing functionality"
|
||||
},
|
||||
"changelog": "CHANGELOG.md"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,483 @@
|
|||
{
|
||||
"_readme": [
|
||||
"This file locks the dependencies of your project to a known state",
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "2d316cec186ab12385e8dda54f6df0f6",
|
||||
"packages": [],
|
||||
"packages-dev": [
|
||||
{
|
||||
"name": "automattic/jetpack-changelogger",
|
||||
"version": "v3.3.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Automattic/jetpack-changelogger.git",
|
||||
"reference": "8f63c829b8d1b0d7b1d5de93510d78523ed18959"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/Automattic/jetpack-changelogger/zipball/8f63c829b8d1b0d7b1d5de93510d78523ed18959",
|
||||
"reference": "8f63c829b8d1b0d7b1d5de93510d78523ed18959",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.6",
|
||||
"symfony/console": "^3.4 || ^5.2 || ^6.0",
|
||||
"symfony/process": "^3.4 || ^5.2 || ^6.0",
|
||||
"wikimedia/at-ease": "^1.2 || ^2.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"wikimedia/testing-access-wrapper": "^1.0 || ^2.0",
|
||||
"yoast/phpunit-polyfills": "1.0.4"
|
||||
},
|
||||
"bin": [
|
||||
"bin/changelogger"
|
||||
],
|
||||
"type": "project",
|
||||
"extra": {
|
||||
"autotagger": true,
|
||||
"branch-alias": {
|
||||
"dev-trunk": "3.3.x-dev"
|
||||
},
|
||||
"mirror-repo": "Automattic/jetpack-changelogger",
|
||||
"version-constants": {
|
||||
"::VERSION": "src/Application.php"
|
||||
},
|
||||
"changelogger": {
|
||||
"link-template": "https://github.com/Automattic/jetpack-changelogger/compare/${old}...${new}"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Automattic\\Jetpack\\Changelog\\": "lib",
|
||||
"Automattic\\Jetpack\\Changelogger\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"GPL-2.0-or-later"
|
||||
],
|
||||
"description": "Jetpack Changelogger tool. Allows for managing changelogs by dropping change files into a changelog directory with each PR.",
|
||||
"support": {
|
||||
"source": "https://github.com/Automattic/jetpack-changelogger/tree/v3.3.0"
|
||||
},
|
||||
"time": "2022-12-26T13:49:01+00:00"
|
||||
},
|
||||
{
|
||||
"name": "psr/log",
|
||||
"version": "1.1.4",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/php-fig/log.git",
|
||||
"reference": "d49695b909c3b7628b6289db5479a1c204601f11"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/php-fig/log/zipball/d49695b909c3b7628b6289db5479a1c204601f11",
|
||||
"reference": "d49695b909c3b7628b6289db5479a1c204601f11",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.1.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Psr\\Log\\": "Psr/Log/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "PHP-FIG",
|
||||
"homepage": "https://www.php-fig.org/"
|
||||
}
|
||||
],
|
||||
"description": "Common interface for logging libraries",
|
||||
"homepage": "https://github.com/php-fig/log",
|
||||
"keywords": [
|
||||
"log",
|
||||
"psr",
|
||||
"psr-3"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/php-fig/log/tree/1.1.4"
|
||||
},
|
||||
"time": "2021-05-03T11:20:27+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/console",
|
||||
"version": "3.4.x-dev",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/console.git",
|
||||
"reference": "a10b1da6fc93080c180bba7219b5ff5b7518fe81"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/console/zipball/a10b1da6fc93080c180bba7219b5ff5b7518fe81",
|
||||
"reference": "a10b1da6fc93080c180bba7219b5ff5b7518fe81",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^5.5.9|>=7.0.8",
|
||||
"symfony/debug": "~2.8|~3.0|~4.0",
|
||||
"symfony/polyfill-mbstring": "~1.0"
|
||||
},
|
||||
"conflict": {
|
||||
"symfony/dependency-injection": "<3.4",
|
||||
"symfony/process": "<3.3"
|
||||
},
|
||||
"provide": {
|
||||
"psr/log-implementation": "1.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"psr/log": "~1.0",
|
||||
"symfony/config": "~3.3|~4.0",
|
||||
"symfony/dependency-injection": "~3.4|~4.0",
|
||||
"symfony/event-dispatcher": "~2.8|~3.0|~4.0",
|
||||
"symfony/lock": "~3.4|~4.0",
|
||||
"symfony/process": "~3.3|~4.0"
|
||||
},
|
||||
"suggest": {
|
||||
"psr/log": "For using the console logger",
|
||||
"symfony/event-dispatcher": "",
|
||||
"symfony/lock": "",
|
||||
"symfony/process": ""
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Symfony\\Component\\Console\\": ""
|
||||
},
|
||||
"exclude-from-classmap": [
|
||||
"/Tests/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Fabien Potencier",
|
||||
"email": "fabien@symfony.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Symfony Console Component",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/console/tree/3.4"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://symfony.com/sponsor",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/fabpot",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2020-10-24T10:57:07+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/debug",
|
||||
"version": "4.4.x-dev",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/debug.git",
|
||||
"reference": "1a692492190773c5310bc7877cb590c04c2f05be"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/debug/zipball/1a692492190773c5310bc7877cb590c04c2f05be",
|
||||
"reference": "1a692492190773c5310bc7877cb590c04c2f05be",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.1.3",
|
||||
"psr/log": "^1|^2|^3"
|
||||
},
|
||||
"conflict": {
|
||||
"symfony/http-kernel": "<3.4"
|
||||
},
|
||||
"require-dev": {
|
||||
"symfony/http-kernel": "^3.4|^4.0|^5.0"
|
||||
},
|
||||
"default-branch": true,
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Symfony\\Component\\Debug\\": ""
|
||||
},
|
||||
"exclude-from-classmap": [
|
||||
"/Tests/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Fabien Potencier",
|
||||
"email": "fabien@symfony.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Provides tools to ease debugging PHP code",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/debug/tree/v4.4.44"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://symfony.com/sponsor",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/fabpot",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"abandoned": "symfony/error-handler",
|
||||
"time": "2022-07-28T16:29:46+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-mbstring",
|
||||
"version": "1.x-dev",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-mbstring.git",
|
||||
"reference": "42292d99c55abe617799667f454222c54c60e229"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/42292d99c55abe617799667f454222c54c60e229",
|
||||
"reference": "42292d99c55abe617799667f454222c54c60e229",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.1"
|
||||
},
|
||||
"provide": {
|
||||
"ext-mbstring": "*"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-mbstring": "For best performance"
|
||||
},
|
||||
"default-branch": true,
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.28-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
"url": "https://github.com/symfony/polyfill"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"files": [
|
||||
"bootstrap.php"
|
||||
],
|
||||
"psr-4": {
|
||||
"Symfony\\Polyfill\\Mbstring\\": ""
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Nicolas Grekas",
|
||||
"email": "p@tchwork.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Symfony polyfill for the Mbstring extension",
|
||||
"homepage": "https://symfony.com",
|
||||
"keywords": [
|
||||
"compatibility",
|
||||
"mbstring",
|
||||
"polyfill",
|
||||
"portable",
|
||||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.28.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://symfony.com/sponsor",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/fabpot",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2023-07-28T09:04:16+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/process",
|
||||
"version": "3.4.x-dev",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/process.git",
|
||||
"reference": "b8648cf1d5af12a44a51d07ef9bf980921f15fca"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/process/zipball/b8648cf1d5af12a44a51d07ef9bf980921f15fca",
|
||||
"reference": "b8648cf1d5af12a44a51d07ef9bf980921f15fca",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^5.5.9|>=7.0.8"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Symfony\\Component\\Process\\": ""
|
||||
},
|
||||
"exclude-from-classmap": [
|
||||
"/Tests/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Fabien Potencier",
|
||||
"email": "fabien@symfony.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Symfony Process Component",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/process/tree/3.4"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://symfony.com/sponsor",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/fabpot",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2020-10-24T10:57:07+00:00"
|
||||
},
|
||||
{
|
||||
"name": "wikimedia/at-ease",
|
||||
"version": "v2.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/wikimedia/at-ease.git",
|
||||
"reference": "013ac61929797839c80a111a3f1a4710d8248e7a"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/wikimedia/at-ease/zipball/013ac61929797839c80a111a3f1a4710d8248e7a",
|
||||
"reference": "013ac61929797839c80a111a3f1a4710d8248e7a",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.6.99"
|
||||
},
|
||||
"require-dev": {
|
||||
"jakub-onderka/php-console-highlighter": "0.3.2",
|
||||
"jakub-onderka/php-parallel-lint": "1.0.0",
|
||||
"mediawiki/mediawiki-codesniffer": "22.0.0",
|
||||
"mediawiki/minus-x": "0.3.1",
|
||||
"ockcyp/covers-validator": "0.5.1 || 0.6.1",
|
||||
"phpunit/phpunit": "4.8.36 || ^6.5"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"files": [
|
||||
"src/Wikimedia/Functions.php"
|
||||
],
|
||||
"psr-4": {
|
||||
"Wikimedia\\AtEase\\": "src/Wikimedia/AtEase/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"GPL-2.0-or-later"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Tim Starling",
|
||||
"email": "tstarling@wikimedia.org"
|
||||
},
|
||||
{
|
||||
"name": "MediaWiki developers",
|
||||
"email": "wikitech-l@lists.wikimedia.org"
|
||||
}
|
||||
],
|
||||
"description": "Safe replacement to @ for suppressing warnings.",
|
||||
"homepage": "https://www.mediawiki.org/wiki/at-ease",
|
||||
"support": {
|
||||
"source": "https://github.com/wikimedia/at-ease/tree/master"
|
||||
},
|
||||
"time": "2018-10-10T15:39:06+00:00"
|
||||
}
|
||||
],
|
||||
"aliases": [],
|
||||
"minimum-stability": "dev",
|
||||
"stability-flags": [],
|
||||
"prefer-stable": false,
|
||||
"prefer-lowest": false,
|
||||
"platform": [],
|
||||
"platform-dev": [],
|
||||
"platform-overrides": {
|
||||
"php": "7.2"
|
||||
},
|
||||
"plugin-api-version": "2.6.0"
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"rootDir": "./src",
|
||||
"preset": "../node_modules/@woocommerce/internal-js-tests/jest-preset.js"
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
{
|
||||
"name": "@woocommerce/integrate-plugin",
|
||||
"version": "0.1.0",
|
||||
"description": "WooCommerce plugin integration scripts.",
|
||||
"author": "Automattic",
|
||||
"license": "GPL-3.0-or-later",
|
||||
"keywords": [
|
||||
"wordpress",
|
||||
"woocommerce",
|
||||
"plugin"
|
||||
],
|
||||
"homepage": "https://github.com/woocommerce/woocommerce/tree/trunk/packages/js/integrate-plugin/README.md",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/woocommerce/woocommerce.git"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/woocommerce/woocommerce/issues"
|
||||
},
|
||||
"main": "build/index.js",
|
||||
"bin": {
|
||||
"woo-integrate-plugin": "./build/index.js"
|
||||
},
|
||||
"types": "build-types",
|
||||
"react-native": "src/index",
|
||||
"sideEffects": [],
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"dependencies": {
|
||||
"@wordpress/create-block": "wp-6.0",
|
||||
"chalk": "^4.1.2",
|
||||
"change-case": "^4.1.2",
|
||||
"commander": "^9.2.0",
|
||||
"execa": "^4.0.2",
|
||||
"fast-glob": "^3.2.7",
|
||||
"inquirer": "^7.1.0",
|
||||
"npm-package-arg": "^8.1.5",
|
||||
"rimraf": "^3.0.2",
|
||||
"write-pkg": "^4.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.21.3",
|
||||
"@babel/runtime": "^7.17.2",
|
||||
"@testing-library/jest-dom": "^5.16.2",
|
||||
"@testing-library/react-hooks": "^8.0.1",
|
||||
"@types/jest": "^27.4.1",
|
||||
"@types/node": "^16.18.18",
|
||||
"@types/testing-library__jest-dom": "^5.14.3",
|
||||
"@woocommerce/eslint-plugin": "workspace:*",
|
||||
"@woocommerce/internal-js-tests": "workspace:*",
|
||||
"@wordpress/browserslist-config": "wp-6.0",
|
||||
"copy-webpack-plugin": "^9.1.0",
|
||||
"css-loader": "^3.6.0",
|
||||
"eslint": "^8.32.0",
|
||||
"jest": "^27.5.1",
|
||||
"jest-cli": "^27.5.1",
|
||||
"rimraf": "^3.0.2",
|
||||
"ts-jest": "^27.1.3",
|
||||
"typescript": "^5.1.6",
|
||||
"webpack": "^5.70.0",
|
||||
"webpack-cli": "^3.3.12"
|
||||
},
|
||||
"scripts": {
|
||||
"turbo:build": "pnpm run build:js",
|
||||
"turbo:test": "jest --config ./jest.config.json",
|
||||
"prepare": "composer install",
|
||||
"changelog": "composer exec -- changelogger",
|
||||
"clean": "pnpm exec rimraf tsconfig.tsbuildinfo build build-*",
|
||||
"build": "pnpm -w exec turbo run turbo:build --filter=$npm_package_name",
|
||||
"test": "pnpm test:js",
|
||||
"test:js": "pnpm -w exec turbo run turbo:test --filter=$npm_package_name",
|
||||
"lint": "eslint --output-file eslint_report.json --format json src",
|
||||
"build:js": "tsc --project tsconfig.json && tsc --project tsconfig-cjs.json",
|
||||
"start": "concurrently \"tsc --project tsconfig.json --watch\" \"tsc --project tsconfig-cjs.json --watch\" \"webpack --watch\"",
|
||||
"prepack": "pnpm run clean && pnpm run build",
|
||||
"lint:fix": "eslint src --fix"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { existsSync, readFileSync, promises } from 'fs';
|
||||
import { join } from 'path';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { info } from './log';
|
||||
|
||||
const { writeFile } = promises;
|
||||
function getUniqueItems( arr: string[] ) {
|
||||
const uniqueObject = arr.reduce( ( unique, item ) => {
|
||||
unique[ item ] = true;
|
||||
return unique;
|
||||
}, {} as Record< string, boolean > );
|
||||
|
||||
return Object.keys( uniqueObject );
|
||||
}
|
||||
|
||||
const getPluginConfig = () => {
|
||||
const cwd = join( process.cwd() );
|
||||
|
||||
if ( ! existsSync( join( cwd, '.woo-plugin.json' ) ) ) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return JSON.parse(
|
||||
readFileSync( join( cwd, '.woo-plugin.json' ), 'utf8' )
|
||||
);
|
||||
};
|
||||
|
||||
const updateConfig = async ( { modules }: { modules: string[] } ) => {
|
||||
const cwd = join( process.cwd() );
|
||||
const config = getPluginConfig();
|
||||
|
||||
const uniqueModules = modules.reduce( ( unique, module ) => {
|
||||
unique[ module ] = true;
|
||||
return unique;
|
||||
}, {} as Record< string, boolean > );
|
||||
|
||||
config.modules = Object.keys( uniqueModules );
|
||||
|
||||
info( '' );
|
||||
info( 'Updating plugin config file.' );
|
||||
|
||||
await writeFile(
|
||||
join( cwd, '.woo-plugin.json' ),
|
||||
JSON.stringify( config, null, 4 )
|
||||
);
|
||||
};
|
||||
|
||||
export { getPluginConfig, getUniqueItems, updateConfig };
|
|
@ -0,0 +1,40 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { readdirSync, readFileSync } from 'fs';
|
||||
import CLIError from '@wordpress/create-block/lib/cli-error';
|
||||
import path from 'path';
|
||||
|
||||
/**
|
||||
* Get the plugin data.
|
||||
*
|
||||
* @return {Object} - Plugin data as key value pairs.
|
||||
*/
|
||||
export function getPluginData() {
|
||||
const files = readdirSync( process.cwd() );
|
||||
for ( let i = 0; i < files.length; i++ ) {
|
||||
const file = path.join( process.cwd(), files[ i ] );
|
||||
if ( path.extname( file ) !== '.php' ) {
|
||||
continue;
|
||||
}
|
||||
const content = readFileSync( file, 'utf8' );
|
||||
const name = content.match( /^\s+\*\s*Plugin Name:\s*(.*)/m );
|
||||
if ( name && name.length > 1 ) {
|
||||
const description = content.match(
|
||||
/^\s+\*\s+Description:\s*(.*)/m
|
||||
);
|
||||
const textdomain = content.match( /^\s+\*\s*Text Domain:\s*(.*)/m );
|
||||
const version = content.match( /^\s+\*\s*Version:\s*(.*)/m );
|
||||
|
||||
return {
|
||||
description: description && description[ 1 ].trim(),
|
||||
name: name[ 1 ].trim(),
|
||||
textdomain: textdomain && textdomain[ 1 ].trim(),
|
||||
version: version && version[ 1 ].trim(),
|
||||
namespace: textdomain && textdomain[ 1 ].trim(),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
throw new CLIError( 'Plugin file not found.' );
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
#!/usr/bin/env node
|
||||
|
||||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { Command } from 'commander';
|
||||
import CLIError from '@wordpress/create-block/lib/cli-error';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import * as log from './log';
|
||||
import { getPluginData } from './get-plugin-data';
|
||||
import { getPluginConfig } from './get-plugin-config';
|
||||
|
||||
//add the following line
|
||||
const program = new Command();
|
||||
|
||||
const commandName = `woo-integrate-plugin`;
|
||||
program
|
||||
.name( commandName )
|
||||
.description(
|
||||
'Integrates a plugin with WooCommerce build scripts and dependencies.\n\n' +
|
||||
'The provided build scripts provide an easy way to build in a modern ' +
|
||||
'JS environment and automatically assist in building block assets. '
|
||||
)
|
||||
.version( '0.1.0' )
|
||||
.option(
|
||||
'--wp-scripts',
|
||||
'enable integration with `@wordpress/scripts` package'
|
||||
)
|
||||
.option(
|
||||
'--no-wp-scripts',
|
||||
'disable integration with `@wordpress/scripts` package'
|
||||
)
|
||||
.option(
|
||||
'-t, --template <name>',
|
||||
'project template type name; allowed values: "standard", "es5", the name of an external npm package, or the path to a local directory',
|
||||
'standard'
|
||||
)
|
||||
.option( '--variant <variant>', 'the variant of the template to use' )
|
||||
.option( '--wp-env', 'enable integration with `@wordpress/env` package' )
|
||||
.option(
|
||||
'--includes-dir <dir>',
|
||||
'the path to the includes directory with backend logic'
|
||||
)
|
||||
.option(
|
||||
'--src-dir <dir>',
|
||||
'the path to the src directory with client-side logic'
|
||||
)
|
||||
.option( '--namespace <value>', 'internal namespace for the plugin' )
|
||||
.action( async () => {
|
||||
try {
|
||||
const pluginData = getPluginData();
|
||||
const pluginConfig = getPluginConfig();
|
||||
log.info( JSON.stringify( pluginData ) );
|
||||
log.info( JSON.stringify( pluginConfig ) );
|
||||
} catch ( error ) {
|
||||
if ( error instanceof CLIError ) {
|
||||
log.error( error.message );
|
||||
process.exit( 1 );
|
||||
} else {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
} )
|
||||
.on( '--help', () => {
|
||||
log.info( '' );
|
||||
log.info( 'Examples:' );
|
||||
log.info( ` $ ${ commandName }` );
|
||||
log.info( ` $ ${ commandName } todo-list` );
|
||||
log.info(
|
||||
` $ ${ commandName } todo-list --template es5 --title "TODO List"`
|
||||
);
|
||||
} )
|
||||
.parse( process.argv );
|
|
@ -0,0 +1,23 @@
|
|||
/* eslint-disable no-console */
|
||||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import chalk from 'chalk';
|
||||
|
||||
const code = ( input: string ) => {
|
||||
console.log( chalk.cyan( input ) );
|
||||
};
|
||||
|
||||
const error = ( input: string ) => {
|
||||
console.log( chalk.bold.red( input ) );
|
||||
};
|
||||
|
||||
const info = ( input: string ) => {
|
||||
console.log( input );
|
||||
};
|
||||
const success = ( input: string ) => {
|
||||
console.log( chalk.bold.green( input ) );
|
||||
};
|
||||
|
||||
export { code, error, info, success };
|
||||
/* eslint-enable no-console */
|
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
"extends": "../tsconfig-cjs",
|
||||
"include": [
|
||||
"**/*.d.ts",
|
||||
"src/**/*",
|
||||
"src/**/*.json"
|
||||
],
|
||||
"compilerOptions": {
|
||||
"outDir": "build",
|
||||
"resolveJsonModule": true,
|
||||
"typeRoots": [
|
||||
"./typings",
|
||||
"./node_modules/@types"
|
||||
]
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"extends": "../tsconfig",
|
||||
"compilerOptions": {
|
||||
"rootDir": "src",
|
||||
"outDir": "build-module",
|
||||
"declaration": true,
|
||||
"declarationMap": true,
|
||||
"declarationDir": "./build-types",
|
||||
"resolveJsonModule": true,
|
||||
"typeRoots": [ "./typings", "./node_modules/@types" ]
|
||||
},
|
||||
"include": [ "**/*.d.ts", "src/**/*", "src/**/*.json" ]
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
declare module '@wordpress/create-block/lib/cli-error' {
|
||||
export default Error;
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
Significance: patch
|
||||
Type: dev
|
||||
Comment: This is just a change to developer commands.
|
||||
|
|
@ -51,7 +51,8 @@
|
|||
"changelog": "composer exec -- changelogger",
|
||||
"clean": "pnpm exec rimraf tsconfig.tsbuildinfo build build-*",
|
||||
"build": "pnpm -w exec turbo run turbo:build --filter=$npm_package_name",
|
||||
"test": "pnpm -w exec turbo run turbo:test --filter=$npm_package_name",
|
||||
"test": "pnpm test:js",
|
||||
"test:js": "pnpm -w exec turbo run turbo:test --filter=$npm_package_name",
|
||||
"lint": "eslint --output-file eslint_report.json --format json src",
|
||||
"start": "concurrently \"tsc --project tsconfig.json --watch\" \"tsc --project tsconfig-cjs.json --watch\"",
|
||||
"prepack": "pnpm run clean && pnpm run build",
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
Significance: patch
|
||||
Type: dev
|
||||
Comment: This is just a change to developer commands.
|
||||
|
|
@ -37,7 +37,8 @@
|
|||
"changelog": "composer exec -- changelogger",
|
||||
"clean": "pnpm exec rimraf tsconfig.tsbuildinfo build build-*",
|
||||
"build": "pnpm -w exec turbo run turbo:build --filter=$npm_package_name",
|
||||
"test": "pnpm -w exec turbo run turbo:test --filter=$npm_package_name",
|
||||
"test": "pnpm test:js",
|
||||
"test:js": "pnpm -w exec turbo run turbo:test --filter=$npm_package_name",
|
||||
"lint": "eslint --output-file eslint_report.json --format json src",
|
||||
"start": "concurrently \"tsc --project tsconfig.json --watch\" \"tsc --project tsconfig-cjs.json --watch\"",
|
||||
"prepack": "pnpm run clean && pnpm run build",
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
Significance: patch
|
||||
Type: dev
|
||||
Comment: This is just a change to developer commands.
|
||||
|
|
@ -79,7 +79,8 @@
|
|||
"build:js": "tsc --project tsconfig.json && tsc --project tsconfig-cjs.json",
|
||||
"build:css": "webpack",
|
||||
"start": "concurrently \"tsc --project tsconfig.json --watch\" \"tsc --project tsconfig-cjs.json --watch\" \"webpack --watch\"",
|
||||
"test": "pnpm -w exec turbo run turbo:test --filter=$npm_package_name",
|
||||
"test": "pnpm test:js",
|
||||
"test:js": "pnpm -w exec turbo run turbo:test --filter=$npm_package_name",
|
||||
"prepack": "pnpm run clean && pnpm run build",
|
||||
"lint:fix": "eslint src --fix",
|
||||
"test-staged": "jest --bail --config ./jest.config.json --findRelatedTests"
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
Significance: minor
|
||||
Type: add
|
||||
|
||||
Add download file list product block
|
|
@ -0,0 +1,4 @@
|
|||
Significance: minor
|
||||
Type: add
|
||||
|
||||
Set shipping disabled when the product is virtual
|
|
@ -0,0 +1,4 @@
|
|||
Significance: minor
|
||||
Type: add
|
||||
|
||||
Show a summary when adding or removing variation option values
|
|
@ -0,0 +1,4 @@
|
|||
Significance: minor
|
||||
Type: add
|
||||
|
||||
Add virtual and downloads related controls to variation management quick actions
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue