diff --git a/.github/workflows/regression.yml b/.github/workflows/regression.yml index 3bb00ef..dfa6584 100644 --- a/.github/workflows/regression.yml +++ b/.github/workflows/regression.yml @@ -45,7 +45,7 @@ jobs: - run: sudo apt-get update && sudo apt-get install -y mariadb-client - name: Install isolated test browser run: | - npm install --prefix "$RUNNER_TEMP/hcr-browser" --ignore-scripts playwright@1.62.1 + npm install --prefix "$RUNNER_TEMP/hcr-browser" --ignore-scripts playwright@1.62.1 jsqr@1.4.0 "$RUNNER_TEMP/hcr-browser/node_modules/.bin/playwright" install --with-deps chromium echo "NODE_PATH=$RUNNER_TEMP/hcr-browser/node_modules" >> "$GITHUB_ENV" echo "HCR_TEST_CHROME=$(node -p "require('$RUNNER_TEMP/hcr-browser/node_modules/playwright').chromium.executablePath()")" >> "$GITHUB_ENV" diff --git a/CLUB-MODALS-2026-10-20.md b/CLUB-MODALS-2026-10-20.md new file mode 100644 index 0000000..4b6f9e3 --- /dev/null +++ b/CLUB-MODALS-2026-10-20.md @@ -0,0 +1,51 @@ +# Club summary action dialogs + +Club add/edit forms now open in Bootstrap modals. The summary shows club details, +tables, history and action buttons; it no longer displays editing fields inline. + +Dialogs cover club editing/archiving, membership edits, existing-account +assignment, invitations, invitation revocation, new seasons, recording dues and +payments, dues corrections and payment reversals. The Invite members header +action opens its dialog directly. Existing-record dialogs identify the selected +member, dues or payment row. Separate club creation and ticket pages retain their +existing workflows. + +`classes/ClubFormModals.php` transforms only the club forms the server has already +authorized for the viewer. It moves dialogs outside the tables, supplies unique +IDs, labelled headings, close and cancel controls, and scrollable phone-friendly +layouts. Members receive no administrator forms or action dialogs. + +`js/club-modals.js` submits these forms through the existing protected club +controller. Validation and permission errors appear inside the dialog without +clearing entered values. Saving disables action buttons and prevents dismissal +until the response returns; existing financial request keys are retained. +Successful saves reload the club summary and display its success notice. Cancel, +close and Escape dismiss an idle dialog without submitting changes. Bootstrap +provides focus containment and returns focus to the opening action. + +`classes/Roster.php` renders the dialog layout and returns a JSON success result +only for the modal's explicitly marked AJAX requests. Existing ordinary POST +flows retain their redirects. All existing CSRF, tenant access, recent MFA, +validation, audit and financial safeguards continue to run on the server. + +Browser regressions exercise the real dialogs rather than hidden forms, +including cancellation, validation failures, membership changes, invitation +delivery feedback, seasons, dues, payments, corrections and reversals. Release +packaging checks require both new files. No new dependency or database migration +is required. + +Validation passed 262 targeted checks: 99 project HTTP, 19 onboarding HTTP, +33 general browser, 19 tenant browser, 16 deployment tooling, 24 MFA/session HTTP, +41 security/capacity service and 11 paging/export HTTP checks. Source validation +passed for 66 PHP files, 58 JavaScript files and 39 XSL stylesheets. Browser tests +also verify club edits, cancellation of invitation revocation, phone dialog +width, first-field focus and focus restoration after Escape. + +The three application files were deployed to development and their hashes +verified. A protected temporary runtime check confirmed server-side dialog +rendering, and the new script was fetched successfully; the probe was removed. +Prior files were saved under +`.tools/deployment-backups/club-modals-07cbd8d9f91242e19f5501609489e35a`. +No existing development database records were changed. Tests used disposable +local databases and generated accounts with external email disabled; the local +test database server was stopped after cleanup. diff --git a/CLUB-UI-AND-SIGNUP-2026-10-20.md b/CLUB-UI-AND-SIGNUP-2026-10-20.md new file mode 100644 index 0000000..1dcb676 --- /dev/null +++ b/CLUB-UI-AND-SIGNUP-2026-10-20.md @@ -0,0 +1,74 @@ +# Club summary and new-club signup + +The club page follows the flow of `xsl/userSummary.xsl`: identity and status at +the top, a compact action row, then clearly headed tables and supporting details. +The reference stylesheet itself is unchanged. + +## Club page + +- The selected club name is the page heading, followed by its status and the + viewer's role. Ticket, membership, dues and invitation actions appear together. +- A Switch club action appears when more than one club is accessible. The + single-club redirect and responsive club cards introduced previously remain. +- Membership, invitations, seasons, dues, payments and correction history follow + in order, using the existing permissions and bounded paging. +- Members see their own membership, dues and financial details. Administrative + forms remain restricted to administrators of that particular club. +- The Create club form is removed from the club summary. Super Administrators + retain a separate Create club page reached through their navigation. Club + administrators cannot access that page or its creation action. +- Existing club editing and archiving remain available on the club summary. +- Responsive table containers now contain their hidden accessibility labels, + preventing those labels from creating document-wide scrolling on phones while + preserving screen-reader names for the membership controls. + +## Signup + +- Public signup now asks for a new club name. A successful submission creates + the account, independent club, administrator membership and mandatory audit + entry in one transaction. Any failure rolls back all four. +- The account retains the global User role. Administration belongs to the new + club membership; posted roles and existing club IDs cannot promote the account + or attach it to another club. Reusing a club name creates a separate tenant. +- Email verification is required before the new owner can access or administer + the club. The existing MFA gate then requires authenticator enrollment before + administrator access. Membership creation does not verify the email. +- An invited-member signup link remains available, without a new-club field. + It requires a current invitation to the submitted email from an authorized + inviter. It creates only an account; email verification and explicit invitation + acceptance are still required before membership is granted. +- Invitation emails link directly to this member signup option. Existing users + continue signing in and accepting invitations as before. +- Existing signup rate limits, CSRF checks, password validation and uniqueness + protections remain in effect. Password fields are never repopulated on error. + +## Files and verification + +Application changes are in `classes/Roster.php`, `classes/AuthService.php`, +`classes/SignUp.php`, `classes/ClubInvitations.php`, `classes/Base.php`, +`xsl/content.xsl` and `xsl/createAccount.xsl`. No new database schema or migration +is required; the existing tenant, verification and MFA migrations must be present. + +New onboarding HTTP coverage checks transactional rollback, validation, duplicate +submission, isolation of identically named clubs, unverified access denial, +mandatory administrator MFA and invitation restrictions. Browser coverage checks +the summary header/actions, separate creation page, phone layout, new-club signup +and invited-member signup. Existing authentication and roster tests were updated +to exercise the corresponding signup and creation paths. These tests use only +disposable local databases and generated accounts; external email is disabled. +The existing MFA replay regression now reuses the exact code submitted during +confirmation, so crossing a 30-second boundary cannot make a fresh code look +like a failed replay test. Application MFA behavior was not changed in this work. + +Completed regression coverage passed 772 checks and 12 concurrency scenarios, +including 19 new onboarding HTTP checks and 18 tenant browser checks. Source +validation passed for 65 PHP files, 57 JavaScript files and 39 XSL stylesheets. + +The seven application files were deployed to ositsdevels and their hashes +verified. Live checks confirmed the new creation method, existing tenant schema, +new-club signup form and invited-member signup form. A protected temporary +runtime probe was removed after verification. Previous application files were +saved under `.tools/deployment-backups/club-summary-083cfeb77c414c7297fd269ebb7cefa4`. +No existing development database records were changed, no migration was run, +and no external test email was sent. Disposable test databases were removed and +the isolated local database server was stopped afterward. diff --git a/MAINTENANCE-REPAIRS.md b/MAINTENANCE-REPAIRS.md new file mode 100644 index 0000000..5474818 --- /dev/null +++ b/MAINTENANCE-REPAIRS.md @@ -0,0 +1,106 @@ +# Maintenance and backup repairs — October 20, 2026 + +This follow-up addresses the three code findings in +[the production review](PRODUCTION-REVIEW-2026-10-20.md). +No schema migration is needed. Tests use disposable local databases, not the +development or production database. Deployment and production-host acceptance +work in that review still applies. + +## Editor replacement + +- Removed the CKEditor 24 bundle and its references from all four alert/popover + add/edit forms. Replaced it with locally hosted **SunEditor 3.3.3**. +- Current CKEditor requires a commercial license key or GPL-compatible usage; + neither was established for this project. The review allowed a maintained + replacement. SunEditor uses the MIT license, included verbatim in + `THIRD-PARTY-NOTICES.md`. No commercial key or runtime CDN is required. +- Kept headings, bold, italic, underline, links, lists, font family/size/color, + indentation, alignment, horizontal rules, tables, undo and redo. Upload and + remote media tools are not enabled. +- Added the shared `js/rich-text.js` adapter. Save buttons stay disabled until + initialization completes. Initialization failure or timeout produces a visible + message. Saving copies editor HTML into the original form field; an empty + editor remains an empty optional field. +- Added versioned JavaScript/CSS, archive integrity and individual asset hashes + to `browser-dependencies.json`. Source checks verify the installed asset hashes + and removal of the old bundle. The release builder includes the replacement, + its license and dependency metadata. `Base::VERSION` changed to `1.01` to refresh + cached form scripts. +- Browser coverage exercises actual add/save/reopen/edit flows for both forms, + including legacy table markup, fonts, lists, links and text formatting; formatted + paste; filtering scripts, event attributes and unsafe links; failed asset + loading; and the existing content security policy. +- SunEditor 3 targets modern browsers (Chrome/Edge 119+, Firefox 125+, + Safari 17.2+). Unusual legacy HTML may be normalized by its content model; + arbitrary HTML is not promised to round-trip byte for byte. Existing server + output protections remain necessary; client filtering is not a server trust + boundary. + +Upstream sources: +[SunEditor release](https://github.com/JiHong88/suneditor/releases/tag/v3.3.3), +[installation and license](https://github.com/JiHong88/suneditor), +[CKEditor licensing](https://ckeditor.com/docs/ckeditor5/latest/getting-started/installation/self-hosted/quick-start.html). + +## Server-side maintenance validation + +- Added `classes/MaintenanceValidation.php`, shared by create and edit handlers + in `Alerts.php` and `Popovers.php`. +- Alert titles and popover names/titles are required and limited to 100 Unicode + characters. Optional popover placeholders allow 100 characters. Optional alert + messages and popover HTML allow 1,000 characters, matching existing columns. +- Rejects malformed text, null bytes, and control characters in single-line + fields. Required fields reject Unicode whitespace-only values. Limits count + characters rather than UTF-8 bytes. +- Alert dates and times must be present and use exact `YYYY-MM-DD` and `HH:MM` + formats. Rejects invalid calendar dates, impossible times, nonexistent local + daylight-saving times, years outside the database range, and expiration before + the start. Equal start/expiration remains allowed. +- Invalid requests return HTTP 422 with a specific error before any write. + Title-only alerts and popovers without optional body text remain supported. +- Alert/popover lookup, update and deletion IDs now use strict integer validation. + The popover uniqueness lookup still allows its create form's zero exclusion ID. +- Added direct HTTP tests that verify both rejection and unchanged table + fingerprints. Fixed the isolated test fixture connection to use UTF-8 so + Unicode assertions read the stored text correctly. + +## Backup memory usage and failure cleanup + +- Added `classes/BackupValidation.php`. Completion validation reads at most the + final **8 KiB** of the dump instead of loading the whole file into PHP memory. +- Requires the completion comment at the end, rejects missing/truncated dumps, + and accepts Windows or Unix line endings. Existing process exit-status, + streaming checksum, atomic completion and protected output handling remain. +- Moved temporary output/credential creation into the cleanup-protected block + and handles credential-file creation failure safely. +- Added a 64 MiB file test under a **16 MiB PHP memory limit**, including checksum + generation and measured peak-memory assertion. Additional tests cover missing, + tiny and incomplete files and a completion comment before unfinished data. +- Deployment tests exercise a real scratch-database dump and a failed dump + process, checking nonzero failure status and removal of temporary credentials, + partial output and success metadata. Release tests verify the new files. + +## Verification + +The full regression entry point is `tests/run.py`; it now includes the new +maintenance HTTP and bounded-memory backup suites. It also runs source validation, +authentication, authorization, club/ledger, concurrency, browser and deployment +checks. The complete run passed **374 checks plus five concurrency scenarios**: + +| Suite | Passed | +| --- | ---: | +| Authentication service/templates | 49 | +| Maintenance unit checks | 52 | +| Authentication HTTP | 27 | +| Project HTTP | 99 | +| New maintenance HTTP | 47 | +| Production security and ledger | 42 | +| Restricted database privileges | 5 | +| Browser flows | 28 | +| Backup validation | 9 | +| Deployment tools/release packaging | 16 | + +Source validation also passed for 44 PHP files, 56 JavaScript files and 39 XSL +stylesheets, including jQuery and SunEditor integrity checks. The isolated +loopback database server was stopped after the disposable databases were removed. +No development database records, real passwords, production services or email +recipients were changed by this work. diff --git a/MEMBER-ACTIONS-2026-10-21.md b/MEMBER-ACTIONS-2026-10-21.md new file mode 100644 index 0000000..0c92563 --- /dev/null +++ b/MEMBER-ACTIONS-2026-10-21.md @@ -0,0 +1,63 @@ +# Administrator actions on member summaries + +Administrators can now work directly from a member summary: + +- Edit membership opens a prefilled dialog for membership status and join date. + Super Administrators can also change the club role. Club administrators cannot + edit protected administrator memberships or grant administrator roles. +- Record season dues opens a dialog tied to the selected member. Seasons are + drawn only from the selected club, with bounded paging for longer season lists. + Inactive memberships do not receive an add-dues action. +- Record payment appears beside each season with an outstanding balance. The + dialog is tied to that dues record and membership and supports amount, received + date, payment method and reference. + +Dialogs identify the member, keep validation errors and entered values in place, +and use the existing cancellation and focus behavior. Successful saves return to +the same member summary, preserve its page selections, show a success notice and +refresh membership details and financial totals. All editing fields remain hidden +until an action is opened. Members retain their read-only summaries, and archived +clubs expose no write dialogs. + +## Security and implementation + +`MemberSummary.php` now handles an explicit allowlist of member, charge and +payment POST actions. It checks CSRF, club management permission, club status, +the selected membership and matching form identifiers before calling the existing +membership/ledger services. It returns a fixed local summary URL for successful +modal submissions; arbitrary return URLs are not accepted. + +`Base.php` applies the existing recent-MFA requirement to membership edits on the +new endpoint. Existing server-side role restrictions, last-administrator +safeguards, audit requirements, duplicate-dues checks, payment idempotency and +overpayment checks remain active. + +`LedgerService.php` accepts an optional membership constraint for payment writes. +The constraint is checked against the locked dues row inside the payment +transaction, before any write or idempotent success. A payment posted from one +member summary cannot target another member's dues, including within the same +club. Existing club-page callers retain their previous behavior. + +`ClubFormModals.php` recognizes the member-summary form action and renders the +existing labelled Bootstrap dialogs. No new JavaScript dependency, database +schema change or migration is required. + +Tests cover complete browser saves from all three dialogs, same-member redirects, +updated totals, privacy, CSRF, target tampering, audit rollback, archived clubs, +duplicate dues, foreign seasons, wrong-member payments, idempotency, overpayments, +administrator role restrictions and recent MFA. Test data is disposable and +external email is disabled. + +Completed validation passed 195 targeted checks: 22 new action HTTP checks, +22 member-summary HTTP checks, 26 tenant browser checks, 33 general browser +checks, 24 MFA/session HTTP checks, 41 security/capacity service checks, +11 paging/export HTTP checks and 16 deployment tooling checks. Source validation +passed for 67 PHP files, 58 JavaScript files and 39 XSL stylesheets. + +The four application files were deployed to development and their hashes +verified. A protected temporary probe confirmed the new summary forms, member +dialog rendering and membership-scoped payment API, then was removed. Prior +files were saved under +`.tools/deployment-backups/member-actions-7033d88c563c4b8ba6399f423cef1601`. +No existing development database records were changed. Disposable databases +were removed and the isolated local database server was stopped after testing. diff --git a/MEMBER-SUMMARY-2026-10-20.md b/MEMBER-SUMMARY-2026-10-20.md new file mode 100644 index 0000000..abc755f --- /dev/null +++ b/MEMBER-SUMMARY-2026-10-20.md @@ -0,0 +1,59 @@ +# Club member summaries + +Follow-up: administrators now have member-specific action dialogs. See +[member summary actions](MEMBER-ACTIONS-2026-10-21.md). Members still have +read-only access; the original summary implementation is described below. + +Roster names now link to a read-only summary for the selected club membership. +The page shows name, email, club, membership status and role, join date, total +dues, net payments and balance, followed by season dues, payment history and dues +correction history. Reversed payments remain visible with their reversal reason +but do not count toward payments received. Financial totals include every season +and remain unchanged when the user pages through individual history sections. + +Each history section has bounded paging. Paging links retain the selected club +and membership. Back to club roster preserves the roster page from which the +member was opened. Members with no financial records receive explicit empty +states; no administrator edit dialogs are exposed on the summary. + +Access is checked on the server for the exact club and membership pair: + +- Super System Administrators can view memberships in every club. +- Club administrators can view members only in clubs they administer. +- Ordinary members can view only their own active club membership. +- A person who administers one club but is an ordinary member of another has + ordinary-member permissions in that other club. +- Membership IDs cannot be paired with another club, and members of multiple + clubs receive separate financial histories for each membership. +- Existing authentication, MFA and email-verification requirements remain in + effect. Opening the summary does not write to membership or ledger records. + +Application files: + +- `classes/MemberSummary.php`: new read-only summary page and complete totals. +- `classes/Roster.php`: clickable names with club, membership and roster page. +- `classes/RosterService.php`: authorized single-membership lookup and an optional + membership filter for dues queries. +- `classes/LedgerService.php`: optional authorized membership filter for payment + and correction histories; existing callers retain their previous behavior. +- `classes/Base.php`: explicit authenticated route and GET allowlist entry. + +Tests cover corrected balances, reversed receipts, bounded and clamped paging, +safe text escaping, read-only requests, cross-club/member access, per-club roles, +MFA, clickable names, empty histories, phone layout and existing modal workflows. +The full test runner includes the new HTTP suite, and release packaging checks +require the new page class. No new dependency or database migration is required. + +Completed validation passed 245 targeted checks: 22 member-summary HTTP, +99 project HTTP, 23 tenant browser, 33 general browser, 16 deployment tooling, +41 security/capacity service and 11 paging/export HTTP checks. Source validation +passed for 67 PHP files, 58 JavaScript files and 39 XSL stylesheets. + +Five application files were deployed to development and their hashes verified. +A temporary protected runtime probe confirmed the page, membership lookup, +membership filters and existing tenant schema, then was removed. Previous files +were saved under +`.tools/deployment-backups/member-summary-700b9a0ae6b84b7e9a1cf1d77397ca64`. +No existing development database records were changed. Tests used disposable +local data with external email disabled; test databases were removed and the +isolated database server was stopped afterward. diff --git a/MFA-REPAIRS-2026-10-20.md b/MFA-REPAIRS-2026-10-20.md new file mode 100644 index 0000000..15fe61a --- /dev/null +++ b/MFA-REPAIRS-2026-10-20.md @@ -0,0 +1,70 @@ +# MFA lifecycle repairs — October 20, 2026 + +Repairs the two confirmed MFA findings in +[the readiness review](MULTI-TENANT-READINESS-2026-10-20.md). + +## Authenticator replacement + +Starting replacement requires the current password and an unused authenticator +or recovery code. The existing factor and all remaining recovery codes stay +active. A ten-minute replacement grant holds the new secret in the authorized +server-side session and binds it to the account version and existing factor. +The page offers a QR code, manual setup key and cancellation. + +Confirmation requires the password again and a valid code from the new device. +One transaction locks the account and factor, checks authorization, replaces the +encrypted secret, generates ten fresh recovery codes, increments the session +version and writes the mandatory audit entry. Other sessions and old recovery +codes are revoked only when this transaction commits. The confirmation code is +recorded as consumed so it cannot immediately be replayed. + +Cancellation, expiration, incorrect credentials and audit failure leave the +existing factor intact. Password resets preserve MFA and invalidate the pending +session. Competing confirmations cannot both succeed. Signing in clears any +previous pending replacement from that session. + +## Password and code verification + +MFA verification checks the current password, active account, session identity +and account version under the account lock before consuming an authenticator +time step or recovery code. Every mutation follows the account-then-factor lock +order, with consumption and mandatory audit committed together. Existing attempt +limits continue to apply. The verification API requires the password explicitly. + +## Security notifications + +Email notices use the account address read under the account lock. Events cover +initial enrollment, replacement requested, replacement completed and recovery +code use. Recovery-authorized replacement sends one combined request/recovery +notice. Notices identify the account and UTC time and explain what to do if the +activity was unauthorized. They contain no passwords, setup secrets, provisioning +links or recovery codes. + +Delivery uses the existing SMTP configuration after the security transaction +commits. Failed or rolled-back actions send no success notice. A delivery failure +does not undo the security change: it produces a visible warning and a log entry +containing the account ID and event type. Delivery is best effort, without a new +queue or automatic retry; production SMTP/inbox delivery and failure monitoring +still need deployment acceptance. + +## Validation and deployment + +New regressions cover 24 HTTP lifecycle assertions, 24 notification assertions +and two concurrent database races. Existing MFA capacity and QR scanning tests +were updated for explicit replacement confirmation and password-required +verification. The release packaging test requires the notification class. +All tests use disposable local databases and generated accounts; notification +tests capture messages or deliberately disable SMTP. No real account password, +MFA factor or recovery codes are changed, and no test email is sent externally. + +No database migration, encryption-key change or administrator re-enrollment is +required. Deploy `classes/MfaSecurityNotifications.php` before the updated +`MfaService.php`, `AuthService.php` and `Roster.php`. + +Completed validation: the full suite passed 743 checks and 12 concurrency +scenarios. Source validation passed for 65 PHP files, 57 JavaScript files and +39 XSL stylesheets. The four application files were deployed to ositsdevels and +their hashes verified. A temporary protected runtime check confirmed the +password-required verification API, replacement methods, notification class and +working server-side encryption key; the probe was removed immediately afterward. +No development database records were changed. diff --git a/MULTI-TENANCY.md b/MULTI-TENANCY.md new file mode 100644 index 0000000..9d9d14b --- /dev/null +++ b/MULTI-TENANCY.md @@ -0,0 +1,168 @@ +# Club tenancy and account access + +Implemented for the requested model. On October 20, 2026, the development +database was backed up and migrated, and `james.richie@onesourceits.com` was +promoted to **Super System Administrator**. Its existing password was preserved; +old sessions were revoked. See the +[development migration report](TENANT-MIGRATION-2026-10-20.md) for backup, +restoration and live verification results. + +## Access model + +| Capability | Super System Administrator | Club Administrator | User/member | +| --- | --- | --- | --- | +| View clubs | All | Assigned clubs | Active joined clubs | +| View member records | All | All members of managed clubs | Own membership only | +| Invite members | Any club | Managed clubs | No | +| Appoint club administrators | Yes | No | No | +| Create a new club | Yes | No | No | +| Edit/archive/reactivate club | Any club | Managed clubs | No | +| Seasons, dues, payments, corrections/reversals | Any club | Managed clubs | Read own dues/history only | +| Export roster/financial data | Any club | Managed clubs | No | +| Tickets | All clubs | All tickets in managed clubs | Submit/read/reply to own tickets | +| Global accounts, credentials, notes, settings, journal | Yes | No | No | + +An administrator assigned to two clubs can manage both. An administrator in one +club who is an ordinary member of another gets only member access in that other +club. Administrators sharing a club see the same membership and invitation data, +regardless of who issued the invitation. An account can belong to several clubs; +deactivating membership in one club leaves its global account and other club +memberships intact. + +Club administration is stored on `club_memberships.membership_role`, not inferred +from the old global `Administrator` or `System Administrator` label. Those old +labels do not confer cross-club access. The exact global +`Super System Administrator` role grants platform access. Only a current Super +System Administrator can assign global privileges or appoint club administrators. +The last active Super System Administrator and the last active administrator +membership in a club cannot be disabled/demoted through their respective controls. + +Members get club name/seasons and their own membership, dues, payment and +correction history. Other members' contact information and private tickets are +not shown to them. Site alerts, dropdowns, popovers and account notes remain +platform-wide features, editable only by the Super System Administrator; they +are not private club content editors. + +## Invitations + +Club administrators use **Invite to this club** within their club workspace, +instead of the global Users directory or a username/email lookup of existing +accounts. This prevents searching another tenant's accounts or changing shared +login credentials. Your Super System Administrator retains global user controls +and can directly assign an existing verified account when provisioning a club. + +An invitation records the club, submitted email, inviter, role and seven-day +expiration. It does not create an account, reset a password, or grant immediate +access. The recipient signs up or signs in using that email, verifies mailbox +ownership using the existing verification/reset process, opens **Invitations**, +and explicitly accepts. A verified, signed-in matching email is required; an +invitation ID alone is not a bearer credential. Consequently an invitation URL +does not need to contain a secret token. + +Invitations cannot be accepted by another account, after expiry/revocation, or +after the inviter loses authority. Acceptance and revocation serialize on the +club record. Repeated acceptance does not duplicate membership. Only the Super +System Administrator can issue administrator invitations. Deactivating an +existing membership revokes its outstanding invitations for that club. Sending +again requires a one-minute wait; per-actor/club limits also apply. + +Delivery uses the configured trusted HTTPS `ApplicationUrl`; the email explains +signup, verification and acceptance. Failed delivery leaves a visible warning +and a pending invitation that the recipient can find after signing in. An +administrator can retry sending to the same email after a minute. Development +email delivery is not claimed to work by these tests. + +## Tickets + +Members submit a subject and message from **Tickets** or **My tickets** inside +their club. Only the author, assigned club administrators and the Super System +Administrator can see that ticket or its messages. Members may reply to open +tickets; administrators can reply, close and reopen them. Archived clubs keep +their history but do not accept new tickets/replies. Subject/message limits are +200/8,000 Unicode characters. Text is escaped on display, requests require CSRF +protection, and submission/reply rates are limited. + +Tickets and replies commit with mandatory audit records. Successful submissions +redirect to a read page, so refreshing does not resubmit the form. Ticket lists use 25-item pages with subject search; count queries and every page +retain the same club/author restrictions. Older authorized tickets are discoverable +through page navigation or search. This feature supports text discussions, +not attachments or email notifications. + +## Migration and rollout + +Use a protected maintenance window for the coordinated code/schema change: + +1. Back up the target database and retain the matching application release. +2. Ensure migrations 001–003 are already applied and the designated existing + login `james.richie@onesourceits.com` is active. This migration does not create + an owner account or guess a replacement if that email is missing. +3. With migration credentials, set `HCR_SUPER_ADMIN_EMAIL` to + `james.richie@onesourceits.com` and run `php bin/migrate-tenants.php`. + Remove that environment variable afterward; it is a one-time explicit + bootstrap selection, not a runtime setting. +4. Deploy this version with all new files and the updated runtime grants in + `deploy/runtime-grants.sql.example`. Run `bin/check-health.php`. +5. Sign in again as the designated owner. Promotion revokes existing sessions and + outstanding reset/verification tokens. Club memberships are **not** promoted + automatically: open each club, assign its intended existing verified accounts + if needed, and set their **Club role** to **Administrator**. Alternatively, + invite an administrator and have them accept. +6. Verify each club administrator/member with separate sessions, then reopen + service. Test production inbox delivery separately. + +The migration adds `membership_role` and three InnoDB tables: +`club_invitations`, `club_tickets`, `club_ticket_messages`. Existing memberships +default to `member`; clubs without an explicit administrator remain visible and +manageable by the Super System Administrator. No historical financial records or +memberships are removed. Club display names no longer need to be globally unique; +club IDs remain the tenant boundary. Rerunning the migration is safe and does not +re-promote an already promoted account or repeatedly revoke sessions. + +Do not deploy the new application by itself against the old schema: health +checks will reject missing tenancy tables. If rollback is required after using +the new roles, restore the matching backed-up database and release together; +older code does not understand the new Super System Administrator role. + +## Implementation and verification + +- `TenantAccess.php` centralizes current database-backed platform/club permissions. + `Base.php` restricts global routes and passes the navigation capability to XSL. +- `RosterService.php`, `LedgerService.php` and `RosterReports.php` enforce the + selected club's access for reads, writes and downloads. Membership changes and + permission checks participate in club transactions. Account services enforce + Super System Administrator access and protect the final platform administrator. +- `ClubInvitations.php`, `ClubTickets.php` and the new Roster screens implement + the invitation and ticket flows. `xsl/content.xsl` shows scoped navigation. +- `migrations/004_tenants.sql`, `bin/migrate-tenants.php`, runtime grants, release + packaging, role options and application cache version (`1.02`) were updated. +- Added separate migration, service, HTTP and browser tenancy suites; expanded + concurrency coverage for invitation acceptance and the last club administrator. + Test fixtures use generated scratch databases, capture invitation mail or + force SMTP to a closed loopback port, and promote only a test account. + +Verification passed: **497 checks plus seven concurrency scenarios**, including +the complete prior regression suite and the final owner-assignment browser check. + +| Suite | Passed checks | +| --- | ---: | +| Existing authentication, maintenance, security, ledger, browser, backup and release suites | 374 | +| Tenant migration | 8 | +| Tenant services | 32 | +| Tenant HTTP access and isolation | 75 | +| Tenant browser workflows, including owner assignment | 8 | + +Source checks passed for 49 PHP files, 56 application JavaScript files and 39 XSL +stylesheets. Concurrency scenarios cover defaults, payment limits, financial +retries, the final platform administrator, invitation acceptance and the final +club administrator. The disposable local test databases were removed and their +loopback server stopped. No development records, real recipients or live account +privileges were changed. + +That regression run preceded the separately authorized development migration. +The subsequent migration and 61 development acceptance checks are documented in +the linked migration report; temporary verification data was removed afterward. + +See [the tenant repair follow-up](TENANT-REPAIRS-2026-10-20.md) for the invitation +reactivation policy, bounded transaction retries and Unicode-aware ticket forms. + +Mandatory administrator MFA and capacity controls require the [security/capacity migration and deployment steps](SECURITY-CAPACITY-2026-10-20.md). Apply them before running this release. diff --git a/MULTI-TENANT-READINESS-2026-10-20.md b/MULTI-TENANT-READINESS-2026-10-20.md new file mode 100644 index 0000000..979151c --- /dev/null +++ b/MULTI-TENANT-READINESS-2026-10-20.md @@ -0,0 +1,118 @@ +# Multi-tenant production readiness review — October 20, 2026 + +Follow-up: the two MFA defects below have been repaired. See +[MFA lifecycle repairs](MFA-REPAIRS-2026-10-20.md) for the implementation and +regression coverage. The findings below preserve the original review evidence. + +Reviewed the current authentication/MFA lifecycle, tenant permissions and routes, +invitations, roster/ledger paging and exports, shared budgets, deployment tooling +and dependency state. No application code, server configuration or development +database records were changed by this review. Reproductions used disposable +local databases and generated accounts, with external email disabled. + +## Confirmed defects, recommended repair order + +### 1. P1 — MFA replacement temporarily permits password-only factor takeover + +Location: `classes/MfaService.php:182`–`200`, particularly the deletion at +lines 188–191; enrollment checks at lines 107–141. + +After verifying the current password and an existing authenticator/recovery code, +replacement immediately deletes the current factor and all recovery codes. The +replacement authenticator has not yet been configured or proved. The account +therefore returns to the initial-enrollment path for any new password login. + +Reproduced through the real HTTP handlers with two independent cookie jars: + +1. A temporary Super System Administrator enrolls MFA normally. +2. Its legitimate session starts authenticator replacement with valid credentials. +3. Before replacement is confirmed, a separate session supplies only the account + password. It has neither the old authenticator nor an unused recovery code. +4. That session receives a new setup secret, enrolls its own authenticator and + successfully opens the Super System Administrator account-management page. + +This requires knowledge of the password and overlap with an authorized +replacement window. It does not bypass a stable enrolled factor outside that +window. Its impact is nevertheless platform-wide for the Super account. + +Fix: retain the existing factor while a replacement is pending. Bind replacement +authorization and the new secret to the authorized session and account version, +then atomically swap the factor, regenerate recovery codes and revoke other +sessions only after confirmation of the new authenticator. New password-only +sessions must continue to face the existing MFA challenge. Abandonment, expiry, +concurrent replacements and password resets must not reopen initial enrollment. + +### 2. P2 — Wrong password consumes a valid recovery code or authenticator step + +Location: `classes/MfaService.php:177`–`181`; consumption in `verify()` at +lines 80–105. + +The page computes `$passwordOk`, but invokes the mutating factor verifier before +testing that boolean. The verifier commits recovery-code deletion/counter +advancement and its audit before the page rejects the incorrect password. + +Reproduced: an account has ten recovery codes; submitting one with an incorrect +password returns HTTP 403 and leaves nine codes. Submitting that same recovery +code with the correct password also returns HTTP 403. The valid recovery code +has been lost despite the failed authentication. + +Fix: validate both credentials before committing factor consumption. Preserve +rate limiting for incorrect passwords as well as incorrect codes, and keep +consumption/auditing atomic. Verify rollback and concurrent use explicitly. + +## Security recommendation before public launch + +MFA enrollment, recovery use and replacement write audit records, but do not +notify the account owner through an independent channel. Add security notices +for factor changes/recovery, with visible or monitored delivery failures and +without putting secrets or recovery codes in email. This is a recommendation, +not another reproduced authorization bypass. It follows +[OWASP's factor-change notification guidance](https://cheatsheetseries.owasp.org/cheatsheets/Multifactor_Authentication_Cheat_Sheet.html). + +## Production acceptance and operations still required + +The previous development fixes are present: administrator MFA/QR setup, absolute +and idle timeouts, bounded lists/exports, and shared club budgets. The recent +server follow-up confirmed Apache key access and private-path denial on +ositsdevels. Development HTTP and its approved database connection are not new +production defects. + +Before public onboarding: + +- Preserve all required new/untracked classes, migrations, tests, assets and + dependency changes in a reviewed, versioned release; run CI on that exact + release. A current workspace build does not prove a clean checkout is complete. +- Run acceptance on the actual production HTTPS host: proxy trust, cookies and + headers, private paths, session/log permissions, and injected production secrets. + The development key-file override is deliberately unavailable in Production; + the production MFA key and a protected recovery copy must be provisioned. If + migrating existing enrolled accounts, preserve their key or perform an explicit + factor migration rather than silently changing it. +- Exercise complete tenant, MFA, invitation, reset and financial workflows with + the actual restricted production database account. Verify remote production + database TLS and separate migration/backup credentials. +- Verify real invitation, verification and reset inbox delivery, trusted links, + sender authentication and monitored delivery failures. +- Verify scheduled backups, cleanup and health checks, alert routing, log + rotation and storage monitoring. Test off-host restore of both SQL and MFA + key material. Document and exercise recovery of a single club without rolling + back unrelated clubs. +- Establish expected club sizes/concurrency and measure sustained workloads. + Bounded rows and request budgets improve resource control but do not establish + production throughput or response-time targets. + +These are requirements to verify on the selected production infrastructure, +not claims that externally configured jobs or controls are absent. + +## Evidence and limits + +- Both MFA findings reproduced against actual service/HTTP behavior using + independent sessions and disposable data. +- No additional cross-club authorization bypass was demonstrated in this review; + this does not replace a full penetration test or independent security review. +- `composer audit --locked` reported no security vulnerability advisories. +- Did not rerun the entire regression suite, load-test production, send real + email, or modify real accounts. Existing happy-path replacement tests do not + cover the competing password-only session reproduced here. +- Private reproduction helper: `.tools/review-mfa-replacement.py`. +- Removed the disposable databases and stopped their loopback server after review. diff --git a/MULTI-TENANT-REVIEW-2026-10-20.md b/MULTI-TENANT-REVIEW-2026-10-20.md new file mode 100644 index 0000000..f531868 --- /dev/null +++ b/MULTI-TENANT-REVIEW-2026-10-20.md @@ -0,0 +1,152 @@ +# Multi-tenant production review — October 20, 2026 + +Follow-up: the four confirmed defects below are addressed in +[tenant invitation and ticket repairs](TENANT-REPAIRS-2026-10-20.md). The findings +describe the reviewed version. Administrator MFA, session lifetime and capacity +recommendations are implemented in [the security/capacity follow-up](SECURITY-CAPACITY-2026-10-20.md). +Production acceptance recommendations remain applicable. + +The development tenant migration and owner promotion are complete. The earlier +61 development acceptance checks and the broader regression results remain +useful evidence, but they did not cover the edge cases reproduced below. +This review changed no application code or development database records. +Reproductions used generated disposable databases on a separate loopback server. + +## Confirmed defects, in recommended repair order + +### 1. P1 — Member invitation restores inactive administrator privileges + +Location: `classes/ClubInvitations.php:49`; related guard in +`classes/RosterService.php:62`. + +The invitation acceptance upsert always activates the membership and preserves +an existing `administrator` role. This conflicts with the rule that only the +Super System Administrator can reactivate/change administrator memberships. + +Reproduced: + +1. The Super System Administrator deactivates an administrator membership while + retaining its historical administrator role. A second administrator remains. +2. That other club administrator sends a normal **member** invitation to the + inactive administrator's email. No administrator invitation or Super approval + is involved. +3. The recipient accepts. The resulting membership is `active/administrator`, + and `TenantAccess::canManage()` returns true. + +This restores management rights within that club; the reproduction did not +grant platform-wide privileges or access to an unrelated club. It is still a +confirmed bypass of the chosen administrator-assignment policy. + +Fix: make reactivation/role assignment honor the newly authorized invitation +role. An inactive historical administrator must not regain administrative rights +through a member invitation. Require fresh Super approval for an administrator +grant, and test inactive, demoted, existing active and shared-account cases. + +### 2. P2 — Invitation acceptance and membership edits use opposite lock order + +Locations: `classes/ClubInvitations.php:42`–`43` and +`classes/RosterService.php:58`–`60`. + +Acceptance locks the club and then the user; membership editing locks the user +and then the club. Controlled concurrent execution of the actual service methods +reproduced a MariaDB deadlock (error **1213**): acceptance failed with a +`PDOException` while the membership update succeeded. The services roll back the +failed transaction, but do not retry it; the user receives an application error. + +Fix: establish a consistent lock order across invitation, membership and account +flows. Add bounded retry handling for retryable transaction failures, with the +authorization checks rerun inside the retried transaction. Extend concurrency +coverage to acceptance versus editing/revocation, rather than only two accepts. + +### 3. P2 — Ticket character limits conflict with the global byte limit + +Locations: `classes/Base.php:250`, `classes/ClubTickets.php:4` and `:18`/`:27`. + +Tickets advertise/validate an 8,000 Unicode-character message, but the dispatcher +rejects any individual value exceeding 8,192 bytes before ticket validation runs. +A valid 3,000-character message consisting of `界` occupies 9,000 UTF-8 bytes and +was rejected with **HTTP 400 / Invalid request** through the real HTTP handler. + +Fix: align field-specific character and byte limits and the HTTP form limits. +Retain request-shape and maximum-size protections; report field-specific errors +instead of rejecting supported text before the field validator can inspect it. +Cover both creation and replies with multibyte boundary tests. + +### 4. P2 — Tickets beyond the newest 100 cannot be found through the UI + +Locations: `classes/ClubTickets.php:8` and `classes/Roster.php::tickets()`. + +The service applies a hard `LIMIT 100`; the page offers no older-page navigation +or search. With 101 owned tickets, the list returned 100 and excluded the oldest. +The older ticket remains in storage and an authorized direct link still works, +but members/administrators cannot discover it through the ticket list. + +Fix: add stable server-side paging/search, keeping the club/author access filter +in every page and count query. Include tests for the second page, private-ticket +visibility and cross-club paging attempts. + +## Administrator security before public launch + +Authentication remains password-only (`classes/AuthService.php:37`), and sensitive +global account/role changes do not require recent authentication. The session +validator has an idle timeout, but no independently enforced absolute lifetime. +The Super System Administrator can access all tenants, so compromise of that +account has platform-wide impact. + +I recommend MFA for the Super System Administrator and club administrators, +recent authentication for privilege/email/security changes, a bounded absolute +session lifetime, and a tested recovery process. This is a security-hardening +recommendation, not a newly demonstrated login bypass. OWASP recommends MFA for +[administrative/high-privilege users](https://cheatsheetseries.owasp.org/cheatsheets/Multifactor_Authentication_Cheat_Sheet.html#quick-recommendations). + +## Shared-service capacity and recovery + +Roster members, dues, financial histories, invitation lists and several exports +still load whole collections with `fetchAll()`. Ticket messages are also unpaged. +Current invitation/ticket limits are chiefly per actor, not a total tenant budget. +No realistic large-club/load result was established by this review. + +Before general onboarding, establish expected club sizes and concurrent use, +measure expensive pages/exports, add bounded paging/streaming where needed, and +set tenant-level resource limits so one busy club cannot consume shared capacity. +This follows the resource-isolation concerns in +[OWASP's multi-tenant guidance](https://cheatsheetseries.owasp.org/cheatsheets/Multi_Tenant_Security_Cheat_Sheet.html). + +The full development backup was restored successfully during migration. A +production recovery plan should additionally explain how to recover one club's +records without rolling back unrelated clubs, and test that procedure. + +## Production acceptance work still required + +These are deployment checks, not assertions that external hosting configuration +is absent or that the approved development connection needs changing. + +- Preserve a reviewed release containing the currently untracked tenant classes, + migration, tests and assets; run CI on that exact release. +- On the actual production host, verify HTTPS/proxy trust, secure session storage, + headers/cookies, secret injection and private-directory denial. The local PHP + router is not evidence that Apache/IIS/Nginx deployment rules are active. +- Run complete tenant/invitation/ticket/financial flows using the actual restricted + runtime database account, with separate migration and backup credentials and + verified TLS for a remote production database. +- Verify real invitation, signup-verification and reset inbox delivery, trusted + links, sender-domain authentication and delivery-failure monitoring. Recent + development acceptance deliberately sent no external messages. +- Install/verify backup, retention, cleanup and health schedules, off-host + protected recovery copies, alert routing and log rotation. Exercise failure + alerts for SMTP, mandatory audit writes, backup jobs and storage exhaustion. +- Explicitly assign the intended club administrators before onboarding members. + Development currently has one existing club and no real memberships; the + security tests correctly used owned temporary assignments. + +## Review evidence and limits + +- Confirmed the privilege restoration, opposite-lock-order deadlock, Unicode HTTP + rejection and 101-ticket list truncation in disposable local databases. +- Current `composer audit --locked` returned no advisories or abandoned packages. + This does not cover all vendored browser assets or establish that hosting is safe. +- Did not rerun the full regression suite, load-test production, send real email, + or modify development records. The new edge cases need permanent regression + coverage with their fixes. +- Removed the disposable databases and stopped their separate loopback server + after the review. diff --git a/PRODUCTION-REVIEW-2026-10-20.md b/PRODUCTION-REVIEW-2026-10-20.md new file mode 100644 index 0000000..1be4139 --- /dev/null +++ b/PRODUCTION-REVIEW-2026-10-20.md @@ -0,0 +1,122 @@ +# Production readiness review — October 20, 2026 + +Follow-up: the three code findings below are addressed in +[maintenance and backup repairs](MAINTENANCE-REPAIRS.md). The findings describe +the state at review time; production-host acceptance work remains applicable. + +The production-safeguards migration is applied to development. Reset invalidation, +verified-email access, financial corrections/reversals, and transactional audit +records are already implemented. Their earlier findings are not being reopened. + +There are three remaining code fixes and production-host acceptance work. This +review changed no application code or development records. It used a disposable +database for focused validation checks, then removed it and stopped its server. +It did not rerun the complete regression suite or contact the future production +hostname. The current Composer audit reported no advisories or abandoned packages. + +## Code fixes, in recommended order + +### 1. Update the separate CKEditor dependency + +`js/ckeditor.js:5` contains the version constant `24.0.0`. This editor is loaded by +the alert and popover forms. It was not replaced by the jQuery update and is not +included in browser-dependencies.json or its integrity checks. + +The upstream advisory GHSA-3rh3-wfr4-76mj affects CKEditor packages through 26.0.0, +including engine, font, and list packages present in this build. It describes a +low-severity regular-expression denial of service that can freeze a browser tab. +This review did not demonstrate an application exploit or establish that every +newer advisory applies to this build. + +Fix: rebuild/replace the editor with an appropriately licensed, patched version +or use a simpler maintained editor. Record all bundled browser libraries and +their provenance, extend advisory/integrity checks, and test paste, save, edit, +formatting, and CSP behavior. Passing editor-initialization tests alone does not +establish security coverage. + +Primary source: +https://github.com/ckeditor/ckeditor5/security/advisories/GHSA-3rh3-wfr4-76mj + +### 2. Finish server validation for older maintenance forms + +`classes/Alerts.php:70–80` accepts title/message fields directly and converts +dates with strtotime without validating the ordering. The edit path at lines +163–174 repeats this pattern. Browser JavaScript checks some of these values, +but a direct authenticated request bypasses those checks. + +Confirmed in a disposable database: posting a blank alert title and an expiration +before its start returned HTTP 200 and persisted both invalid values. + +`classes/Popovers.php:52–56` and its edit path also lack equivalent server-side +required-field validation. Posting a blank popover name/title returned HTTP 200 +and stored the blank name. + +Fix: centralize required fields, length limits, strict date/time parsing and date +ordering for create/edit operations. Return field-specific validation errors and +test direct HTTP submissions. These routes require an administrator; this is a +data-integrity gap, not a demonstrated unauthenticated write vulnerability. + +### 3. Make backup completion checking bounded in memory + +`bin/backup-database.php:23` uses file_get_contents on the entire SQL dump merely +to locate the completion marker. Memory use grows with the database backup size. +Under a configured memory limit, a valid large dump can therefore cause the +backup job to fail during validation. Current tests exercise a small database. + +Fix: inspect a bounded tail of the dump or stream it, retaining the existing +exit-code and checksum checks. Test large-file behavior and failed/interrupted +jobs, including temporary credential/partial-file cleanup and scheduler alerts. +The resource concern was identified from source; a large-file failure was not +reproduced during this review. + +## Production acceptance work still required + +These are checks on the selected production environment, not evidence of a public +leak or an instruction to change the approved development connection. + +1. **Complete and preserve the release.** Essential new classes, migrations, + browser assets, deployment files, and the CI workflow are still untracked in + the working tree. Include them in the reviewed source-control release; a + GitHub checkout cannot run files that have not been committed. Run CI on the + actual repository and retain a versioned release and recovery plan. +2. **Validate the actual hosting configuration.** Configure production secrets, + HTTPS/proxy trust, secure cookies/headers, protected sessions/logs, and private + directory denial. Run the production check script against the real HTTPS + deployment when it exists. Apache/IIS/Nginx examples have not been exercised + on the selected production host. +3. **Verify production database transport and privileges.** Use verified TLS for + a remote production database and separate runtime/migration/backup roles. + Run complete workflows using the actual restricted runtime account, rather + than validating only connectivity or individual denied operations. The + development non-TLS approval does not establish this production configuration. +4. **Test real email delivery.** The most recent development acceptance run + captured links locally. Send actual verification, invitation, and reset emails + from production, confirm inbox delivery and links, and configure sender-domain + authentication and delivery-failure monitoring. Generated URLs and a prior + SMTP acceptance result do not prove the final inbox experience. +5. **Install operational jobs and alerts.** Backup/cleanup/health entry points + exist, but the repository does not prove their production schedules or alert + routing. Configure protected encrypted off-host backups, retention, restore + drills, log rotation, and monitoring for failed jobs, audit writes, SMTP, + database health, and disk space. Verify any existing external setup rather + than assuming it is absent. +6. **Test realistic volumes.** Roster, dues, history, and export code loads whole + collections. Test the expected club sizes and concurrent use. Introduce paging, + streaming, or background exports where measured limits require them; small + workflow tests do not establish large-club performance. + +## Recommendations and product scope + +- MFA and recent-password confirmation for sensitive administrator actions remain + recommended protections. They are not implemented, and this review does not + represent them as newly discovered authorization bypasses. +- Global administrators still manage all clubs. Delegated club administrators + are needed only if clubs will administer themselves. +- Active members still see fellow club members' email addresses. Confirm that + directory policy before onboarding real members. +- Online payment collection/refunds are outside the current manual-ledger scope; + their absence is not a defect in recording received payments and reversals. + +Recommended next step: address the three code items, then complete one documented +production acceptance run. Additional features should be driven by the intended +operating model rather than treated as automatic launch blockers. diff --git a/README.md b/README.md index 8a0ec18..f0e04eb 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,20 @@ # Hunting Club Roster +See [member summary actions](MEMBER-ACTIONS-2026-10-21.md) for administrator +membership edits, dues and payment dialogs directly on a member summary. + +See [member summaries](MEMBER-SUMMARY-2026-10-20.md) for clickable roster names, +membership details and member-specific financial history. + +See [club action modals](CLUB-MODALS-2026-10-20.md) for the cleaner summary page +and add/edit dialogs. + +See [club summary and signup changes](CLUB-UI-AND-SIGNUP-2026-10-20.md) for the +club page layout, separate club creation page and new administrator signup flow. + +See [MFA lifecycle repairs](MFA-REPAIRS-2026-10-20.md) for secure authenticator +replacement, password-before-code verification, security notices and tests. + See [authentication setup and changes](AUTHENTICATION.md) before deploying the updated login, signup, and password reset flows. The authentication migration must be applied to the existing database before using this version. @@ -9,3 +24,14 @@ fixes, new roster migration, feature scope, and verification results. See [production safeguard changes](PRODUCTION-FIXES.md) for the newest migration, verified-email requirement, ledger corrections, and deployment instructions. + +See [maintenance and backup repairs](MAINTENANCE-REPAIRS.md) for the editor +replacement, server validation, bounded-memory backups, and regression coverage. + +See [club tenancy and account access](MULTI-TENANCY.md) before deploying the +tenant migration, Super System Administrator role, club invitations and tickets. + +See [tenant invitation and ticket repairs](TENANT-REPAIRS-2026-10-20.md) for the +invitation-role fix, transaction retries, Unicode limits, ticket paging and tests. + +See [administrator security and capacity](SECURITY-CAPACITY-2026-10-20.md) for mandatory MFA, session expiration, bounded collections, shared club budgets, and the required new migration/key configuration. diff --git a/SECURITY-CAPACITY-2026-10-20.md b/SECURITY-CAPACITY-2026-10-20.md new file mode 100644 index 0000000..4eeffaf --- /dev/null +++ b/SECURITY-CAPACITY-2026-10-20.md @@ -0,0 +1,152 @@ +# Administrator security and shared capacity — October 20, 2026 + +Implements the first four remaining multi-tenant review recommendations. All +database verification uses disposable local databases. This work does not migrate +the development database or enroll any real account's authenticator. + +## 1. Administrator MFA and recent authentication + +- Added maintained `spomky-labs/otphp` 11.5.0 and its locked dependencies. +- Every authenticated request passes an MFA gate before application dispatch. + Super System Administrators and active club administrators must enroll and + complete MFA; an ordinary global User role does not bypass a club administrator + membership. Enrolled ordinary members must also complete their chosen MFA. +- Existing password login establishes the first factor only. Direct URLs and + AJAX requests cannot use administrator functionality before the gate completes. +- Setup requires the current password and a working authenticator code. The + setup page offers a locally generated QR code and a manual key for authenticator + apps using SHA-1, six digits and 30-second periods. The QR uses the same pending + secret, the application issuer and account email. A white quiet zone preserves + scan contrast on dark pages. Pending setup expires after ten minutes. No + third-party QR service receives the secret, and QR images are not saved to disk. +- Secrets use AES-256-GCM with a random nonce and account ID as authenticated + data. `HCR_MFA_KEY` is a separate, required 32-byte encryption key, encoded as + base64. Database records do not contain plaintext secrets. +- Verifies the current or adjacent time step, rejecting counters already used. + Verification locks the factor row. Ten random 128-bit recovery codes are + displayed once; only SHA-256 hashes are stored. Consumption and mandatory audit + commit together. Failed audit writes roll back consumption. +- Limits authentication attempts per account and IP. Successful MFA rotates the + session ID and CSRF token. Password login clears earlier MFA verification; + password resets preserve the factor and its replay counter. +- Account security is linked from the home page. Lost authenticator replacement + requires the password and an unused recovery/current authenticator code. It + retains the existing factor while the authorized session configures a new one. + Confirmation atomically replaces the factor, refreshes recovery codes and + revokes other sessions. See [MFA repairs](MFA-REPAIRS-2026-10-20.md). +- Global account/security changes and membership role/status changes require + password plus MFA confirmation within five minutes. The original write is + never replayed automatically after authentication; the user submits it again. +- MFA enrollment/replacement invalidates other account sessions. Session versions + are captured under lock, avoiding adoption of a concurrent password-reset + version. Recovery does not use email-only factor removal. + +## 2. Absolute session lifetime + +- `AuthService` records an authentication start timestamp at password login and + enforces an eight-hour maximum lifetime independently of the existing + 30-minute idle timeout. +- Activity, MFA and recent-authentication confirmation do not extend that start + time. Legacy sessions without a start timestamp must sign in again. + +## 3. Bounded collections and exports + +- Added shared count/paging support using the same authorized SQL for both. +- Club navigation, roster members, seasons, dues, payment histories, corrections, + administrator invitation lists, pending invitations and ticket messages now + have independent 25-record pages with first/previous/next/last controls. +- Page numbers are validated and clamped. Links preserve the selected club and + other page/filter context. Personal member visibility applies to counts as + well as rows. Older records remain accessible through the pager. +- Dues-entry member/season selectors use their corresponding displayed pages; + navigate those pages to choose older seasons or additional members. +- Added a read-only, authorized report-catalog route for page navigation. Its + club list counts only clubs the administrator can manage. +- Roster CSV/Excel/PDF and financial CSV exports reject oversized collections + before loading them, with a default 1,000-row limit. Queries retain a second + hard bound so concurrent growth cannot create unbounded allocations. + `HCR_EXPORT_MAX_ROWS` accepts 1–5,000. Oversized exports return a clear error, + never a silently truncated file; a large-export workflow is not added here. + +## 4. Shared club resource budgets + +Each club has independent hourly counters for: + +| Resource | Default per hour | Configuration | +|---|---:|---| +| Invitation email attempts | 100 | `HCR_CLUB_EMAIL_HOURLY` | +| New tickets | 100 | `HCR_CLUB_TICKET_HOURLY` | +| Ticket replies | 1,000 | `HCR_CLUB_REPLY_HOURLY` | +| Exports, across all formats | 20 | `HCR_CLUB_EXPORT_HOURLY` | + +- Configured budgets accept 1–100,000; invalid configuration fails closed. +- Existing individual rate limits remain. Changing users or formats does not + reset the club counter. Another club has a separate budget. +- Atomic database increments return each connection's own assigned slot, so + simultaneous requests cannot exceed the configured budget. +- Permission checks precede consumption. Budgets count authorized attempts, + including failed delivery or later validation; they are deliberately not + refunded by transaction retries or failed writes. +- Counters occupy one row per club/resource and reset on the next attempt after + an hour, so request history does not grow without a bound. + +## Deployment steps + +1. Preserve a backup, then run `bin/migrate-security-capacity.php` with migration + credentials after the existing migrations. It adds `user_mfa`, `mfa_recovery` + and `club_resource_usage`; rerunning it preserves existing data. +2. Inject a unique random `HCR_MFA_KEY` through the application's secret store. + Generate 32 cryptographically random bytes and base64-encode them. Never use + the disposable test key. Keep a protected recovery copy separate from SQL + backups; changing or losing the key prevents decrypting existing factors. + Development can instead set `MfaKeyFile` in its private local settings to a + protected file outside the application directory. An explicit environment key + takes precedence. Production does not allow this development fallback. +3. Apply the new table grants in `deploy/runtime-grants.sql.example` to the + restricted runtime account. The health check now verifies these tables and, + in Production, the MFA key format. +4. Deploy the complete locked dependencies and updated source together. The + release builder includes the migration and new classes. Application version + is now 1.04. +5. Administrators sign in and enroll their own authenticator, saving their + recovery codes offline. Keep server clocks synchronized. If both the device + and all recovery codes are lost, recovery requires a trusted operator to + verify identity and perform an audited database recovery; there is no public + email-only bypass. + +Production host acceptance, sender-domain/inbox checks, off-host recovery and +realistic sustained load testing remain separate deployment work. These changes +do not establish production hosting readiness by themselves. + +## Verification + +Regression verification covers **675 checks and ten concurrency scenarios**: + +- Existing 584 authentication, maintenance, tenant isolation, financial, + browser, backup and deployment checks, plus nine existing concurrency races. +- 24 HTTP MFA/session checks, 41 service checks, 11 large-list/export HTTP checks + and 15 shared-budget HTTP checks. +- Twelve simultaneous requests from two administrators compete for five export + slots: exactly five succeed and seven receive the limit response. +- MFA checks include valid code verification, counter replay rejection, + single-use recovery, audit-failure rollback, account-bound encryption, + password-reset factor preservation, lost-device replacement, recent + authentication, promotion-triggered enrollment and both session timeouts. +- Source validation covers 60 PHP files, 57 application JavaScript files and + 39 XSL stylesheets, plus bundled browser dependency integrity. Composer + installation reported no security advisories for the locked dependencies. + +The existing regression suites and all new suites passed across the full run +and targeted follow-up runs. Test databases are disposable and no real email +is sent. The isolated local database server was stopped after verification. + +The later [development migration and acceptance run](SECURITY-MIGRATION-2026-10-20.md) +verified the persistent key-file configuration with eight additional regression +checks and 68 acceptance checks against the backed-up development database. + +The subsequent QR setup change passed ten browser checks using an independent +decoder, 24 existing MFA/security HTTP checks and 16 deployment checks. Browser +coverage includes scanning, enrollment using the scanned secret, phone-width +layout, stable pending setup details, replacement and absence of external QR +requests. QR rendering was also verified on ositsdevels without changing a real +account. No new application dependency or database migration was required. diff --git a/SECURITY-MIGRATION-2026-10-20.md b/SECURITY-MIGRATION-2026-10-20.md new file mode 100644 index 0000000..2e8d160 --- /dev/null +++ b/SECURITY-MIGRATION-2026-10-20.md @@ -0,0 +1,102 @@ +# Development security/capacity migration — October 20, 2026 + +Completed against the approved development target, +`192.168.1.190/huntingclubroster`, using its previously approved non-TLS connection. + +## Backup and migration + +- Backup: `.tools/backups/20261020-190128/huntingclubroster.sql`. +- Size: 53,033 bytes; 23 existing tables. +- SHA-256: `e7301cc5429f57bf93e9f1627b6c77afc9d8678ea0757a56a445e597417e0570`. +- Verified the completion marker and checksum, restored the backup to an + isolated loopback database, and matched all 23 table row counts. +- Applied `bin/migrate-security-capacity.php` and reran it to confirm repeatability. + The database now has 26 tables, including `user_mfa`, `mfa_recovery` and + `club_resource_usage`. +- Compared every original table's row fingerprints before and after migration; + existing values were preserved. + +## Persistent development MFA key + +- Generated a cryptographically random 32-byte key outside the project, in + `C:\Users\JamesRichie\AppData\Local\HuntingClubRoster\secrets\development-mfa.key`. +- Configured its path in ignored `xml/settings.local.xml`. Development servers + can read this persistent key without inheriting a temporary shell variable. + No key value is stored in the repository or this report. +- The key has protected Windows permissions allowing only the current Windows + account and SYSTEM. A protected recovery copy was saved under the same + external secrets folder's `recovery` subdirectory. This is a local recovery + copy, not an off-host backup. +- Added a development-only key-file loader. It rejects missing, oversized, + malformed and in-project key files. Production continues to require its + explicitly injected environment key. +- Eight key-configuration regression checks passed and are included in the test + runner. + +## Development acceptance + +All **68 development acceptance checks passed**, using owned temporary clubs, +accounts and records: + +- Super System Administrator and club administrator authenticator enrollment; + administrator URLs and AJAX denied before MFA; valid authenticator acceptance; + encrypted secrets; recovery-code consumption and rejection of reused codes. +- Password login still requires the enrolled factor. Ordinary members keep their + normal login flow. Sensitive changes require recent password/MFA confirmation. +- Independent eight-hour absolute and 30-minute idle session expiration, tested + by aging only private test sessions rather than changing server time or waiting. +- Last-page access for members, seasons, dues, payments, corrections and + invitations; paged ticket conversations; invalid page handling; personal + counts and cross-club access denial. +- Shared ticket, reply, invitation email and export budgets across different + users, independent budgets for another club, and hourly-window reset. +- Oversized CSV, Excel, PDF and financial exports rejected without truncation. + +The verification servers temporarily used lower limits to exercise boundaries; +normal development defaults were not changed. SMTP was redirected to an unused +loopback port, so no real email was sent. The MFA key was loaded from the actual +protected development key file, not a disposable test key. + +All temporary accounts, factors, recovery codes, clubs, ledger rows, tickets, +audits, counters and private sessions were removed. Row fingerprints for all +26 tables then matched their pre-test state. Real account passwords, roles, +email verification and MFA enrollment were unchanged. + +Detailed private evidence is retained beside the backup in +`security-migration-result.json`, `security-acceptance-result.json` and +`security-cleanup-result.json`. + +The final development health check passed. Source validation passed for 61 PHP +files, 57 application JavaScript files and 39 XSL stylesheets, including browser +dependency integrity. The local backup-restoration copy was removed and its +isolated database server stopped. + +The existing Super System Administrator will be prompted to enroll an +authenticator at the next sign-in; its owner must save the recovery codes. +No real account was enrolled on the owner's behalf. + +## Actual development web-server follow-up + +The browser application runs on `ositsdevels` under Rocky Linux Apache/PHP-FPM, +not on the Windows workstation used for the original acceptance server. Its +copied Windows key path caused login to fail before displaying MFA setup. + +The owner ran the prepared administrator installer on that server. It installed +the unchanged key at `/etc/httpd/huntingclubroster/development-mfa.key`, restricted +its permissions to root and the Apache group, restored its SELinux context, and +configured the application's FastCGI requests with `HCR_MFA_KEY_FILE`. This +development-only override prevents workstation settings from replacing the +server's key path. Nine key-configuration regression checks passed. + +The installer also enabled the app's existing private-directory rules, validated +Apache configuration and reloaded Apache. Its staged key was outside the web +root in the server home directory and was removed after installation. + +Verified through the actual Apache/PHP-FPM server after installation: + +- Configured MFA key is readable and can encrypt a secret. +- Authenticator library can generate and verify a code entirely in memory. +- Login page returns HTTP 200. +- `.tools/`, local settings, classes and vendor endpoints return HTTP 403. +- The staged key is removed. All temporary token-protected diagnostics were + immediately removed, and no real account was enrolled or changed. diff --git a/TENANT-MIGRATION-2026-10-20.md b/TENANT-MIGRATION-2026-10-20.md new file mode 100644 index 0000000..afa3d14 --- /dev/null +++ b/TENANT-MIGRATION-2026-10-20.md @@ -0,0 +1,87 @@ +# Development tenant migration — October 20, 2026 + +Completed against the authorized development target +`192.168.1.190/huntingclubroster`, using the previously approved unencrypted +development connection. No production service was changed. + +## Backup and restoration + +- Backup: `.tools/backups/20261020-173710/huntingclubroster.sql`. +- Full dump with routines, events, triggers, 20 existing tables and a completion + footer; size **48,133 bytes**. Temporary connection credentials were removed. +- SHA-256: + `4107de994758039a107ee449120463d3f2b21d8a7da705355fa940d6bf834ed8`. +- Restored on the separate loopback test database server before migration; + all 20 table row counts matched the backup manifest. The local restoration + copy was subsequently removed and that server stopped. +- Backup validation uses the bounded-tail validator. Backup files remain in the + ignored, web-denied `.tools` directory; the verification confirmed that the + private control file was inaccessible over HTTP. + +## Migration and owner promotion + +- Applied `bin/migrate-tenants.php` and `migrations/004_tenants.sql`. +- Added `membership_role` and the invitations, tickets and ticket-message tables; + replaced the global unique club-name index with a normal index. +- Explicitly promoted **james.richie@onesourceits.com** to + **Super System Administrator**. +- Preserved its existing password and email-verification state. Incremented the + authentication version to revoke old sessions, invalidated the designated + account's outstanding reset/verification tokens, and added one promotion audit + entry. The one-time promotion environment variable was removed afterward. +- Compared all original tables and original-column values, allowing only those + intended owner changes and the new audit entry. Original clubs, other accounts, + memberships and financial data were preserved. +- No existing club-administrator assignments were guessed. The existing club + had no memberships before the migration and still has none; it is available + to the Super System Administrator for explicit setup. + +## Verification on the migrated development database + +**61 checks passed** using real HTTP handlers on a temporary loopback web server +connected to the development database. Separate cookie/session clients signed +in with seven randomly generated temporary accounts across two owned test clubs. +No real account password was requested or changed, and no external email was sent. + +Verified: + +- Club administrators see all members/invitations of their shared club and cannot + view or modify another tenant through changed URLs, IDs or direct submissions. +- Global user searches, account edits/deletion, password-reset requests, notes and + the journal are denied to club administrators, including attempts against the + real owner account. +- Roster and financial exports are restricted to managed clubs, including CSV, + Excel, PDF and financial-history endpoints. Downloads contain only that club's + member data. +- An administrator in one club who is an ordinary member of another gets only + ordinary member access in the second club. +- Members see their own membership and dues, cannot see other members' contact + details, and cannot record payments or access an unassigned club. +- A foreign dues ID cannot be paired with an authorized club. Recording a valid + payment updates only the intended member's balance. +- Administrator invitations cannot be forged; matching verified accounts can + accept member invitations, and other accounts cannot steal them by ID. +- Members can submit and read their own private tickets; other members and other + tenants cannot read them. Assigned administrators can respond and close tickets. + Ticket text is escaped when displayed. +- Revoking a club administrator assignment removes management privileges on the + next request in the existing session. +- Private verification credentials cannot be downloaded through the web server. + +Afterward, removed only the owned temporary clubs, accounts, memberships, dues, +payment, invitation, ticket/messages, tagged audit entries and exact test rate +limit records. Fingerprints across **all 23 tables** matched the post-migration, +pre-test baseline before cleanup committed. The owner promotion and its audit +record remain intact. + +Final health check passed. The development database contains its original +**2 users, 1 club and 0 memberships**. The promoted owner can see the existing +club. Temporary sessions and web server were removed/stopped. + +Protected evidence is retained beside the backup: +`manifest.json`, `pre-tenant-snapshot.json`, `tenant-migration-result.json`, +`tenant-acceptance-result.json`, `tenant-cleanup-result.json`, and +`tenant-final-state.json`. The HTTP log is retained there as well. + +Sign in again using the owner's existing credentials, then assign the intended +club administrators explicitly as described in [MULTI-TENANCY.md](MULTI-TENANCY.md). diff --git a/TENANT-REPAIRS-2026-10-20.md b/TENANT-REPAIRS-2026-10-20.md new file mode 100644 index 0000000..4936e73 --- /dev/null +++ b/TENANT-REPAIRS-2026-10-20.md @@ -0,0 +1,122 @@ +# Tenant invitation and ticket repairs — October 20, 2026 + +Addresses the four confirmed defects in +[the multi-tenant production review](MULTI-TENANT-REVIEW-2026-10-20.md), in its +recommended order. No schema migration or development database change is needed. +All verification uses generated disposable local databases; no real email is sent. + +## 1. Administrator invitation bypass + +`ClubInvitations::accept()` now distinguishes existing **active** administrator +memberships from inactive historical roles. A member invitation can reactivate an +inactive membership only as a member; it cannot restore the historical +administrator role. A fresh administrator invitation still requires a current +Super System Administrator grant. Already active administrators keep their role +when accepting a member invitation, preventing accidental loss of the last club +administrator. + +`RosterService::saveMember()` revokes outstanding invitations when the membership +role changes as well as when membership is made inactive. An earlier administrator +invitation therefore cannot undo a later explicit demotion. These changes are +scoped to the selected membership and do not change a shared account's other clubs. + +Regression cases cover rejoining as a member, Super-approved restoration, +preserving active administrators, invitation invalidation on promotion/demotion +or deactivation, and unaffected access to another club. + +## 2. Concurrent transactions + +Invitation acceptance now locks the recipient user before the club, matching +membership updates and account operations that lock user records first. + +New `classes/DatabaseTransaction.php` provides up to **three complete transaction +attempts** for database deadlocks, serialization failures and lock-wait timeouts. +Every failed attempt rolls back before a short randomized backoff and retry. +Other database errors and business/permission errors are propagated immediately. +Exhausted retries propagate the failure after rollback; retries are bounded. + +Applied the helper to: + +- Invitation creation, acceptance and revocation. +- Club creation/updates, membership updates and season creation. +- Ledger charges, payments, corrections and reversals. +- Global account edits, activation/deactivation and deletion. +- Ticket creation and replies. + +Permission checks inside the transaction rerun on retry. Administrator invitation +issuance also rechecks Super privilege inside each attempt. Email delivery and +rate-limit accounting remain outside the retry closure, so retrying database work +does not repeat those external effects. Mandatory audits commit with their writes. + +Tests inject retryable failures after database writes, verify exactly one +committed write, cover exhausted attempts and nonretryable permission failures, +and revoke authority between attempts to confirm the retry cannot commit. +Controlled concurrent real service calls cover acceptance versus activation and +acceptance versus deactivation. Existing financial and final-administrator races +remain part of the full suite. + +## 3. Unicode ticket validation + +- Ticket subjects and bodies use server-owned limits of **200** and **8,000** + Unicode characters, with specific required/invalid/over-limit errors. +- The dispatcher permits larger message transport only for POST ticket creation + and reply actions. That field retains a hard **65,536-byte** ceiling; all other + fields retain the existing 8,192-byte ceiling. The field validator then enforces + the actual 8,000-character limit before storage. +- Query and form values are checked separately. A valid POST value cannot hide an + array-shaped query value with the same name. +- Added `js/tickets.js`, which validates Unicode code-point length rather than + JavaScript UTF-16 units. HTML maxlength permits the required two UTF-16 units + per character; client validation and server validation enforce the character + limit. The same handling applies to subjects, replies and ticket search. +- HTTP tests preserve 3,000 CJK characters and 8,000 four-byte emoji without + truncation, reject 8,001-character messages/replies without partial writes, + and verify malformed/extreme requests still fail. Browser tests cover native + controls, meaningful validation messages and full Unicode submission. + +## 4. Ticket pages and search + +- Replaced the newest-100-only list with **25-ticket pages**, newest serial first, + and first/previous/next/last navigation. +- Added subject search with a 100-character limit. Search treats SQL wildcard + characters `%`, `_` and `!` literally and uses bound parameters. +- Both the count and row query apply the club and author/administrator scope. + Members see only their personal results/counts; club administrators see only + their managed club's tickets. Direct ticket access retains its own permission + check. +- Validates page numbers, clamps requests beyond the last page, escapes subjects + and search text, and provides clear no-match and page-count displays. +- Opening a ticket preserves list context. Reply redirects retain page/search + state; a newly created ticket returns to an unfiltered first page. Successful + submissions still redirect to GET, avoiding resubmission on refresh. +- Tests use 102 personal tickets, a private ticket from another member and a ticket + in another club. They verify complete nonduplicated traversal, old-ticket search, + literal wildcard handling, escaped HTML, private counts, malformed/tampered + requests, old-ticket replies and the browser navigation controls. + +## Other changed files + +`Base::VERSION` is now `1.03` for browser cache refresh. Updated `tests/run.py` +to include all new repair suites, test fixtures/workers to create owned data and +control concurrency, and release-package tests to require the new transaction +helper and browser script. Updated the tenancy documentation and linked the +review to this follow-up. New classes/scripts are automatically included by the +existing release builder. + +## Verification results + +The complete regression suite passed: **584 checks and nine concurrency +scenarios**, including the existing authentication, tenant isolation, financial, +backup and deployment checks. New coverage includes nine invitation checks, +eight transaction retry checks, 18 Unicode HTTP checks, 44 ticket paging HTTP +checks and eight ticket browser checks. The nine concurrency scenarios include +two new invitation/membership races. + +Source validation passed for 53 PHP files, 57 application JavaScript files and +39 XSL files, along with bundled editor and jQuery integrity checks. Tests used +disposable databases on the isolated local server; no development database +migration or development data changes were needed. + +The remaining MFA, +capacity and production-host acceptance work in the review is outside these four +repairs; these changes do not assert that production hosting has been validated. diff --git a/THIRD-PARTY-NOTICES.md b/THIRD-PARTY-NOTICES.md new file mode 100644 index 0000000..97b6602 --- /dev/null +++ b/THIRD-PARTY-NOTICES.md @@ -0,0 +1,29 @@ +# SunEditor 3.3.3 + +Source: https://github.com/JiHong88/suneditor/releases/tag/v3.3.3 + +MIT License + +Copyright (c) 2017-2025 Yi JiHong + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +## OTPHP and MFA dependencies + +Authenticator codes use spomky-labs/otphp 11.5.0 (MIT). Locked supporting packages include paragonie/constant_time_encoding (MIT), psr/clock (MIT), and symfony/deprecation-contracts (MIT). Their license texts are included in the corresponding vendor directories and the release archive. diff --git a/bin/backup-database.php b/bin/backup-database.php index ab39689..33f7c30 100644 --- a/bin/backup-database.php +++ b/bin/backup-database.php @@ -8,21 +8,22 @@ $base=new Base();$settings=$base->getSettings();$db=$base->connect(); $engines=$db->query("SELECT ENGINE FROM information_schema.TABLES WHERE TABLE_SCHEMA=DATABASE() AND TABLE_TYPE='BASE TABLE'")->fetchAll(PDO::FETCH_COLUMN); if(array_filter($engines,static fn($v)=>$v!=='InnoDB'))throw new RuntimeException('Nontransactional tables require a maintenance-window locked backup.'); $file=$directory.DIRECTORY_SEPARATOR.'hcr-'.gmdate('Ymd-His').'-'.bin2hex(random_bytes(3)).'.sql'; -$partial=$file.'.partial';$handle=fopen($partial,'x');if(!$handle)throw new RuntimeException('Cannot create protected backup output.');fclose($handle);chmod($partial,0600); -$config=tempnam($directory,'hcr-connection-');chmod($config,0600); +$partial=$file.'.partial';$config=null; $quote=static fn($value)=>'"'.str_replace(["\\",'"',"\r","\n"],["\\\\",'\\"','\\r','\\n'],(string)$value).'"'; $options="[client]\nhost=".$quote($settings->DatabaseServer)."\nport=".(int)($settings->DatabasePort??3306)."\nuser=".$quote($settings->DatabaseUser)."\npassword=".$quote($settings->DatabasePassword)."\n"; $ca=getenv('HCR_DB_TLS_CA');if($ca)$options.='ssl-ca='.$quote($ca)."\nssl-verify-server-cert\n"; try{ + $handle=fopen($partial,'x');if(!$handle)throw new RuntimeException('Cannot create protected backup output.');fclose($handle);chmod($partial,0600); + $config=tempnam($directory,'hcr-connection-');if($config===false)throw new RuntimeException('Cannot create protected connection configuration.');chmod($config,0600); file_put_contents($config,$options); $command=[getenv('HCR_DUMP_BINARY')?:'mariadb-dump','--defaults-extra-file='.$config,'--single-transaction','--quick','--routines','--events','--triggers','--hex-blob','--databases',(string)$settings->DatabaseName,'--result-file='.$partial]; $process=proc_open($command,[0=>['pipe','r'],1=>['pipe','w'],2=>['pipe','w']],$pipes); if(!is_resource($process))throw new RuntimeException('Backup process could not start.'); fclose($pipes[0]);$out=stream_get_contents($pipes[1]);$error=stream_get_contents($pipes[2]);fclose($pipes[1]);fclose($pipes[2]); if(proc_close($process)!==0){error_log('Backup process failed: '.$error);throw new RuntimeException('Backup failed; inspect the protected backup error log.');} - if(!is_file($partial)||filesize($partial)<100||!str_contains(file_get_contents($partial),'Dump completed on'))throw new RuntimeException('Backup completion could not be confirmed.'); + if(!BackupValidation::complete($partial))throw new RuntimeException('Backup completion could not be confirmed.'); if(!rename($partial,$file))throw new RuntimeException('Cannot finalize completed backup.'); chmod($file,0600); $metadata=['created_utc'=>gmdate(DATE_ATOM),'bytes'=>filesize($file),'sha256'=>hash_file('sha256',$file)];file_put_contents($file.'.json',json_encode($metadata,JSON_PRETTY_PRINT));chmod($file.'.json',0600); echo json_encode(['backup'=>$file]+$metadata),"\n"; -}finally{if(is_file($config))unlink($config);if(is_file($partial))unlink($partial);} +}finally{if(is_string($config)&&is_file($config))unlink($config);if(is_file($partial))unlink($partial);} diff --git a/bin/build-release.py b/bin/build-release.py index a14a8f3..c1040ba 100644 --- a/bin/build-release.py +++ b/bin/build-release.py @@ -11,9 +11,9 @@ for directory in ['classes','css','images','js','html','migrations','reports','v for file in (ROOT/directory).rglob('*'): if file.is_file() and not file.is_symlink() and file.suffix.lower() not in ['.sql','.php','.js','.css','.xsl'] and directory not in ['vendor','images','css','html']:continue if file.is_file() and not file.is_symlink() and not any(p.startswith('.') for p in file.relative_to(ROOT).parts) and '_orig.' not in file.name:files.append(file) -for name in ['main.php','.htaccess','web.config','composer.json','composer.lock','xml/settings.xml','xml/constants.xml']: +for name in ['main.php','.htaccess','web.config','composer.json','composer.lock','THIRD-PARTY-NOTICES.md','browser-dependencies.json','xml/settings.xml','xml/constants.xml']: files.append(ROOT/name) -for name in ['migrate-auth.php','migrate-roster.php','migrate-production.php','cleanup-auth.php','check-production.py','backup-database.php','check-health.php']: +for name in ['migrate-auth.php','migrate-roster.php','migrate-production.php','migrate-tenants.php','migrate-security-capacity.php','cleanup-auth.php','check-production.py','backup-database.php','check-health.php']: file=ROOT/'bin'/name if file.exists():files.append(file) if not (ROOT/'vendor/autoload.php').is_file():raise SystemExit('Install locked Composer dependencies before building a release.') diff --git a/bin/check-health.php b/bin/check-health.php index ae0e0e0..549624e 100644 --- a/bin/check-health.php +++ b/bin/check-health.php @@ -4,6 +4,8 @@ require __DIR__.'/../classes/Base.php'; try{ $db=(new Base())->connect();$db->query('SELECT 1')->fetchColumn(); if(!(new RosterService())->ready())throw new RuntimeException('Required schema is missing.'); + foreach(['user_mfa','mfa_recovery','club_resource_usage'] as $table)$db->query('SELECT 1 FROM '.$table.' LIMIT 0'); + if((string)(new Base())->getSettings()->Environment==='Production'){ $key=base64_decode(getenv('HCR_MFA_KEY')?:'',true);if($key===false||strlen($key)!==32)throw new RuntimeException('MFA key is missing.');} foreach(['user_email_verified_at'] as $column){$columns=$db->query('SHOW COLUMNS FROM users')->fetchAll(PDO::FETCH_COLUMN);if(!in_array($column,$columns,true))throw new RuntimeException('Account schema is missing.');} echo "Database and required application schema are available.\n"; }catch(Throwable $e){fwrite(STDERR,"Health check failed. Review the protected server logs.\n");error_log((string)$e);exit(1);} diff --git a/bin/migrate-security-capacity.php b/bin/migrate-security-capacity.php new file mode 100644 index 0000000..a2d23f3 --- /dev/null +++ b/bin/migrate-security-capacity.php @@ -0,0 +1,6 @@ +connect(); +foreach(explode(';',file_get_contents(__DIR__.'/../migrations/005_security_capacity.sql')) as $sql)if(trim($sql))$db->exec($sql); +echo "Security and capacity schema ready. Configure HCR_MFA_KEY before administrator sign-in.\n"; diff --git a/bin/migrate-tenants.php b/bin/migrate-tenants.php new file mode 100644 index 0000000..4d8996d --- /dev/null +++ b/bin/migrate-tenants.php @@ -0,0 +1,27 @@ +connect(); +$columns=$db->query('SHOW COLUMNS FROM club_memberships')->fetchAll(PDO::FETCH_COLUMN); +if(!in_array('membership_role',$columns,true))$db->exec("ALTER TABLE club_memberships ADD COLUMN membership_role ENUM('member','administrator') NOT NULL DEFAULT 'member'"); +// Club display names are tenant-local, not a global account lookup key. +$index=$db->query("SHOW INDEX FROM clubs WHERE Key_name='club_name'")->fetch(); +if($index && !(int)$index['Non_unique'])$db->exec('ALTER TABLE clubs DROP INDEX club_name, ADD INDEX club_name (club_name)'); +foreach(explode(';',file_get_contents(__DIR__.'/../migrations/004_tenants.sql')) as $sql)if(trim($sql))$db->exec($sql); +$email=getenv('HCR_SUPER_ADMIN_EMAIL')?:''; +if($email!==''){ + if(!filter_var($email,FILTER_VALIDATE_EMAIL))throw new RuntimeException('Use a valid existing Super System Administrator email.'); + $db->beginTransaction(); + try{ + $stmt=$db->prepare("SELECT user_serial,user_role FROM users WHERE user_email=? AND user_status='active' FOR UPDATE");$stmt->execute([$email]);$user=$stmt->fetch(); + if(!$user)throw new RuntimeException('The selected active account does not exist. No account was promoted.'); + if($user['user_role']!==TenantAccess::SUPER){ + $stmt=$db->prepare('UPDATE users SET user_role=?,user_auth_version=user_auth_version+1 WHERE user_serial=?');$stmt->execute([TenantAccess::SUPER,$user['user_serial']]); + foreach(['password_resets','email_verifications'] as $table){$stmt=$db->prepare('DELETE FROM '.$table.' WHERE user_serial=?');$stmt->execute([$user['user_serial']]);} + Audit::required($db,(int)$user['user_serial'],'designated Super System Administrator by CLI migration'); + } + $db->commit(); + }catch(Throwable $e){if($db->inTransaction())$db->rollBack();throw $e;} +} +echo "Tenant schema is ready. Existing clubs require explicit administrator assignments; no memberships were guessed.\n"; diff --git a/browser-dependencies.json b/browser-dependencies.json index c7b2a3e..9a3cf36 100644 --- a/browser-dependencies.json +++ b/browser-dependencies.json @@ -6,6 +6,23 @@ "sha256_base64": "/JqT3SQfawRcv/BIHPThkBvs0OEvtFFmqPF/lYI/Cxo=", "upgrade_note": "Patched jQuery 3.x retained for compatibility with the existing Bootstrap plugins; browser regressions required for future upgrades." }, - "bootstrap": {"file": "js/bootstrap.bundle.min.js", "version": "5.3.8"}, - "bootstrap-datepicker": {"file": "js/bootstrap-datepicker.min.js", "version": "1.9.0"} + "bootstrap": { + "file": "js/bootstrap.bundle.min.js", + "version": "5.3.8" + }, + "bootstrap-datepicker": { + "file": "js/bootstrap-datepicker.min.js", + "version": "1.9.0" + }, + "suneditor": { + "version": "3.3.3", + "license": "MIT", + "source": "https://registry.npmjs.org/suneditor/-/suneditor-3.3.3.tgz", + "integrity": "sha512-p/e8ymutQOVDVfGnVo3kVAltkshQdfIDWoR/akMRGg4s1OUuz3eYQGMwd4HbER/oojXLV6YbRrRSQC6hHKSFvA==", + "files": { + "js/suneditor-3.3.3.min.js": "79320e3c797d27fbaabb023dbc170964b2f91047c1abc35722297d65285a9ec5", + "css/suneditor-3.3.3.min.css": "0cffdc05252996ee97609317850f7ae3c84ef8cefab0f11ee477b0a6595116e8", + "THIRD-PARTY-NOTICES.md": "00c332152816d2e8ddff450bb56d35f688f0d6314fca420adea9e3daae7d42df" + } + } } diff --git a/classes/AdminAccounts.php b/classes/AdminAccounts.php index ae3c6b5..015f1fd 100644 --- a/classes/AdminAccounts.php +++ b/classes/AdminAccounts.php @@ -3,12 +3,13 @@ class AdminAccounts extends Base { public function create(array $input): array { + (new TenantAccess())->requireSuper(); $first = trim($input['user_first_name'] ?? ''); $last = trim($input['user_last_name'] ?? ''); $email = trim($input['user_email'] ?? ''); $name = trim($input['user_name'] ?? ''); $role = $input['user_role'] ?? ''; - if (!$first || !$last || strlen($first) > 128 || strlen($last) > 128 || !filter_var($email, FILTER_VALIDATE_EMAIL) || strlen($email) > 100 || !preg_match('/\A[A-Za-z0-9_.-]{3,64}\z/', $name) || !in_array($role, ['User', 'Guest', 'Administrator'], true)) + if (!$first || !$last || strlen($first) > 128 || strlen($last) > 128 || !filter_var($email, FILTER_VALIDATE_EMAIL) || strlen($email) > 100 || !preg_match('/\A[A-Za-z0-9_.-]{3,64}\z/', $name) || !in_array($role, ['User', 'Guest', 'Administrator', TenantAccess::SUPER], true)) throw new AppException('Enter a valid username, first/last name, email and role.'); $db = $this->connect(); $stmt = $db->prepare('SELECT user_serial FROM users WHERE user_name IN (?,?) OR user_email IN (?,?)'); diff --git a/classes/Alerts.php b/classes/Alerts.php index 895adec..63de900 100644 --- a/classes/Alerts.php +++ b/classes/Alerts.php @@ -69,15 +69,8 @@ class Alerts extends Base { case "add": - $alert_title = filter_input(INPUT_POST, "alert_title") ?: ""; - $alert_starts_date = filter_input(INPUT_POST, "alert_starts_date") ?: ""; - $alert_starts_time = filter_input(INPUT_POST, "alert_starts_time") ?: ""; - $alert_expires_date = filter_input(INPUT_POST, "alert_expires_date") ?: ""; - $alert_expires_time = filter_input(INPUT_POST, "alert_expires_time") ?: ""; - $alert_message = filter_input(INPUT_POST, "alert_message") ?: ""; - - $alert_starts = date("Y-m-d H:i", strtotime("{$alert_starts_date} {$alert_starts_time}")); - $alert_expires = date("Y-m-d H:i", strtotime("{$alert_expires_date} {$alert_expires_time}")); + $data=MaintenanceValidation::alert($_POST); + $alert_title=$data['title'];$alert_starts=$data['starts'];$alert_expires=$data['expires'];$alert_message=$data['message']; $SQL = "insert into alerts @@ -120,7 +113,7 @@ class Alerts extends Base { public function deleteAlert() { - $alert_serial = filter_input(INPUT_POST, "alert_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0; + $alert_serial = MaintenanceService::id($_POST['alert_serial']??null); $alert = $this->getAlert($alert_serial); @@ -146,7 +139,7 @@ class Alerts extends Base { case "prompt": - $alert_serial = filter_input(INPUT_POST, "alert_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0; + $alert_serial = MaintenanceService::id($_POST['alert_serial']??null); $alert = $this->getAlert($alert_serial); @@ -162,16 +155,9 @@ class Alerts extends Base { case "update": - $alert_serial = filter_input(INPUT_POST, "alert_serial") ?: 0; - $alert_title = filter_input(INPUT_POST, "alert_title") ?: ""; - $alert_starts_date = filter_input(INPUT_POST, "alert_starts_date") ?: ""; - $alert_starts_time = filter_input(INPUT_POST, "alert_starts_time") ?: ""; - $alert_expires_date = filter_input(INPUT_POST, "alert_expires_date") ?: ""; - $alert_expires_time = filter_input(INPUT_POST, "alert_expires_time") ?: ""; - $alert_message = filter_input(INPUT_POST, "alert_message") ?: ""; - - $alert_starts = date("Y-m-d H:i", strtotime("{$alert_starts_date} {$alert_starts_time}")); - $alert_expires = date("Y-m-d H:i", strtotime("{$alert_expires_date} {$alert_expires_time}")); + $alert_serial = MaintenanceService::id($_POST['alert_serial']??null); + $data=MaintenanceValidation::alert($_POST); + $alert_title=$data['title'];$alert_starts=$data['starts'];$alert_expires=$data['expires'];$alert_message=$data['message']; $alert = $this->getAlert($alert_serial); @@ -211,6 +197,7 @@ class Alerts extends Base { // ===================== public function getAlert($alert_serial = 0) { + $alert_serial=MaintenanceService::id($alert_serial); $SQL = "select *, date_format(alert_started, '%Y') as alert_started_year, diff --git a/classes/AuthService.php b/classes/AuthService.php index 5838c6d..225fba8 100644 --- a/classes/AuthService.php +++ b/classes/AuthService.php @@ -4,6 +4,7 @@ class AuthService extends Base { public const IDLE_TIMEOUT = 1800; + public const ABSOLUTE_TIMEOUT = 28800; public function findUser(string $identifier): ?array { $stmt = $this->connect()->prepare('SELECT * FROM view_users WHERE user_email = :email OR user_name = :name LIMIT 1'); @@ -50,6 +51,8 @@ class AuthService extends Base { $stmt->execute([':hash' => password_hash($password, PASSWORD_DEFAULT), ':id' => $user['user_serial'], ':old_hash' => $hash]); } session_regenerate_id(true); + unset($_SESSION['mfa_user'],$_SESSION['recent_auth'],$_SESSION['mfa_pending'],$_SESSION['mfa_replacement']); + $_SESSION['authenticated_at']=time(); $_SESSION[self::USER_AUTHENTICATED] = true; $_SESSION[self::USER_SERIAL] = (int) $user['user_serial']; $_SESSION[self::USER_NAME] = $user['user_name']; @@ -68,7 +71,7 @@ class AuthService extends Base { public function currentUser(): ?array { if (empty($_SESSION[self::USER_AUTHENTICATED])) return null; - if (time() - ($_SESSION['last_activity'] ?? 0) > self::IDLE_TIMEOUT) + if (time() - ($_SESSION['last_activity'] ?? 0) > self::IDLE_TIMEOUT || time() - ($_SESSION['authenticated_at'] ?? 0) >= self::ABSOLUTE_TIMEOUT) return null; $stmt = $this->connect()->prepare('SELECT * FROM view_users WHERE user_serial = :id'); $stmt->execute([':id' => $_SESSION[self::USER_SERIAL] ?? 0]); @@ -104,8 +107,25 @@ class AuthService extends Base { if ($stmt->fetch()) throw new InvalidArgumentException('Unable to create an account with these details. Try signing in or resetting your password.'); $stmt = $db->prepare("INSERT INTO users (user_name, user_first_name, user_last_name, user_email, user_password_hash, user_role, user_status, user_creator) VALUES (:name, :first, :last, :email, :hash, 'User', 'active', 'Self registration')"); + $kind=$input['registration_kind']??'account'; + if(!in_array($kind,['account','new_club','invited'],true))throw new InvalidArgumentException('Choose a valid signup option.'); + $clubName=trim($input['club_name']??''); + if($kind==='new_club' && ($clubName===''||strlen($clubName)>128))throw new InvalidArgumentException('Enter your new club name (up to 128 bytes).'); try { - $stmt->execute([':name' => $name, ':first' => $first, ':last' => $last, ':email' => $email, ':hash' => password_hash($input['user_password'], PASSWORD_DEFAULT)]); + DatabaseTransaction::run($db,function(PDO $db)use($stmt,$name,$first,$last,$email,$input,$kind,$clubName){ + if($kind==='invited'){ + $invites=$db->prepare("SELECT i.club_serial,i.invited_by,i.membership_role FROM club_invitations i JOIN clubs c ON c.club_serial=i.club_serial WHERE i.invite_email=? AND i.invitation_status='pending' AND i.expires_at>UTC_TIMESTAMP() AND c.club_status='active'");$invites->execute([$email]);$valid=false;$access=new TenantAccess(); + foreach($invites->fetchAll() as $invite)if($access->canManage((int)$invite['club_serial'],$db,(int)$invite['invited_by'])&&($invite['membership_role']==='member'||$access->isSuper($db,(int)$invite['invited_by']))){$valid=true;break;} + if(!$valid)throw new InvalidArgumentException('Ask your club administrator for a current invitation to this email address.'); + } + $stmt->execute([':name'=>$name,':first'=>$first,':last'=>$last,':email'=>$email,':hash'=>password_hash($input['user_password'],PASSWORD_DEFAULT)]); + $user=(int)$db->lastInsertId(); + if($kind==='new_club'){ + $club=$db->prepare("INSERT INTO clubs(club_name,club_status) VALUES(?,'active')");$club->execute([$clubName]);$clubId=(int)$db->lastInsertId(); + $membership=$db->prepare("INSERT INTO club_memberships(club_serial,user_serial,membership_role,membership_status,joined_on) VALUES(?,?,'administrator','active',?)");$membership->execute([$clubId,$user,date('Y-m-d')]); + Audit::required($db,$user,'registered new club '.json_encode(['club'=>$clubId,'name'=>$clubName])); + } + }); } catch (PDOException $e) { if ($e->getCode() === '23000') throw new InvalidArgumentException('Unable to create an account with these details. Try signing in or resetting your password.'); diff --git a/classes/BackupValidation.php b/classes/BackupValidation.php new file mode 100644 index 0000000..f0d786b --- /dev/null +++ b/classes/BackupValidation.php @@ -0,0 +1,14 @@ +applyXSL("", $this->getXSL("content")); + $html = $this->applyXSL("", $this->getXSL("content"), ["IS_SUPER"=>(new TenantAccess())->isSuper()?"1":"0","CAN_MANAGE_CLUBS" => (new TenantAccess())->managesAny()?"1":"0"]); $html = str_replace("$$$-CONTENT-$$$", $content, $html); echo $html; @@ -245,11 +245,18 @@ class Base { exit('Method not allowed.'); } - // Reject arrays and oversized values before passing input to string operations. - foreach (array_merge($_GET, $_POST) as $value) { - if (!is_string($value) || strlen($value) > 8192) { - http_response_code(400); - exit('Invalid request.'); + // Ticket bodies need room for 8,000 four-byte Unicode characters. Keep + // a hard transport ceiling; field validators enforce the character limit. + $candidate=$_POST['action']??$_GET['Xaction']??$_GET['action']??''; + $ticketSubmission=is_string($candidate)&&strtolower(trim($candidate))==='roster.tickets' + && in_array($_POST['step']??null,['openTicket','reply'],true); + foreach ([$_GET,$_POST] as $source=>$values) { + foreach($values as $field=>$value){ + $byteLimit=$source===1&&$ticketSubmission&&$field==='message'?65536:8192; + if (!is_string($value) || strlen($value) > $byteLimit) { + http_response_code(400); + exit('Invalid request.'); + } } } $action = strtolower(trim($_POST['action'] ?? $_GET['Xaction'] ?? $_GET['action'] ?? '')); @@ -296,6 +303,12 @@ class Base { if ($method === 'POST') { $this->requireCsrf(); } + $mfa=new MfaService(); + if($mfa->gate($user,$action))return; + $sensitive=in_array($action,['users.changepassword','users.adduser','users.edituser','users.deleteuser','users.updateactivestatus','users.useractive','users.resetpassword'],true) + || ($action==='roster.membersummary' && ($_POST['step']??'')==='member') + || ($action==='roster.workspace' && (($_POST['step']??'')==='member' || (($_POST['step']??'')==='invite' && ($_POST['membership_role']??'')==='administrator'))); + if($method==='POST' && $sensitive && (new TenantAccess())->managesAny())$mfa->requireRecent(); if ((bool) $user['user_change_password']) { (new Users())->changePassword(); return; @@ -312,7 +325,12 @@ class Base { 'getage' => [Base::class, 'getAge', false], 'users.changepassword' => [Users::class, 'changePassword', false], 'roster.workspace' => [Roster::class,'workspace',false], + 'roster.membersummary' => [MemberSummary::class,'show',false], + 'roster.createclub' => [Roster::class,'createClub','super'], 'roster.help' => [Roster::class,'help',false], + 'roster.invitations' => [Roster::class,'invitations',false], + 'roster.tickets' => [Roster::class,'tickets',false], + 'rosterreports.catalog' => [RosterReports::class,'catalog',true], 'rosterreports.ledger' => [RosterReports::class,'ledger',true], 'rosterreports.csv' => [RosterReports::class,'csv',true], 'rosterreports.excel' => [RosterReports::class,'excel',true], @@ -334,7 +352,7 @@ class Base { ]; foreach ($adminRoutes as $class => $methods) { foreach ($methods as $entry) { - $routes[strtolower($class . '.' . $entry)] = [$class, $entry, true]; + $routes[strtolower($class . '.' . $entry)] = [$class, $entry, $class==='Reports'?true:'super']; } } if (!isset($routes[$action])) { @@ -342,11 +360,11 @@ class Base { exit('Page not found.'); } [$class, $entry, $adminOnly] = $routes[$action]; - if ($adminOnly && !in_array($user['user_role'], ['Administrator', 'System Administrator'], true)) { + if (($adminOnly==='super' && !(new TenantAccess())->isSuper()) || ($adminOnly===true && !(new TenantAccess())->managesAny())) { http_response_code(403); exit('You do not have permission to perform this action.'); } - if ($method !== 'POST' && !in_array($action, ['', './', 'displayhome', 'users.changepassword','roster.workspace','roster.help'], true)) { + if ($method !== 'POST' && !in_array($action, ['', './', 'displayhome', 'users.changepassword','roster.workspace','roster.membersummary','roster.createclub','roster.help','roster.invitations','roster.tickets','rosterreports.catalog'], true)) { http_response_code(405); exit('Use POST for this action.'); } diff --git a/classes/BoundedList.php b/classes/BoundedList.php new file mode 100644 index 0000000..36f4561 --- /dev/null +++ b/classes/BoundedList.php @@ -0,0 +1,39 @@ +['min_range'=>1]]); + if($page===false)throw new AppException('Choose a valid page.');return $page; + } + public static function rows(PDO $db,string $sql,array $args,?int $page,string $scope): array { + if($page!==null){ + $stmt=$db->prepare('SELECT COUNT(*) FROM ('.$sql.') scoped_rows');$stmt->execute($args);$count=(int)$stmt->fetchColumn(); + $paging=Pagination::calculate($count,25,$page);self::$pages[$scope]=$paging+['count'=>$count,'pages'=>max(1,(int)ceil($count/25))]; + $sql.=' LIMIT '.$paging['size'].' OFFSET '.$paging['offset']; + } + if($page===null&&self::$exporting)$sql.=' LIMIT '.(self::exportLimit()+1); + $stmt=$db->prepare($sql);$stmt->execute($args);$rows=$stmt->fetchAll(); + if(self::$exporting&&count($rows)>self::exportLimit())throw new AppException('This export exceeds the configured row limit.',422); + return $rows; + } + public static function navigation(string $scope,?string $action=null): string { + $p=self::$pages[$scope]??null;if(!$p)return ''; + $h=static fn($v)=>htmlspecialchars((string)$v,ENT_QUOTES,'UTF-8');$html=''; + } + public static function exportLimit(): int { + $value=getenv('HCR_EXPORT_MAX_ROWS');$limit=$value===false?1000:filter_var($value,FILTER_VALIDATE_INT,['options'=>['min_range'=>1,'max_range'=>5000]]); + if($limit===false)throw new RuntimeException('Invalid export row limit.');return $limit; + } + public static function exportGuard(PDO $db,string $sql,array $args): void { + $stmt=$db->prepare($sql);$stmt->execute($args); + if((int)$stmt->fetchColumn()>self::exportLimit())throw new AppException('This export exceeds the configured row limit. Contact support for a large export.',422); + } +} diff --git a/classes/ClubFormModals.php b/classes/ClubFormModals.php new file mode 100644 index 0000000..1575cdd --- /dev/null +++ b/classes/ClubFormModals.php @@ -0,0 +1,59 @@ +'Edit or archive club','member'=>'Add member','invite'=>'Invite members', + 'season'=>'Add season','charge'=>'Record season dues','payment'=>'Record payment', + 'adjust'=>'Correct dues','reverse'=>'Reverse incorrect payment','revokeInvitation'=>'Revoke invitation']; + $doc=new DOMDocument('1.0','UTF-8');$previous=libxml_use_internal_errors(true); + try{$loaded=$doc->loadHTML(''.$html,LIBXML_NONET);} + finally{libxml_clear_errors();libxml_use_internal_errors($previous);} + if(!$loaded)throw new RuntimeException('Cannot render club dialogs.'); + $main=$doc->getElementsByTagName('main')->item(0); + if(!$main)throw new LogicException('Club summary container is missing.'); + $dialogs=[];$index=0; + foreach(iterator_to_array($main->getElementsByTagName('form')) as $form){ + $values=[];foreach($form->getElementsByTagName('input') as $input)$values[$input->getAttribute('name')]=$input->getAttribute('value'); + $step=$values['step']??''; + if(!in_array($values['action']??'',['Roster.workspace','Roster.memberSummary'],true)||!isset($titles[$step]))continue; + $title=$step==='member'&&!empty($values['membership_serial'])?'Edit membership':$titles[$step]; + $id='club-action-'.(++$index);$parent=$form->parentNode; + $trigger=$doc->createElement('button');$trigger->appendChild($doc->createTextNode($title)); + foreach(['type'=>'button','class'=>'btn btn-outline-primary me-2 mb-2','data-bs-toggle'=>'modal','data-bs-target'=>'#'.$id,'data-club-step'=>$step] as $key=>$value)$trigger->setAttribute($key,$value); + $dialog=$doc->createElement('div'); + foreach(['class'=>'modal fade club-action-modal','id'=>$id,'tabindex'=>'-1','aria-labelledby'=>$id.'-title','aria-hidden'=>'true'] as $key=>$value)$dialog->setAttribute($key,$value); + $layout=$dialog->appendChild($doc->createElement('div'));$layout->setAttribute('class','modal-dialog modal-lg modal-dialog-centered modal-dialog-scrollable'); + $content=$layout->appendChild($doc->createElement('div'));$content->setAttribute('class','modal-content'); + $header=$content->appendChild($doc->createElement('div'));$header->setAttribute('class','modal-header'); + $heading=$header->appendChild($doc->createElement('h2'));$heading->setAttribute('class','modal-title fs-5');$heading->setAttribute('id',$id.'-title');$heading->appendChild($doc->createTextNode($title)); + $close=$header->appendChild($doc->createElement('button'));$close->setAttribute('type','button');$close->setAttribute('class','btn-close');$close->setAttribute('data-bs-dismiss','modal');$close->setAttribute('aria-label','Close'); + $body=$content->appendChild($doc->createElement('div'));$body->setAttribute('class','modal-body'); + // Keep the selected row visible in the dialog so financial/member actions are unambiguous. + $row=$parent;while($row&&$row!==$main&&!in_array($row->nodeName,['tr','li'],true))$row=$row->parentNode; + if($row&&$row!==$main){ + $text=$row->textContent; + if($row->nodeName==='tr')$text=implode(' · ',array_map(static fn($cell)=>trim($cell->textContent),array_slice(iterator_to_array($row->getElementsByTagName('td')),0,-1))); + $context=$body->appendChild($doc->createElement('p'));$context->setAttribute('class','text-secondary');$context->appendChild($doc->createTextNode(trim(preg_replace('/\s+/u',' ',$text)))); + } + if($parent->nodeName==='details'){ + $parent->parentNode->replaceChild($trigger,$parent); + foreach(iterator_to_array($parent->childNodes) as $child)if($child->nodeName!=='summary')$body->appendChild($child); + }else{ + $previous=$form->previousSibling; + if($previous&&$previous->nodeName==='h4')$previous->parentNode->removeChild($previous); + $following=$form->nextSibling; + $parent->replaceChild($trigger,$form);$body->appendChild($form); + if($following&&$following->nodeName==='p')$body->appendChild($following); + } + $error=$doc->createElement('p');$error->setAttribute('class','alert alert-danger club-modal-error');$error->setAttribute('role','alert');$error->setAttribute('tabindex','-1');$error->setAttribute('hidden','hidden');$body->insertBefore($error,$body->firstChild); + $footer=$content->appendChild($doc->createElement('div'));$footer->setAttribute('class','modal-footer'); + $cancel=$footer->appendChild($doc->createElement('button'));$cancel->setAttribute('type','button');$cancel->setAttribute('class','btn btn-outline-secondary');$cancel->setAttribute('data-bs-dismiss','modal');$cancel->appendChild($doc->createTextNode('Cancel')); + $dialogs[]=$dialog; + if($step==='invite')foreach(iterator_to_array($main->getElementsByTagName('a')) as $link)if($link->getAttribute('href')==='#club-invitations'){$link->parentNode->replaceChild($trigger,$link);break;} + } + foreach($dialogs as $dialog)$main->appendChild($dialog); + $script=$main->appendChild($doc->createElement('script'));$script->setAttribute('src','js/club-modals.js?version='.Base::VERSION); + return $doc->saveHTML($main); + } +} diff --git a/classes/ClubInvitations.php b/classes/ClubInvitations.php new file mode 100644 index 0000000..cb647e0 --- /dev/null +++ b/classes/ClubInvitations.php @@ -0,0 +1,64 @@ +connect(),"SELECT i.invitation_serial,c.club_name,i.membership_role,i.expires_at FROM club_invitations i JOIN clubs c ON c.club_serial=i.club_serial JOIN users u ON LOWER(u.user_email)=LOWER(i.invite_email) WHERE u.user_serial=? AND i.invitation_status='pending' AND i.expires_at>UTC_TIMESTAMP() AND c.club_status='active' ORDER BY i.invitation_serial",[$_SESSION[self::USER_SERIAL]??0],$page,'pending'); + } + public function forClub(int $club,?int $page=null): array { + (new TenantAccess())->requireManager($club);$this->club($club); + return BoundedList::rows($this->connect(),'SELECT invitation_serial,invite_email,membership_role,invitation_status,expires_at FROM club_invitations WHERE club_serial=? ORDER BY invitation_serial DESC',[$club],$page,'invitations'); + } + public function invite(int $club,string $email,string $role='member'): array { + $email=trim($email);$access=new TenantAccess();$access->requireManager($club); + if(!filter_var($email,FILTER_VALIDATE_EMAIL)||strlen($email)>100||!in_array($role,['member','administrator'],true))throw new AppException('Enter a valid invitation email and club role.'); + if($role==='administrator')$access->requireSuper(); + if(!(new AuthService())->allowAttempt('club-invite',($_SESSION[self::USER_SERIAL]??0).':'.$club,20,3600))throw new AppException('Too many invitations. Try again later.',429); + (new ClubResources())->consume($club,'email'); + $db=$this->connect(); + $selected=DatabaseTransaction::run($db,function(PDO $db)use($club,$email,$role,$access){ + $selected=$this->club($club,$db,true); + if($role==='administrator')$access->requireSuper($db); + $stmt=$db->prepare('SELECT * FROM club_invitations WHERE club_serial=? AND invite_email=? FOR UPDATE');$stmt->execute([$club,$email]);$existing=$stmt->fetch(); + if($existing && strtotime($existing['sent_at'].' UTC')>time()-60)throw new AppException('Wait a minute before sending this invitation again.',429); + if($existing && $existing['membership_role']==='administrator')$access->requireSuper($db); + $stmt=$db->prepare("INSERT INTO club_invitations(club_serial,invite_email,membership_role,invited_by,expires_at,sent_at) VALUES(?,?,?,?,DATE_ADD(UTC_TIMESTAMP(),INTERVAL 7 DAY),UTC_TIMESTAMP()) ON DUPLICATE KEY UPDATE membership_role=VALUES(membership_role),invited_by=VALUES(invited_by),invitation_status='pending',expires_at=VALUES(expires_at),sent_at=VALUES(sent_at),accepted_at=NULL"); + $stmt->execute([$club,$email,$role,$_SESSION[self::USER_SERIAL]]); + Audit::required($db,(int)$_SESSION[self::USER_SERIAL],'invited club member '.json_encode(['club'=>$club,'email'=>$email,'role'=>$role]));return $selected; + }); + $sent=false;try{$sent=$this->deliver($email,$selected['club_name']);}catch(Throwable $e){error_log('Club invitation delivery failed: '.$e->getMessage());} + return ['ok'=>true,'message'=>'Invitation saved. The recipient must sign in with this email, verify it, and accept the invitation.','warning'=>$sent?'':'The invitation email could not be sent. The recipient can still sign in and open Invitations; you can retry sending after a minute.']; + } + protected function deliver(string $email,string $club): bool { + $url=rtrim((string)$this->getSettings()->ApplicationUrl,'/'); + if(!filter_var($url,FILTER_VALIDATE_URL)||parse_url($url,PHP_URL_SCHEME)!=='https'||parse_url($url,PHP_URL_QUERY)!==null||parse_url($url,PHP_URL_FRAGMENT)!==null||parse_url($url,PHP_URL_USER)!==null||parse_url($url,PHP_URL_PASS)!==null)throw new RuntimeException('Configure a trusted HTTPS ApplicationUrl.'); + $h=static fn($v)=>htmlspecialchars($v,ENT_QUOTES,'UTF-8'); + $body='

You have been invited to '.$h($club).'.

Sign in and open Invitations. If you do not have an account, use invited member signup with this email and verify it. Accepting the invitation grants access to this club.

This invitation expires in seven days.

'; + return (new Email())->sendEmail($email,self::APPLICATION_NAME.' - Club invitation',$body); + } + public function accept(int $id): void { + $db=$this->connect(); + DatabaseTransaction::run($db,function(PDO $db)use($id){ + // Match membership/account edits: lock the recipient before the club. + $stmt=$db->prepare('SELECT club_serial FROM club_invitations WHERE invitation_serial=?');$stmt->execute([$id]);$club=(int)$stmt->fetchColumn(); + $stmt=$db->prepare('SELECT user_serial,user_email,user_email_verified_at,user_status FROM users WHERE user_serial=? FOR UPDATE');$stmt->execute([$_SESSION[self::USER_SERIAL]??0]);$user=$stmt->fetch(); + $stmt=$db->prepare('SELECT club_status FROM clubs WHERE club_serial=? FOR UPDATE');$stmt->execute([$club]);if($stmt->fetchColumn()!=='active')throw new AppException('Invitation is unavailable.',409); + $stmt=$db->prepare("SELECT * FROM club_invitations WHERE invitation_serial=? AND invitation_status='pending' AND expires_at>UTC_TIMESTAMP() FOR UPDATE");$stmt->execute([$id]);$invite=$stmt->fetch(); + if(!$invite||!$user||strcasecmp($invite['invite_email'],$user['user_email'])!==0)throw new AppException('Invitation is unavailable.',404); + if(!$user['user_email_verified_at']||$user['user_status']!=='active')throw new AppException('Verify your account email before accepting an invitation.',403); + $access=new TenantAccess(); + if(!$access->canManage($club,$db,(int)$invite['invited_by']) || ($invite['membership_role']==='administrator'&&!$access->isSuper($db,(int)$invite['invited_by'])))throw new AppException('Ask a current club administrator to send a new invitation.',409); + $stmt=$db->prepare("INSERT INTO club_memberships(club_serial,user_serial,membership_status,joined_on,membership_role) VALUES(?,?,'active',?,?) ON DUPLICATE KEY UPDATE membership_role=IF(membership_status='active' AND membership_role='administrator','administrator',VALUES(membership_role)),membership_status='active'");$stmt->execute([$club,$user['user_serial'],date('Y-m-d'),$invite['membership_role']]); + $stmt=$db->prepare("UPDATE club_invitations SET invitation_status='accepted',accepted_at=UTC_TIMESTAMP() WHERE invitation_serial=?");$stmt->execute([$id]); + Audit::required($db,(int)$user['user_serial'],'accepted club invitation '.json_encode(['club'=>$club,'invitation'=>$id,'role'=>$invite['membership_role']])); + }); + } + public function revoke(int $club,int $id): void { + $db=$this->connect();DatabaseTransaction::run($db,function(PDO $db)use($club,$id){ + $this->club($club,$db,true); + $stmt=$db->prepare('SELECT membership_role FROM club_invitations WHERE invitation_serial=? AND club_serial=? FOR UPDATE');$stmt->execute([$id,$club]);$role=$stmt->fetchColumn();if(!$role)throw new AppException('Invitation not found.',404); + if($role==='administrator')(new TenantAccess())->requireSuper($db); + $stmt=$db->prepare("UPDATE club_invitations SET invitation_status='revoked' WHERE invitation_serial=? AND club_serial=? AND invitation_status='pending'");$stmt->execute([$id,$club]); + Audit::required($db,(int)$_SESSION[self::USER_SERIAL],'revoked club invitation '.json_encode(['club'=>$club,'invitation'=>$id])); + }); + } +} diff --git a/classes/ClubResources.php b/classes/ClubResources.php new file mode 100644 index 0000000..82b7513 --- /dev/null +++ b/classes/ClubResources.php @@ -0,0 +1,16 @@ +100,'ticket'=>100,'reply'=>1000,'export'=>20]; + if(!isset($defaults[$resource]))throw new LogicException('Unknown club resource.'); + (new RosterService())->club($club); + $raw=getenv('HCR_CLUB_'.strtoupper($resource).'_HOURLY'); + $limit=$raw===false?$defaults[$resource]:filter_var($raw,FILTER_VALIDATE_INT,['options'=>['min_range'=>1,'max_range'=>100000]]); + if($limit===false)throw new RuntimeException('Invalid club resource limit.'); + $db=$this->connect(); + $stmt=$db->prepare("INSERT INTO club_resource_usage(club_serial,resource_name,window_started,used_count) VALUES(?,?,UTC_TIMESTAMP(),LAST_INSERT_ID(1)) ON DUPLICATE KEY UPDATE used_count=LAST_INSERT_ID(IF(window_started<=DATE_SUB(UTC_TIMESTAMP(),INTERVAL 1 HOUR),1,LEAST(used_count+1,100001))),window_started=IF(window_started<=DATE_SUB(UTC_TIMESTAMP(),INTERVAL 1 HOUR),UTC_TIMESTAMP(),window_started)");$stmt->execute([$club,$resource]); + $stmt=$db->query('SELECT LAST_INSERT_ID()'); + if((int)$stmt->fetchColumn()>$limit)throw new AppException('This club has reached its hourly '.$resource.' limit. Try again later.',429); + } +} diff --git a/classes/ClubTickets.php b/classes/ClubTickets.php new file mode 100644 index 0000000..96cce69 --- /dev/null +++ b/classes/ClubTickets.php @@ -0,0 +1,56 @@ +$limit)throw new AppException($label.' must be '.$limit.' characters or fewer.'); + return $value; + } + public function normalizeSearch(string $search): string { + $search=trim($search);return $search===''?'':$this->text($search,100,'Ticket search'); + } + public function page(int $club,int $page=1,string $search=''): array { + $this->club($club);if($page<1)throw new AppException('Choose a valid ticket page.'); + $search=$this->normalizeSearch($search);$manage=$this->manages($club);$args=$manage?[$club]:[$club,$_SESSION[self::USER_SERIAL]??0]; + $scope=' WHERE club_serial=?'.($manage?'':' AND user_serial=?'); + if($search!==''){$scope.=" AND subject LIKE ? ESCAPE '!'";$args[]='%'.str_replace(['!','%','_'],['!!','!%','!_'],$search).'%';} + $db=$this->connect();$stmt=$db->prepare('SELECT COUNT(*) FROM club_tickets'.$scope);$stmt->execute($args);$count=(int)$stmt->fetchColumn(); + $paging=Pagination::calculate($count,25,$page);$pages=max(1,(int)ceil($count/$paging['size'])); + $stmt=$db->prepare('SELECT ticket_serial,subject,ticket_status,user_serial,created_at FROM club_tickets'.$scope.' ORDER BY ticket_serial DESC LIMIT '.$paging['size'].' OFFSET '.$paging['offset']);$stmt->execute($args); + return $paging+['rows'=>$stmt->fetchAll(),'count'=>$count,'pages'=>$pages,'search'=>$search]; + } + public function listing(int $club,int $page=1,string $search=''): array {return $this->page($club,$page,$search)['rows'];} + public function ticket(int $club,int $id,?PDO $db=null): array { + $this->club($club,$db);$stmt=($db??$this->connect())->prepare('SELECT * FROM club_tickets WHERE club_serial=? AND ticket_serial=?');$stmt->execute([$club,$id]);$row=$stmt->fetch(); + if(!$row||(!$this->manages($club,$db)&&(int)$row['user_serial']!==(int)($_SESSION[self::USER_SERIAL]??0)))throw new AppException('Ticket not found.',404);return $row; + } + public function messages(int $club,int $id,?int $page=null): array { + $this->ticket($club,$id);return BoundedList::rows($this->connect(),'SELECT m.message_text,m.created_at,u.user_first_name,u.user_last_name FROM club_ticket_messages m JOIN users u ON u.user_serial=m.author_serial WHERE ticket_serial=? ORDER BY message_serial',[$id],$page,'messages'); + } + public function createTicket(int $club,string $subject,string $message): int { + $subject=$this->text($subject,self::SUBJECT_LIMIT,'Subject');$message=$this->text($message,self::MESSAGE_LIMIT,'Message'); + if(!(new AuthService())->allowAttempt('club-ticket',(string)($_SESSION[self::USER_SERIAL]??0),20,3600))throw new AppException('Too many tickets. Try again later.',429); + (new ClubResources())->consume($club,'ticket'); + $db=$this->connect();return DatabaseTransaction::run($db,function(PDO $db)use($club,$subject,$message){ + $selected=$this->club($club,$db);$stmt=$db->prepare('SELECT club_status FROM clubs WHERE club_serial=? FOR UPDATE');$stmt->execute([$club]);if($stmt->fetchColumn()!=='active')throw new AppException('This club is archived.',409); + $this->club($club,$db);$stmt=$db->prepare('INSERT INTO club_tickets(club_serial,user_serial,subject) VALUES(?,?,?)');$stmt->execute([$club,$_SESSION[self::USER_SERIAL],$subject]);$id=(int)$db->lastInsertId(); + $stmt=$db->prepare('INSERT INTO club_ticket_messages(ticket_serial,author_serial,message_text) VALUES(?,?,?)');$stmt->execute([$id,$_SESSION[self::USER_SERIAL],$message]);Audit::required($db,(int)$_SESSION[self::USER_SERIAL],'opened club ticket '.json_encode(['club'=>$club,'ticket'=>$id]));return $id; + }); + } + public function reply(int $club,int $id,string $message,string $status=''): void { + $message=$this->text($message,self::MESSAGE_LIMIT,'Message');if(!in_array($status,['','open','closed'],true))throw new AppException('Invalid ticket status.'); + if(!(new AuthService())->allowAttempt('ticket-reply',(string)($_SESSION[self::USER_SERIAL]??0),60,3600))throw new AppException('Too many replies. Try again later.',429); + $this->ticket($club,$id);(new ClubResources())->consume($club,'reply'); + $db=$this->connect();DatabaseTransaction::run($db,function(PDO $db)use($club,$id,$message,$status){ + $stmt=$db->prepare('SELECT club_status FROM clubs WHERE club_serial=? FOR UPDATE');$stmt->execute([$club]);if($stmt->fetchColumn()!=='active')throw new AppException('This club is archived.',409); + $row=$this->ticket($club,$id,$db);if($status!=='')(new TenantAccess())->requireManager($club,$db); + if($row['ticket_status']==='closed'&&$status!=='open')throw new AppException('A club administrator must reopen the ticket before replying.',409); + $stmt=$db->prepare('INSERT INTO club_ticket_messages(ticket_serial,author_serial,message_text) VALUES(?,?,?)');$stmt->execute([$id,$_SESSION[self::USER_SERIAL],$message]); + $stmt=$db->prepare('UPDATE club_tickets SET ticket_status=?,updated_at=CURRENT_TIMESTAMP WHERE ticket_serial=?');$stmt->execute([$status?:$row['ticket_status'],$id]);Audit::required($db,(int)$_SESSION[self::USER_SERIAL],'replied to club ticket '.json_encode(['club'=>$club,'ticket'=>$id,'status'=>$status?:$row['ticket_status']])); + }); + } +} diff --git a/classes/DatabaseTransaction.php b/classes/DatabaseTransaction.php new file mode 100644 index 0000000..0a6f7fe --- /dev/null +++ b/classes/DatabaseTransaction.php @@ -0,0 +1,19 @@ +inTransaction())throw new LogicException('Retryable work must own its transaction.'); + for($attempt=1;$attempt<=3;$attempt++){ + $db->beginTransaction(); + try{ + $result=$work($db);$db->commit();return $result; + }catch(Throwable $error){ + if($db->inTransaction())$db->rollBack(); + $retryable=$error instanceof PDOException && (in_array((int)($error->errorInfo[1]??0),[1205,1213],true)||$error->getCode()==='40001'); + if(!$retryable||$attempt===3)throw $error; + usleep(random_int(10000,30000)*$attempt); + } + } + throw new LogicException('Transaction attempts exhausted.'); + } +} diff --git a/classes/LedgerService.php b/classes/LedgerService.php index 78d7444..04aa353 100644 --- a/classes/LedgerService.php +++ b/classes/LedgerService.php @@ -5,8 +5,8 @@ class LedgerService extends RosterService { private function key(string $key): void {if(!preg_match('/\A[a-f0-9]{64}\z/',$key))throw new AppException('Invalid request key.');} private function reason(string $reason): string {$reason=trim($reason);if(!$reason||strlen($reason)>500)throw new AppException('Enter a correction reason, up to 500 bytes.');return $reason;} private function transaction(callable $work): void { - $this->requireAdministrator();$db=$this->connect();$db->beginTransaction(); - try{$work($db);$db->commit();}catch(Throwable $e){if($db->inTransaction())$db->rollBack();throw $e;} + $this->requireAdministrator();$db=$this->connect(); + DatabaseTransaction::run($db,$work); } private function lockedDue(PDO $db,int $club,int $due): array { $this->club($club,$db,true); @@ -25,11 +25,12 @@ class LedgerService extends RosterService { Audit::required($db,$this->actor(),'created dues '.json_encode(['due'=>(int)$db->lastInsertId(),'club'=>$club,'membership'=>$membership,'season'=>$season,'amount_cents'=>$cents])); }); } - public function payment(int $club,int $due,string $amount,string $paid,string $key,string $method='unspecified',string $reference=''): void { + public function payment(int $club,int $due,string $amount,string $paid,string $key,string $method='unspecified',string $reference='',?int $membership=null): void { $cents=self::cents($amount);self::date($paid);$this->key($key);$reference=trim($reference); if($cents<=0||$paid>date('Y-m-d')||!in_array($method,['unspecified','cash','check','transfer','other'],true)||strlen($reference)>100)throw new AppException('Enter a positive payment, a valid date/method, and a reference up to 100 bytes.'); - $this->transaction(function(PDO $db)use($club,$due,$cents,$paid,$key,$method,$reference){ + $this->transaction(function(PDO $db)use($club,$due,$cents,$paid,$key,$method,$reference,$membership){ $row=$this->lockedDue($db,$club,$due); + if($membership!==null&&(int)$row['membership_serial']!==$membership)throw new AppException('Dues record does not belong to this membership.',404); $stmt=$db->prepare('SELECT * FROM club_payments WHERE request_key=?');$stmt->execute([$key]);$existing=$stmt->fetch(); if($existing){if((int)$existing['due_serial']!==$due||(int)$existing['amount_cents']!==$cents||$existing['paid_on']!==$paid||$existing['payment_method']!==$method||$existing['payment_reference']!==$reference)throw new AppException('This request key was already used for different payment details.',409);return;} if($cents>$row['effective']-$row['paid'])throw new AppException('Payment exceeds the outstanding balance.',409); @@ -59,10 +60,11 @@ class LedgerService extends RosterService { Audit::required($db,$this->actor(),'reversed payment '.json_encode(['reversal'=>(int)$db->lastInsertId(),'club'=>$club,'payment'=>$payment,'amount_cents'=>(int)$row['amount_cents'],'reason'=>$reason])); }); } - public function history(int $club): array { + public function history(int $club,?int $page=null,?int $adjustmentPage=null,?int $membership=null): array { $this->club($club);$result=[];$db=$this->connect(); - $scope=$this->administrator()?'':' AND m.user_serial=?';$args=$this->administrator()?[$club]:[$club,$_SESSION[self::USER_SERIAL]??0]; - $stmt=$db->prepare('SELECT p.*,m.user_serial,r.reversal_serial,r.reason AS reversal_reason,r.created_at AS reversed_at,CONCAT_WS(" ",u.user_first_name,u.user_last_name) AS member_name,a.user_name AS actor,ra.user_name AS reversal_actor FROM club_payments p JOIN club_dues d ON d.due_serial=p.due_serial JOIN club_memberships m ON m.membership_serial=d.membership_serial JOIN users u ON u.user_serial=m.user_serial LEFT JOIN club_payment_reversals r ON r.payment_serial=p.payment_serial LEFT JOIN users a ON a.user_serial=p.recorded_by LEFT JOIN users ra ON ra.user_serial=r.recorded_by WHERE d.club_serial=?'.$scope.' ORDER BY p.paid_on DESC,p.payment_serial DESC');$stmt->execute($args);$result['payments']=$stmt->fetchAll(); - $stmt=$db->prepare('SELECT x.*,CONCAT_WS(" ",u.user_first_name,u.user_last_name) AS member_name,a.user_name AS actor FROM club_due_adjustments x JOIN club_dues d ON d.due_serial=x.due_serial JOIN club_memberships m ON m.membership_serial=d.membership_serial JOIN users u ON u.user_serial=m.user_serial JOIN users a ON a.user_serial=x.recorded_by WHERE d.club_serial=?'.$scope.' ORDER BY x.adjustment_serial DESC');$stmt->execute($args);$result['adjustments']=$stmt->fetchAll();return $result; + $scope=$this->manages($club)?'':' AND m.user_serial=?';$args=$this->manages($club)?[$club]:[$club,$_SESSION[self::USER_SERIAL]??0]; + if($membership!==null){$this->member($club,$membership);$scope.=' AND m.membership_serial=?';$args[]=$membership;} + $result['payments']=BoundedList::rows($db,'SELECT p.*,m.user_serial,r.reversal_serial,r.reason AS reversal_reason,r.created_at AS reversed_at,CONCAT_WS(" ",u.user_first_name,u.user_last_name) AS member_name,a.user_name AS actor,ra.user_name AS reversal_actor FROM club_payments p JOIN club_dues d ON d.due_serial=p.due_serial JOIN club_memberships m ON m.membership_serial=d.membership_serial JOIN users u ON u.user_serial=m.user_serial LEFT JOIN club_payment_reversals r ON r.payment_serial=p.payment_serial LEFT JOIN users a ON a.user_serial=p.recorded_by LEFT JOIN users ra ON ra.user_serial=r.recorded_by WHERE d.club_serial=?'.$scope.' ORDER BY p.paid_on DESC,p.payment_serial DESC',$args,$page,'payments'); + $result['adjustments']=BoundedList::rows($db,'SELECT x.*,CONCAT_WS(" ",u.user_first_name,u.user_last_name) AS member_name,a.user_name AS actor FROM club_due_adjustments x JOIN club_dues d ON d.due_serial=x.due_serial JOIN club_memberships m ON m.membership_serial=d.membership_serial JOIN users u ON u.user_serial=m.user_serial JOIN users a ON a.user_serial=x.recorded_by WHERE d.club_serial=?'.$scope.' ORDER BY x.adjustment_serial DESC',$args,$adjustmentPage,'adjustments');return $result; } } diff --git a/classes/MaintenanceService.php b/classes/MaintenanceService.php index 1cd0171..94bde49 100644 --- a/classes/MaintenanceService.php +++ b/classes/MaintenanceService.php @@ -120,19 +120,20 @@ class MaintenanceService extends Base { } private function lockAdministrators(PDO $db): array { - return $db->query("SELECT user_serial FROM users WHERE user_status='active' AND user_role IN ('Administrator','System Administrator') ORDER BY user_serial FOR UPDATE")->fetchAll(PDO::FETCH_COLUMN); + return $db->query("SELECT user_serial FROM users WHERE user_status='active' AND user_role='Super System Administrator' ORDER BY user_serial FOR UPDATE")->fetchAll(PDO::FETCH_COLUMN); } private function guardAdministrator(array $admins, int $id, string $role, string $status, bool $deleting = false): void { if ($deleting && $id === (int) ($_SESSION[self::USER_SERIAL] ?? 0)) throw new AppException('You cannot delete your own account.', 409); - if (in_array($id, array_map('intval', $admins), true) && count($admins) <= 1 && ($deleting || $status !== 'active' || !in_array($role, ['Administrator', 'System Administrator'], true))) { - throw new AppException('The last active administrator cannot be removed, disabled or demoted.', 409); + if (in_array($id, array_map('intval', $admins), true) && count($admins) <= 1 && ($deleting || $status !== 'active' || $role!==TenantAccess::SUPER)) { + throw new AppException('The last active Super System Administrator cannot be removed, disabled or demoted.', 409); } } public function userUsed(int $id, ?PDO $db = null): bool { $db ??= $this->connect(); + (new TenantAccess())->requireSuper($db); $stmt = $db->prepare("SELECT COUNT(*) FROM notes WHERE note_type='User' AND note_reference=?"); $stmt->execute([$id]); if ((int) $stmt->fetchColumn() > 0) @@ -149,20 +150,25 @@ class MaintenanceService extends Base { if ((int) $stmt->fetchColumn() > 0) return true; } + foreach(['club_invitations'=>'invited_by','club_tickets'=>'user_serial','club_ticket_messages'=>'author_serial'] as $table=>$column){ + $stmt=$db->prepare("SELECT COUNT(*) FROM information_schema.TABLES WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME=?");$stmt->execute([$table]); + if($stmt->fetchColumn()){$stmt=$db->prepare('SELECT 1 FROM '.$table.' WHERE '.$column.'=? LIMIT 1');$stmt->execute([$id]);if($stmt->fetchColumn())return true;} + } return false; } public function deleteUser(int $id): void { + (new TenantAccess())->requireSuper(); $db = $this->connect(); - $db->beginTransaction(); - try { + DatabaseTransaction::run($db,function(PDO $db)use($id){ $admins = $this->lockAdministrators($db); + (new TenantAccess())->requireSuper($db); $stmt = $db->prepare('SELECT user_role,user_status FROM users WHERE user_serial=? FOR UPDATE'); $stmt->execute([$id]); $user = $stmt->fetch(); if (!$user) throw new AppException('User not found.', 404); - if ($user['user_role'] === 'System Administrator' && ($_SESSION[self::USER_ROLE] ?? '') !== 'System Administrator') + if ($user['user_role'] === TenantAccess::SUPER && !(new TenantAccess())->isSuper($db)) throw new AppException('Only a system administrator can modify that account.', 403); $this->guardAdministrator($admins, $id, $user['user_role'], $user['user_status'], true); if ($this->userUsed($id, $db)) @@ -172,35 +178,32 @@ class MaintenanceService extends Base { $stmt = $db->prepare('DELETE FROM users WHERE user_serial=?'); $stmt->execute([$id]); Audit::required($db, (int) ($_SESSION[self::USER_SERIAL] ?? 0), 'deleted unused user ' . $id); - $db->commit(); - } catch (Throwable $e) { - if ($db->inTransaction()) - $db->rollBack();throw $e; - } + }); } public function updateUser(int $id, array $input): void { + (new TenantAccess())->requireSuper(); $name = trim($input['user_name'] ?? ''); $email = trim($input['user_email'] ?? ''); $first = trim($input['user_first_name'] ?? ''); $last = trim($input['user_last_name'] ?? ''); $role = $input['user_role'] ?? ''; $status = self::boolean($input['user_active'] ?? false) ? 'active' : 'inactive'; - if (!preg_match('/\A[A-Za-z0-9_.-]{3,64}\z/', $name) || !filter_var($email, FILTER_VALIDATE_EMAIL) || strlen($email) > 100 || !$first || !$last || strlen($first) > 128 || strlen($last) > 128 || !in_array($role, ['User', 'Guest', 'Administrator', 'System Administrator'], true)) + if (!preg_match('/\A[A-Za-z0-9_.-]{3,64}\z/', $name) || !filter_var($email, FILTER_VALIDATE_EMAIL) || strlen($email) > 100 || !$first || !$last || strlen($first) > 128 || strlen($last) > 128 || !in_array($role, ['User', 'Guest', 'Administrator', TenantAccess::SUPER], true)) throw new AppException('Enter a valid username, first/last name, email and role.'); // Only an existing system administrator may assign that role. - if ($role === 'System Administrator' && ($_SESSION[self::USER_ROLE] ?? '') !== 'System Administrator') + if ($role === TenantAccess::SUPER && !(new TenantAccess())->isSuper()) throw new AppException('Only a system administrator can assign that role.', 403); $db = $this->connect(); - $db->beginTransaction(); - try { + DatabaseTransaction::run($db,function(PDO $db)use($id,$name,$email,$first,$last,$role,$status){ $admins = $this->lockAdministrators($db); + (new TenantAccess())->requireSuper($db); $stmt = $db->prepare('SELECT * FROM users WHERE user_serial=? FOR UPDATE'); $stmt->execute([$id]); $old = $stmt->fetch(); if (!$old) throw new AppException('User not found.', 404); - if ($old['user_role'] === 'System Administrator' && ($_SESSION[self::USER_ROLE] ?? '') !== 'System Administrator') + if ($old['user_role'] === TenantAccess::SUPER && !(new TenantAccess())->isSuper($db)) throw new AppException('Only a system administrator can modify that account.', 403); $this->guardAdministrator($admins, $id, $role, $status); $revoke = $old['user_role'] !== $role || $old['user_status'] !== $status || $old['user_email'] !== $email || $old['user_name'] !== $name; @@ -218,24 +221,21 @@ class MaintenanceService extends Base { } $fields = ['user_name', 'user_email', 'user_first_name', 'user_last_name', 'user_role', 'user_status']; Audit::required($db, (int) ($_SESSION[self::USER_SERIAL] ?? 0), 'updated user ' . json_encode(['user' => $id, 'before' => array_intersect_key($old, array_flip($fields)), 'after' => ['user_name' => $name, 'user_email' => $email, 'user_first_name' => $first, 'user_last_name' => $last, 'user_role' => $role, 'user_status' => $status]])); - $db->commit(); - } catch (Throwable $e) { - if ($db->inTransaction()) - $db->rollBack();throw $e; - } + }); } public function setUserActive(int $id, bool $active): void { + (new TenantAccess())->requireSuper(); $db = $this->connect(); - $db->beginTransaction(); - try { + DatabaseTransaction::run($db,function(PDO $db)use($id,$active){ $admins = $this->lockAdministrators($db); + (new TenantAccess())->requireSuper($db); $stmt = $db->prepare('SELECT user_role FROM users WHERE user_serial=? FOR UPDATE'); $stmt->execute([$id]); $role = $stmt->fetchColumn(); if (!$role) throw new AppException('User not found.', 404); - if ($role === 'System Administrator' && ($_SESSION[self::USER_ROLE] ?? '') !== 'System Administrator') + if ($role === TenantAccess::SUPER && !(new TenantAccess())->isSuper($db)) throw new AppException('Only a system administrator can modify that account.', 403); $this->guardAdministrator($admins, $id, $role, $active ? 'active' : 'inactive'); $stmt = $db->prepare('UPDATE users SET user_status=?,user_auth_version=user_auth_version+1 WHERE user_serial=?'); @@ -245,11 +245,7 @@ class MaintenanceService extends Base { $stmt = $db->prepare('DELETE FROM email_verifications WHERE user_serial=?'); $stmt->execute([$id]); Audit::required($db, (int) ($_SESSION[self::USER_SERIAL] ?? 0), 'changed user status ' . json_encode(['user' => $id, 'active' => $active])); - $db->commit(); - } catch (Throwable $e) { - if ($db->inTransaction()) - $db->rollBack();throw $e; - } + }); } public function deleteStatus(int $id): void { diff --git a/classes/MaintenanceValidation.php b/classes/MaintenanceValidation.php new file mode 100644 index 0000000..cbe09c6 --- /dev/null +++ b/classes/MaintenanceValidation.php @@ -0,0 +1,45 @@ + $limit) + throw new AppException($label . ' must be ' . $limit . ' characters or fewer.'); + if ($singleLine && preg_match('/[\x00-\x1f\x7f]/u', $value)) + throw new AppException($label . ' must be a single line.'); + return $value; + } + + private static function timestamp(array $input, string $prefix, string $label): string { + $date = self::text($input, $prefix . '_date', $label . ' date', 10, true, true); + $time = self::text($input, $prefix . '_time', $label . ' time', 5, true, true); + $value = $date . ' ' . $time; + if (!preg_match('/\A[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}\z/', $value)) + throw new AppException($label . ' must use a valid YYYY-MM-DD date and HH:MM time.'); + $parsed = DateTimeImmutable::createFromFormat('!Y-m-d H:i', $value, new DateTimeZone(Base::TIMEZONE)); + $errors = DateTimeImmutable::getLastErrors(); + if (!$parsed || ($errors && ($errors['warning_count'] || $errors['error_count'])) || $parsed->format('Y-m-d H:i') !== $value || $date < '1000-01-01') + throw new AppException($label . ' date/time is invalid.'); + return $value; + } + + public static function alert(array $input): array { + $title = self::text($input, 'alert_title', 'Alert title', 100, true, true); + $starts = self::timestamp($input, 'alert_starts', 'Start'); + $expires = self::timestamp($input, 'alert_expires', 'Expiration'); + if ($expires < $starts) + throw new AppException('Expiration cannot be before the start.'); + return ['title' => $title, 'starts' => $starts, 'expires' => $expires, 'message' => self::text($input, 'alert_message', 'Alert message', 1000)]; + } + + public static function popover(array $input): array { + return ['name' => self::text($input, 'popover_name', 'Popover name', 100, true, true), 'title' => self::text($input, 'popover_title', 'Popover title', 100, true, true), 'placeholder' => self::text($input, 'popover_placeholder', 'Popover placeholder', 100, false, true), 'text' => self::text($input, 'popover_text', 'Popover text', 1000)]; + } +} diff --git a/classes/MemberSummary.php b/classes/MemberSummary.php new file mode 100644 index 0000000..bdb7505 --- /dev/null +++ b/classes/MemberSummary.php @@ -0,0 +1,89 @@ +'Roster.memberSummary','club_serial'=>$club,'membership_serial'=>$membership,'members_page'=>BoundedList::page('members'),'dues_page'=>BoundedList::page('dues'),'payments_page'=>BoundedList::page('payments'),'adjustments_page'=>BoundedList::page('adjustments'),'seasons_page'=>BoundedList::page('seasons')]); + return '

Member: '.self::h($this->memberLabel).'

'; + } + private static function field(string $name,string $label,string $type='text',string $value='',int $max=128): string { + $id='member_'.$name.'_'.bin2hex(random_bytes(3)); + return '
'; + } + + public function show(): void { + $club=MaintenanceService::id($_GET['club_serial']??$_POST['club_serial']??null); + $membership=MaintenanceService::id($_GET['membership_serial']??$_POST['membership_serial']??null); + $service=new RosterService();$member=$service->member($club,$membership);$selected=$service->club($club); + $this->memberLabel=trim($member['user_first_name'].' '.$member['user_last_name']).' ('.$member['user_email'].')'; + $manage=$service->manages($club);$super=(new TenantAccess())->isSuper();$active=$selected['club_status']==='active'; + if(($_SERVER['REQUEST_METHOD']??'GET')==='POST'){ + $this->requireCsrf();(new TenantAccess())->requireManager($club); + if(!$active)throw new AppException('Reactivate the club before changing records.',409); + if((int)($_POST['membership_serial']??0)!==$membership||(int)($_POST['club_serial']??0)!==$club)throw new AppException('The selected membership changed. Reload its summary.',409); + switch($_POST['step']??''){ + case 'member':$service->saveMember($club,$membership,'',$_POST['membership_status']??'',$_POST['joined_on']??'',$_POST['membership_role']??'member');break; + case 'charge':$service->charge($club,$membership,MaintenanceService::id($_POST['season_serial']??null),$_POST['amount']??'');break; + case 'payment':(new LedgerService())->payment($club,MaintenanceService::id($_POST['due_serial']??null),$_POST['amount']??'',$_POST['paid_on']??'',$_POST['request_key']??'',$_POST['payment_method']??'unspecified',$_POST['payment_reference']??'',$membership);break; + default:throw new AppException('Unknown member action.'); + } + $_SESSION['roster_notice']='Changes saved.'; + $redirect='main.php?'.http_build_query(['Xaction'=>'Roster.memberSummary','club_serial'=>$club,'membership_serial'=>$membership,'members_page'=>BoundedList::page('members'),'dues_page'=>BoundedList::page('dues'),'payments_page'=>BoundedList::page('payments'),'adjustments_page'=>BoundedList::page('adjustments'),'seasons_page'=>BoundedList::page('seasons')]); + if(($_SESSION[self::AJAX]??false)&&($_SERVER['HTTP_X_HCR_MODAL']??'')==='1'){header('Content-Type: application/json');echo json_encode(['ok'=>true,'redirect'=>$redirect]);return;} + header('Location: '.$redirect,true,303);return; + } + $dues=$service->dues($club,BoundedList::page('dues'),$membership); + $history=(new LedgerService())->history($club,BoundedList::page('payments'),BoundedList::page('adjustments'),$membership); + // Totals include every season, independently of the visible history pages. + $stmt=$this->connect()->prepare('SELECT COALESCE(SUM(d.amount_cents+COALESCE((SELECT SUM(a.amount_cents) FROM club_due_adjustments a WHERE a.due_serial=d.due_serial),0)),0) AS dues_cents,COALESCE(SUM(COALESCE((SELECT SUM(p.amount_cents) FROM club_payments p WHERE p.due_serial=d.due_serial AND NOT EXISTS(SELECT 1 FROM club_payment_reversals r WHERE r.payment_serial=p.payment_serial)),0)),0) AS paid_cents FROM club_dues d WHERE d.club_serial=? AND d.membership_serial=?'); + $stmt->execute([$club,$membership]);$totals=$stmt->fetch(); + $back='main.php?'.http_build_query(['Xaction'=>'Roster.workspace','club_serial'=>$club,'members_page'=>BoundedList::page('members')]).'#roster'; + $name=trim($member['user_first_name'].' '.$member['user_last_name']); + $html='

'.self::h($name).'

'.self::h($member['user_email']).'

Club: '.self::h($selected['club_name']).' · '.self::h(ucfirst($selected['club_status'])).'

Membership: '.self::h(ucfirst($member['membership_status'])).' · '.self::h(ucfirst($member['membership_role'])).'
Joined: '.self::h($member['joined_on']).'

Back to club roster
'; + if(!empty($_SESSION['roster_notice'])){$html.='

'.self::h($_SESSION['roster_notice']).'

';unset($_SESSION['roster_notice']);} + if($manage&&$active){ + $html.=''; + } + $html.='
'; + foreach(['Total dues'=>(int)$totals['dues_cents'],'Payments received'=>(int)$totals['paid_cents'],'Balance due'=>(int)$totals['dues_cents']-(int)$totals['paid_cents']] as $label=>$amount) + $html.='

'.$label.'

'.self::money($amount).'

'; + $html.='

Amounts are in USD. Totals include all seasons and exclude reversed payments.

Season dues

'.($manage&&$active?'':'').''; + foreach($dues as $due){ + $balance=(int)$due['amount_cents']-(int)$due['paid_cents']; + $html.=''; + if($manage&&$active){ + $html.=''; + } + $html.=''; + } + if(!$dues)$html.=''; + $html.='
SeasonDuesPaidBalanceActions
'.self::h($due['season_name']).''.self::money((int)$due['amount_cents']).''.self::money((int)$due['paid_cents']).''.self::money($balance).''; + if($balance>0)$html.=$this->form('payment',$club,$membership).''.self::field('amount','Payment (USD)').self::field('paid_on','Received on','date',date('Y-m-d')).''; + $html.='
No dues recorded for this membership.
'.BoundedList::navigation('dues','Roster.memberSummary').'

Payment history

'; + foreach($history['payments'] as $payment){ + $status=$payment['reversal_serial']?'Reversed: '.$payment['reversal_reason'].' ('.$payment['reversed_at'].' UTC)':'Received'; + $html.=''; + } + if(!$history['payments'])$html.=''; + $html.='
PaymentDateAmountMethod / referenceStatus
#'.(int)$payment['payment_serial'].' · Dues #'.(int)$payment['due_serial'].''.self::h($payment['paid_on']).''.self::money((int)$payment['amount_cents']).''.self::h($payment['payment_method'].' / '.$payment['payment_reference']).''.self::h($status).'
No payments recorded for this membership.
'.BoundedList::navigation('payments','Roster.memberSummary').'

Dues correction history

'; + foreach($history['adjustments'] as $adjustment)$html.=''; + if(!$history['adjustments'])$html.=''; + $html.='
Date (UTC)AdjustmentCorrected totalReason
'.self::h($adjustment['created_at']).''.self::money((int)$adjustment['amount_cents']).''.self::money((int)$adjustment['corrected_amount_cents']).''.self::h($adjustment['reason']).'
No dues corrections recorded for this membership.
'.BoundedList::navigation('adjustments','Roster.memberSummary').'
'; + $this->displayContent($manage&&$active?ClubFormModals::render($html):$html); + } +} diff --git a/classes/MfaClock.php b/classes/MfaClock.php new file mode 100644 index 0000000..1525794 --- /dev/null +++ b/classes/MfaClock.php @@ -0,0 +1,8 @@ +'An authenticator was added to your account.', + 'replacement_started'=>'An authenticator replacement was requested. Your existing authenticator remains active until replacement is confirmed.', + 'replacement_started_recovery'=>'A single-use recovery code was used to request authenticator replacement. Your existing authenticator remains active until replacement is confirmed.', + 'replaced'=>'Your authenticator was replaced. Old recovery codes and other sign-in sessions have been revoked.', + 'recovery_used'=>'A single-use recovery code was used to authenticate your account.' + ]; + if(!isset($events[$event]))throw new LogicException('Unknown MFA notification event.'); + $h=static fn($text)=>htmlspecialchars((string)$text,ENT_QUOTES,'UTF-8'); + $body='

'.$h($events[$event]).'

Account: '.$h($account['user_email']).'
Time (UTC): '.$h(gmdate('Y-m-d H:i:s')).'

If you did not authorize this activity, contact your site administrator immediately and secure your account.

'; + $ok=false; + try{$ok=$this->deliver((string)$account['user_email'],self::APPLICATION_NAME.' - Account security notice',$body);} + catch(Throwable $error){/* Keep secrets and provider diagnostics out of this event log. */} + if(!$ok)error_log('MFA security notification failed user='.(int)$account['user_serial'].' event='.$event); + return $ok; + } + protected function deliver(string $to,string $subject,string $body): bool {return (new Email())->sendEmail($to,$subject,$body);} + public static function notice(): string { + if(empty($_SESSION['mfa_notification_warning']))return ''; + unset($_SESSION['mfa_notification_warning']); + return ''; + } +} diff --git a/classes/MfaService.php b/classes/MfaService.php new file mode 100644 index 0000000..12a305f --- /dev/null +++ b/classes/MfaService.php @@ -0,0 +1,251 @@ +getSettings(); + $file = getenv('HCR_MFA_KEY_FILE'); + if ($file === false) + $file = (string) ($settings->MfaKeyFile ?? ''); + if ((string) $settings->Environment === 'Development' && $file !== '') { + $resolved = realpath($file); + $root = realpath(__DIR__ . '/..'); + $normalize = static fn($path) => strtolower(str_replace('\\', '/', $path)); + if ($resolved === false || !is_file($resolved) || !is_readable($resolved) || filesize($resolved) > 128 || str_starts_with($normalize($resolved), $normalize($root) . '/')) + throw new RuntimeException('Development MFA key must be a readable file outside the application directory.'); + $encoded = trim(file_get_contents($resolved)); + } + } + $key = base64_decode($encoded === false ? '' : $encoded, true); + if ($key === false || strlen($key) !== 32) + throw new RuntimeException('Configure HCR_MFA_KEY with a base64-encoded random 32-byte key.'); + return $key; + } + + public function sealSecret(string $secret, int $user): string { + $iv = random_bytes(12); + $tag = ''; + $cipher = openssl_encrypt($secret, 'aes-256-gcm', $this->key(), OPENSSL_RAW_DATA, $iv, $tag, (string) $user); + if ($cipher === false) + throw new RuntimeException('Cannot protect authenticator secret.'); + return base64_encode($iv . $tag . $cipher); + } + + private function decrypt(string $cipher, int $user): string { + $raw = base64_decode($cipher, true); + if ($raw === false || strlen($raw) < 29) + throw new RuntimeException('Invalid authenticator secret.'); + $secret = openssl_decrypt(substr($raw, 28), 'aes-256-gcm', $this->key(), OPENSSL_RAW_DATA, substr($raw, 0, 12), substr($raw, 12, 16), (string) $user); + if ($secret === false) + throw new RuntimeException('Cannot unlock authenticator secret.');return $secret; + } + + public function enrolled(int $user): bool { + $stmt = $this->connect()->prepare('SELECT 1 FROM user_mfa WHERE user_serial=?'); + $stmt->execute([$user]); + return (bool) $stmt->fetchColumn(); + } + + public function required(int $user): bool { + return (new TenantAccess())->managesAny() || $this->enrolled($user); + } + + public function verified(int $user): bool { + return ($_SESSION['mfa_user'] ?? 0) === $user; + } + + private function limited(int $user): void { + $auth = new AuthService(); + if (!$auth->allowAttempt('mfa-account', (string) $user, 10, 300) || !$auth->allowAttempt('mfa-ip', $_SERVER['REMOTE_ADDR'] ?? '', 40, 300)) + throw new AppException('Too many authentication attempts. Try again later.', 429); + } + + private static function counter(string $secret, string $code, int $last): ?int { + if (!preg_match('/\A[0-9]{6}\z/', $code)) + return null; + $otp = TOTP::createFromSecret($secret, new MfaClock()); + $now = intdiv(time(), 30); + foreach ([$now, $now - 1, $now + 1] as $counter) + if ($counter > $last && hash_equals($otp->at($counter * 30), $code)) + return $counter; + return null; + } + + /** All factor mutations use the account-then-factor lock order. */ + private function account(PDO $db,int $user,string $password): ?array { + $stmt=$db->prepare('SELECT user_serial,user_email,user_password_hash,user_status,user_auth_version FROM users WHERE user_serial=? FOR UPDATE'); + $stmt->execute([$user]);$account=$stmt->fetch(); + if(!$account||$account['user_status']!=='active'||($_SESSION[self::USER_SERIAL]??0)!==$user + ||($_SESSION['auth_version']??-1)!==(int)$account['user_auth_version'] + ||!password_verify($password,$account['user_password_hash']))return null; + return $account; + } + + private function factor(PDO $db,int $user): ?array { + $stmt=$db->prepare('SELECT * FROM user_mfa WHERE user_serial=? FOR UPDATE');$stmt->execute([$user]);return $stmt->fetch()?:null; + } + + private function consume(PDO $db,int $user,array $factor,string $code): ?string { + $code=trim($code);$counter=self::counter($this->decrypt($factor['secret_cipher'],$user),$code,(int)$factor['last_counter']); + if($counter!==null){ + $stmt=$db->prepare('UPDATE user_mfa SET last_counter=? WHERE user_serial=?');$stmt->execute([$counter,$user]);return 'totp'; + } + $code=strtolower($code);if(!preg_match('/\A[a-f0-9]{32}\z/',$code))return null; + $stmt=$db->prepare('DELETE FROM mfa_recovery WHERE user_serial=? AND code_hash=?');$stmt->execute([$user,hash('sha256',$code)]); + return $stmt->rowCount()===1?'recovery':null; + } + + protected function notify(array $account,string $event): void { + if(!(new MfaSecurityNotifications())->send($account,$event))$_SESSION['mfa_notification_warning']=true; + } + + public function verify(int $user,string $code,string $password): bool { + $this->limited($user); + $result=DatabaseTransaction::run($this->connect(),function(PDO $db)use($user,$code,$password){ + $account=$this->account($db,$user,$password);if(!$account)return null; + $factor=$this->factor($db,$user);if(!$factor)return null; + $kind=$this->consume($db,$user,$factor,$code);if($kind===null)return null; + Audit::required($db,$user,$kind==='recovery'?'used MFA recovery code':'verified authenticator'); + return ['account'=>$account,'kind'=>$kind]; + }); + if(!$result)return false; + if($result['kind']==='recovery')$this->notify($result['account'],'recovery_used'); + return true; + } + + private function recoveryCodes(PDO $db,int $user): array { + $stmt=$db->prepare('DELETE FROM mfa_recovery WHERE user_serial=?');$stmt->execute([$user]); + $stmt=$db->prepare('INSERT INTO mfa_recovery(user_serial,code_hash) VALUES(?,?)');$codes=[]; + for($i=0;$i<10;$i++){$code=bin2hex(random_bytes(16));$codes[]=$code;$stmt->execute([$user,hash('sha256',$code)]);} + return $codes; + } + + public function enroll(int $user,string $secret,string $code,string $password): array { + $this->limited($user);$pending=$_SESSION['mfa_pending']??[]; + if(($pending['user']??0)!==$user||($pending['expires']??0)connect(),function(PDO $db)use($user,$secret,$counter,$password){ + $account=$this->account($db,$user,$password);if(!$account)throw new AppException('Current password is incorrect or your session has expired.',403); + if($this->factor($db,$user))throw new AppException('Authenticator is already enrolled.',409); + $stmt=$db->prepare('INSERT INTO user_mfa(user_serial,secret_cipher,last_counter) VALUES(?,?,?)');$stmt->execute([$user,$this->sealSecret($secret,$user),$counter]); + $codes=$this->recoveryCodes($db,$user); + $stmt=$db->prepare('UPDATE users SET user_auth_version=user_auth_version+1 WHERE user_serial=?');$stmt->execute([$user]); + Audit::required($db,$user,'enrolled authenticator');return ['codes'=>$codes,'account'=>$account,'version'=>(int)$account['user_auth_version']+1]; + }); + unset($_SESSION['mfa_pending'],$_SESSION['mfa_replacement']);$_SESSION['auth_version']=$result['version']; + $this->notify($result['account'],'enrolled');return $result['codes']; + } + + /** Prove the old factor, but keep it and the remaining recovery codes active. */ + public function beginReplacement(int $user,string $code,string $password): bool { + $this->limited($user); + $result=DatabaseTransaction::run($this->connect(),function(PDO $db)use($user,$code,$password){ + $account=$this->account($db,$user,$password);if(!$account)return null; + $factor=$this->factor($db,$user);if(!$factor)return null; + $kind=$this->consume($db,$user,$factor,$code);if($kind===null)return null; + if($kind==='recovery')Audit::required($db,$user,'used MFA recovery code'); + Audit::required($db,$user,'requested authenticator replacement'); + return ['account'=>$account,'kind'=>$kind,'factor'=>hash('sha256',$factor['secret_cipher'])]; + }); + if(!$result)return false; + $_SESSION['mfa_replacement']=['user'=>$user,'version'=>(int)$result['account']['user_auth_version'],'factor'=>$result['factor'], + 'secret'=>TOTP::generate(new MfaClock())->getSecret(),'expires'=>time()+600]; + $this->mark($user); + $this->notify($result['account'],$result['kind']==='recovery'?'replacement_started_recovery':'replacement_started');return true; + } + + private function replacement(int $user): ?array { + $pending=$_SESSION['mfa_replacement']??null; + if(!$pending)return null; + if(($pending['user']??0)!==$user||($pending['version']??-1)!==($_SESSION['auth_version']??-2)||($pending['expires']??0)limited($user);$pending=$this->replacement($user); + if(!$pending)throw new AppException('Replacement setup expired. Your existing authenticator is still active.',409); + $counter=self::counter($pending['secret'],trim($code),-1);if($counter===null)throw new AppException('Enter the code from your new authenticator.'); + $result=DatabaseTransaction::run($this->connect(),function(PDO $db)use($user,$password,$pending,$counter){ + $account=$this->account($db,$user,$password);if(!$account)throw new AppException('Current password is incorrect or your session has expired.',403); + $factor=$this->factor($db,$user); + if(!$factor||!hash_equals($pending['factor'],hash('sha256',$factor['secret_cipher'])))throw new AppException('Authenticator changed. Start replacement again.',409); + $stmt=$db->prepare('UPDATE user_mfa SET secret_cipher=?,last_counter=? WHERE user_serial=?');$stmt->execute([$this->sealSecret($pending['secret'],$user),$counter,$user]); + $codes=$this->recoveryCodes($db,$user); + $stmt=$db->prepare('UPDATE users SET user_auth_version=user_auth_version+1 WHERE user_serial=?');$stmt->execute([$user]); + Audit::required($db,$user,'replaced authenticator');return ['codes'=>$codes,'account'=>$account,'version'=>(int)$account['user_auth_version']+1]; + }); + unset($_SESSION['mfa_replacement'],$_SESSION['mfa_pending']);$_SESSION['auth_version']=$result['version'];$this->mark($user); + $this->notify($result['account'],'replaced');return $result['codes']; + } + + private function mark(int $user): void { + session_regenerate_id(true);$_SESSION['mfa_user']=$user;$_SESSION['recent_auth']=time();$_SESSION['csrf_token']=bin2hex(random_bytes(32)); + } + + public function gate(array $user,string $action): bool { + $id=(int)$user['user_serial']; + if($action!=='security'&&(!$this->required($id)||$this->verified($id)))return false; + if(!empty($_SESSION[self::AJAX])&&$action!=='security')throw new AppException('Complete administrator authentication from the home page.',403); + $this->page($user);return true; + } + + public function page(array $user): void { + $id=(int)$user['user_serial'];$error='';$codes=[];$enrolled=$this->enrolled($id); + if(($_SERVER['REQUEST_METHOD']??'GET')==='POST'){ + $this->requireCsrf(); + try{ + $action=$_POST['factor_action']??''; + if($action==='cancelReplacement'){ + unset($_SESSION['mfa_replacement']);header('Location: main.php?Xaction=security',true,303);return; + }elseif($action==='confirmReplacement'){ + $codes=$this->completeReplacement($id,$_POST['mfa_code']??'',$_POST['current_password']??''); + }elseif(!$enrolled){ + $codes=$this->enroll($id,$_SESSION['mfa_pending']['secret']??'',$_POST['mfa_code']??'',$_POST['current_password']??'');$enrolled=true;$this->mark($id); + }elseif($action==='replace'){ + if(!$this->beginReplacement($id,$_POST['mfa_code']??'',$_POST['current_password']??''))throw new AppException('Password or authentication code is incorrect.',403); + header('Location: main.php?Xaction=security',true,303);return; + }else{ + if(!$this->verify($id,$_POST['mfa_code']??'',$_POST['current_password']??''))throw new AppException('Password or authentication code is incorrect.',403); + $this->mark($id);header('Location: main.php',true,303);return; + } + }catch(AppException $errorObject){http_response_code($errorObject->status);$error=$errorObject->getMessage();} + } + $pending=$this->replacement($id);$h=static fn($value)=>htmlspecialchars((string)$value,ENT_QUOTES,'UTF-8'); + $html='

Account security

'.$h($error).'

'.MfaSecurityNotifications::notice(); + if($codes){ + $html.='

Save your recovery codes

These single-use codes are shown only now. Store them securely away from your authenticator. You will need one if your device is lost.

'.implode("\n",$codes).'
I have saved my recovery codes'; + }else{ + if(!$enrolled||$pending){ + if(!$pending){ + $this->key();$initial=$_SESSION['mfa_pending']??[]; + if(($initial['user']??0)!==$id||($initial['expires']??0)$id,'secret'=>TOTP::generate(new MfaClock())->getSecret(),'expires'=>time()+600]; + } + $secret=$pending['secret']??$_SESSION['mfa_pending']['secret'];$qr=MfaSetupQr::dataUri($secret,$user['user_email']); + if($pending)$html.='

Confirm your new authenticator

Your existing authenticator remains active until you confirm this replacement. This setup expires after ten minutes.

'; + $html.='

Scan this QR code with your authenticator app, then enter its six-digit code below.

Scan to set up your authenticator

If you cannot scan it, use this setup key:

'.$h($secret).'

Account: '.$h($user['user_email']).'. Six digits, 30-second period, SHA-1.

'; + }else $html.='

Enter your password and an authenticator code or a single-use recovery code.

'; + $html.='
'; + if($pending)$html.=''; + $html.=''; + if($enrolled&&!$pending)$html.='

Replacement requires your password and a current authenticator or unused recovery code. Your old factor remains active until the new one is confirmed.

'; + $html.='
'; + if($pending)$html.='
'; + } + $this->displayContent($html.'
'); + } + + public function requireRecent(): void { + if(($_SESSION['recent_auth']??0)withIssuer(Base::APPLICATION_NAME)->withLabel($email); + $barcode=new TCPDF2DBarcode($otp->getProvisioningUri(),'QRCODE,M'); + $matrix=$barcode->getBarcodeArray(); + $size=(int)$matrix['num_cols'];$height=(int)$matrix['num_rows']; + if($size<1||$height!==$size)throw new RuntimeException('Cannot generate authenticator QR code.'); + // A four-module white quiet zone keeps the image scannable on dark pages. + $edge=$size+8;$path=''; + for($y=0;$y<$size;$y++)for($x=0;$x<$size;$x++){ + if($matrix['bcode'][$y][$x])$path.='M'.($x+4).' '.($y+4).'h1v1h-1z'; + } + $svg=''; + return 'data:image/svg+xml;base64,'.base64_encode($svg); + } +} diff --git a/classes/Popovers.php b/classes/Popovers.php index 62b2845..ad328da 100644 --- a/classes/Popovers.php +++ b/classes/Popovers.php @@ -51,10 +51,8 @@ class Popovers extends Base { case "add": - $popover_name = filter_input(INPUT_POST, "popover_name") ?: ""; - $popover_title = filter_input(INPUT_POST, "popover_title") ?: ""; - $popover_placeholder = filter_input(INPUT_POST, "popover_placeholder") ?: ""; - $popover_text = filter_input(INPUT_POST, "popover_text") ?: ""; + $data=MaintenanceValidation::popover($_POST); + $popover_name=$data['name'];$popover_title=$data['title'];$popover_placeholder=$data['placeholder'];$popover_text=$data['text']; $SQL = "insert into popovers @@ -97,7 +95,7 @@ class Popovers extends Base { public function deletePopover() { - $popover_serial = filter_input(INPUT_POST, "popover_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0; + $popover_serial = MaintenanceService::id($_POST['popover_serial']??null); $popover = $this->getPopover($popover_serial); @@ -123,7 +121,7 @@ class Popovers extends Base { case "prompt": - $popover_serial = filter_input(INPUT_POST, "popover_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0; + $popover_serial = MaintenanceService::id($_POST['popover_serial']??null); $popover = $this->getPopover($popover_serial); @@ -141,11 +139,9 @@ class Popovers extends Base { case "update": - $popover_serial = filter_input(INPUT_POST, "popover_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0; - $popover_name = filter_input(INPUT_POST, "popover_name") ?: ""; - $popover_title = filter_input(INPUT_POST, "popover_title") ?: ""; - $popover_placeholder = filter_input(INPUT_POST, "popover_placeholder") ?: ""; - $popover_text = filter_input(INPUT_POST, "popover_text") ?: ""; + $popover_serial = MaintenanceService::id($_POST['popover_serial']??null); + $data=MaintenanceValidation::popover($_POST); + $popover_name=$data['name'];$popover_title=$data['title'];$popover_placeholder=$data['placeholder'];$popover_text=$data['text']; $popover = $this->getPopover($popover_serial); @@ -187,6 +183,7 @@ class Popovers extends Base { // ======================= public function getPopover($popover_serial = 0) { + $popover_serial=MaintenanceService::id($popover_serial); $SQL = "select view_popovers.* from view_popovers @@ -299,7 +296,8 @@ class Popovers extends Base { public function popoverExists() { - $popover_serial = filter_input(INPUT_POST, "popover_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0; + $popover_serial = filter_var($_POST['popover_serial']??0,FILTER_VALIDATE_INT,['options'=>['min_range'=>0]]); + if($popover_serial===false)throw new AppException('Invalid popover ID.'); $popover_name = filter_input(INPUT_POST, "popover_name") ?: ""; $popover_name = strtolower($popover_name); diff --git a/classes/Roster.php b/classes/Roster.php index 7d28818..2646070 100644 --- a/classes/Roster.php +++ b/classes/Roster.php @@ -9,33 +9,48 @@ class Roster extends Base { return '
'; } public function help(): void { - $this->displayContent('

Using your club workspace

Open Clubs and dues to view clubs assigned to your account. Club rosters and your season dues are available inside each club.

Site administrators create clubs, assign existing accounts, add seasons, and record dues and received payments. Contact your club administrator for membership or account assistance.

'); + $this->displayContent('

Using your club workspace

Open Clubs and dues to view clubs assigned to your account. Club rosters and your season dues are available inside each club.

Your Super System Administrator creates clubs and assigns club administrators. Club administrators invite members, add seasons, record dues and payments, and answer tickets only in their clubs. Members can view club information and their own dues, and submit tickets. Accept invitations through Invitations after verifying your email.

'); } public function home(): void { - $service=new RosterService();$html='

Club workspace

Club access requires a verified email. Verify your email or request another link.

'; + $service=new RosterService();$html='

Club workspace

Account security and authenticator recovery

Club access requires a verified email. Verify your email or request another link.

'; if(!$service->ready()){ $html.=$service->administrator()?'

Club setup is ready to install. Run the database migrations described in PRODUCTION-FIXES.md.

':'

Your club workspace is being prepared. Please contact the site administrator.

'; }else{ - $clubs=$service->clubs(); + $clubs=$service->clubs(BoundedList::page('clubs')); + if((BoundedList::$pages['clubs']['count']??0)===1 && $clubs){ + header('Location: main.php?Xaction=Roster.workspace&club_serial='.(int)$clubs[0]['club_serial'],true,303); + return; + } if(!$clubs)$html.='

You are not assigned to an active club yet. A site administrator can create clubs and assign memberships.

'; - foreach($clubs as $club)$html.='

'.self::h($club['club_name']).'

'.self::h(ucfirst($club['club_status'])).'

Open club
'; + $html.='
'; + foreach($clubs as $club)$html.='

'.self::h($club['club_name']).'

'.self::h(ucfirst($club['club_status'])).'

Open club
'; + $html.='
'.BoundedList::navigation('clubs','displayHome'); $html.=''.($service->administrator()?'Manage clubs and memberships':'View my clubs and dues').''; } - $this->displayContent($html.'
'); + $this->displayContent($html.MfaSecurityNotifications::notice().'
'); } private function financialHistory(int $club,bool $active,bool $admin): string { - $history=(new LedgerService())->history($club);$html='

Payment history

'; + $history=(new LedgerService())->history($club,BoundedList::page('payments'),BoundedList::page('adjustments'));$html='

Payment history

'; if($admin)$html.='
'; - $html.='
'; + $html.='
PaymentMemberDateAmountMethod / referenceRecorded byStatus
'; foreach($history['payments'] as $p){ $html.=''; } - $html.='
PaymentMemberDateAmountMethod / referenceRecorded byStatus
#'.(int)$p['payment_serial'].''.self::h($p['member_name']).''.self::h($p['paid_on']).'$'.number_format($p['amount_cents']/100,2).''.self::h($p['payment_method'].' '.$p['payment_reference']).''.self::h($p['actor']??'Historical record').''; if($p['reversal_serial'])$html.='Reversed: '.self::h($p['reversal_reason'].' by '.$p['reversal_actor'].' on '.$p['reversed_at']); elseif($admin&&$active)$html.='
Reverse incorrect payment

This preserves the original entry and restores the amount owed. It does not send a refund.

'.$this->form('reverse',$club).''.self::field('reason','Reversal reason','text','',500).'
'; else $html.='Received';$html.='

Dues correction history

    '; + $html.=''.BoundedList::navigation('payments').'

    Dues correction history

      '; foreach($history['adjustments'] as $a)$html.='
    • '.self::h($a['member_name']).': $'.number_format($a['amount_cents']/100,2).' adjustment; corrected total $'.number_format($a['corrected_amount_cents']/100,2).' — '.self::h($a['reason'].' ('.$a['actor'].', '.$a['created_at'].')').'
    • '; - return $html.'
    '; + return $html.'
'.BoundedList::navigation('adjustments'); + } + public function createClub(): void { + (new TenantAccess())->requireSuper();$service=new RosterService(); + if(($_SERVER['REQUEST_METHOD']??'GET')==='POST'){ + $this->requireCsrf();$club=$service->saveClub(0,$_POST['club_name']??''); + $_SESSION['roster_notice']='Club created.';header('Location: main.php?Xaction=Roster.workspace&club_serial='.$club,true,303);return; + } + $form=str_replace('value="Roster.workspace"','value="Roster.createClub"',$this->form('club')); + $this->displayContent('

Create club

Create a separate club, then assign its administrator from the club roster.

'.$form.self::field('club_name','Club name').'
Back to clubs
'); } public function workspace(): void { $service=new RosterService();if(!$service->ready()){$this->home();return;} @@ -44,7 +59,9 @@ class Roster extends Base { $service->requireAdministrator();$this->requireCsrf(); switch($_POST['step']){ case 'club':$club=$service->saveClub($club,$_POST['club_name']??'',$_POST['club_status']??'active');break; - case 'member':$service->saveMember($club,empty($_POST['membership_serial'])?0:MaintenanceService::id($_POST['membership_serial']),$_POST['identifier']??'',$_POST['membership_status']??'active',$_POST['joined_on']??'');break; + case 'member':$service->saveMember($club,empty($_POST['membership_serial'])?0:MaintenanceService::id($_POST['membership_serial']),$_POST['identifier']??'',$_POST['membership_status']??'active',$_POST['joined_on']??'',$_POST['membership_role']??'member');break; + case 'invite':$result=(new ClubInvitations())->invite($club,$_POST['invite_email']??'',$_POST['membership_role']??'member');$_SESSION['club_notice']=$result['message'].' '.$result['warning'];break; + case 'revokeInvitation':(new ClubInvitations())->revoke($club,MaintenanceService::id($_POST['invitation_serial']??null));$_SESSION['club_notice']='Invitation revoked.';break; case 'season':$service->addSeason($club,$_POST['season_name']??'',$_POST['starts_on']??'',$_POST['ends_on']??'');break; case 'charge':$service->charge($club,MaintenanceService::id($_POST['membership_serial']??null),MaintenanceService::id($_POST['season_serial']??null),$_POST['amount']??'');break; case 'payment':$service->payment($club,MaintenanceService::id($_POST['due_serial']??null),$_POST['amount']??'',$_POST['paid_on']??'',$_POST['request_key']??'',$_POST['payment_method']??'unspecified',$_POST['payment_reference']??'');break; @@ -52,45 +69,99 @@ class Roster extends Base { case 'reverse':(new LedgerService())->reverse($club,MaintenanceService::id($_POST['payment_serial']??null),$_POST['reason']??'',$_POST['request_key']??'');break; default:throw new AppException('Unknown club action.'); } - $_SESSION['roster_notice']='Changes saved.';header('Location: main.php?Xaction=Roster.workspace&club_serial='.$club,true,303);exit; + $_SESSION['roster_notice']='Changes saved.'; + $redirect='main.php?Xaction=Roster.workspace&club_serial='.$club; + if(($_SESSION[self::AJAX]??false)&&($_SERVER['HTTP_X_HCR_MODAL']??'')==='1'){ + header('Content-Type: application/json');echo json_encode(['ok'=>true,'redirect'=>$redirect]);return; + } + header('Location: '.$redirect,true,303);exit; } - $html='

Clubs and memberships

'; - if(!empty($_SESSION['roster_notice'])){$html.='

'.self::h($_SESSION['roster_notice']).'

';unset($_SESSION['roster_notice']);} - $clubs=$service->clubs();$html.=''; - if($service->administrator())$html.='

Create club

'.$this->form('club').self::field('club_name','Club name').'
'; + $clubs=$service->clubs(BoundedList::page('clubs')); if(!$club && $clubs)$club=(int)$clubs[0]['club_serial']; - if(!$club){$this->displayContent($html.'

No clubs are available.

');return;} - $selected=$service->club($club);$members=$service->members($club);$seasons=$service->seasons($club);$dues=$service->dues($club); - $html.='

'.self::h($selected['club_name']).'

'; - if($service->administrator()){ - $html.='
Edit or archive club'.$this->form('club',$club).self::field('club_name','Club name','text',$selected['club_name']).'
'; + if(!$club){$this->displayContent('

Clubs and memberships

No clubs are available. Accept an invitation to join your club.

View invitations
');return;} + $selected=$service->club($club);$manage=$service->manages($club);$super=(new TenantAccess())->isSuper();$members=$service->members($club,BoundedList::page('members'));$seasons=$service->seasons($club,BoundedList::page('seasons'));$dues=$service->dues($club,BoundedList::page('dues')); + $html='

'.self::h($selected['club_name']).'

Club status: '.self::h(ucfirst($selected['club_status'])).' · '.($super?'Super System Administrator':($manage?'Club administrator':'Member')).'

'.($manage?'Manage your club roster, invitations, seasons and dues.':'View your membership, season dues and payment history.').'

')); + } + public function invitations(): void { + if(!(new RosterService())->ready()){$this->home();return;} + $service=new ClubInvitations(); + if(($_POST['step']??'')==='accept'){$service->accept(MaintenanceService::id($_POST['invitation_serial']??null));header('Location: main.php?Xaction=Roster.workspace',true,303);exit;} + $html='

Club invitations

Sign in using the invited email and verify it before accepting. Club invitations never change your account password or other club memberships.

'; + $pending=$service->pending(BoundedList::page('pending')); + foreach($pending as $invite)$html.='

'.self::h($invite['club_name']).'

Club role: '.self::h($invite['membership_role']).'; expires '.self::h($invite['expires_at']).' UTC.

'.str_replace('Roster.workspace','Roster.invitations',$this->form('accept')).'
'; + if(!$pending)$html.='

No pending invitations for your current email.

'; + $html.=BoundedList::navigation('pending'); + $this->displayContent($html.'
'); + } + public function tickets(): void { + $service=new ClubTickets();if(!$service->ready()){$this->home();return;} + $clubs=$service->clubs(BoundedList::page('clubs'));$raw=$_POST['club_serial']??$_GET['club_serial']??'';$club=$raw===''?($clubs?(int)$clubs[0]['club_serial']:0):MaintenanceService::id($raw); + $html='

Club tickets

'.BoundedList::navigation('clubs'); + if(!$club){$this->displayContent($html.'

Accept a club invitation to submit a ticket.

');return;} + $selected=$service->club($club);$manage=$service->manages($club);$raw=$_POST['ticket_serial']??$_GET['ticket_serial']??'';$ticket=$raw===''?0:MaintenanceService::id($raw); + $page=filter_var($_POST['ticket_page']??$_GET['ticket_page']??'1',FILTER_VALIDATE_INT,['options'=>['min_range'=>1]]); + if($page===false)throw new AppException('Choose a valid ticket page.'); + $search=$service->normalizeSearch($_POST['ticket_search']??$_GET['ticket_search']??''); + if(($_POST['step']??'')==='openTicket')$ticket=$service->createTicket($club,$_POST['subject']??'',$_POST['message']??''); + elseif(($_POST['step']??'')==='reply')$service->reply($club,$ticket,$_POST['message']??'',$_POST['ticket_status']??''); + if(($_POST['step']??'')!==''){if(!in_array($_POST['step'],['openTicket','reply'],true))throw new AppException('Unknown ticket action.');header('Location: main.php?Xaction=Roster.tickets&club_serial='.$club.'&ticket_serial='.$ticket.($_POST['step']==='reply'?'&ticket_page='.$page.'&ticket_search='.rawurlencode($search):''),true,303);exit;} + $listing=$service->page($club,$page,$search);$page=$listing['page']; + $ticketUrl=static fn(int $target)=>'main.php?'.http_build_query(['Xaction'=>'Roster.tickets','club_serial'=>$club,'ticket_page'=>$target,'ticket_search'=>$search],'','&',PHP_QUERY_RFC3986); + $html.='

'.self::h($selected['club_name']).'

'.($manage?'Tickets from this club.':'Only your own tickets are shown.').'

'; + $html.='
Clear search
'; + $html.='

Tickets '.$listing['start'].'-'.$listing['end'].' of '.$listing['count'].'. Page '.$page.' of '.$listing['pages'].'.

'; + if($ticket){$row=$service->ticket($club,$ticket);$html.='

'.self::h($row['subject']).'

Status: '.self::h($row['ticket_status']).'

';foreach($service->messages($club,$ticket,BoundedList::page('messages')) as $message)$html.='

'.self::h($message['user_first_name'].' '.$message['user_last_name'].' — '.$message['created_at']).'

'.nl2br(self::h($message['message_text'])).'

'; + $html.=BoundedList::navigation('messages'); + if($selected['club_status']==='active'&&($manage||$row['ticket_status']==='open')){$html.=str_replace('Roster.workspace','Roster.tickets',$this->form('reply',$club)).'';if($manage)$html.='';$html.='';} + } + if($selected['club_status']==='active')$html.='

Submit a ticket

'.str_replace('Roster.workspace','Roster.tickets',$this->form('openTicket',$club)).str_replace('name="subject"','name="subject" data-character-limit="'.ClubTickets::SUBJECT_LIMIT.'"',self::field('subject','Subject','text','',ClubTickets::SUBJECT_LIMIT*2)).''; + $html.=''; $this->displayContent($html.''); } } diff --git a/classes/RosterReports.php b/classes/RosterReports.php index 0c90ca3..dd6ce14 100644 --- a/classes/RosterReports.php +++ b/classes/RosterReports.php @@ -3,9 +3,18 @@ use PhpOffice\PhpSpreadsheet\Spreadsheet; use PhpOffice\PhpSpreadsheet\Writer\Xlsx; use PhpOffice\PhpSpreadsheet\Cell\DataType; class RosterReports extends Base { + private function exportBudget(int $club,bool $financial=false): void { + (new TenantAccess())->requireManager($club); + (new ClubResources())->consume($club,'export'); + $db=$this->connect(); + if($financial){ + BoundedList::exportGuard($db,'SELECT (SELECT COUNT(*) FROM club_dues WHERE club_serial=?)+(SELECT COUNT(*) FROM club_payments p JOIN club_dues d ON d.due_serial=p.due_serial WHERE d.club_serial=?)+(SELECT COUNT(*) FROM club_due_adjustments a JOIN club_dues d ON d.due_serial=a.due_serial WHERE d.club_serial=?)',[$club,$club,$club]); + }else BoundedList::exportGuard($db,'SELECT COUNT(*) FROM club_memberships WHERE club_serial=?',[$club]); + BoundedList::$exporting=true; + } public function ledger(): void { - $service=new RosterService();$service->requireAdministrator();$club=MaintenanceService::id($_POST['club_serial']??null);$name=$service->club($club)['club_name']; - $history=(new LedgerService())->history($club);header('Content-Type: text/csv; charset=UTF-8');header('Content-Disposition: attachment; filename="club-financial-history.csv"');$file=fopen('php://output','w'); + $service=new RosterService();$service->requireAdministrator();$club=MaintenanceService::id($_POST['club_serial']??null);(new TenantAccess())->requireManager($club);$name=$service->club($club)['club_name']; + $this->exportBudget($club,true);$history=(new LedgerService())->history($club);header('Content-Type: text/csv; charset=UTF-8');header('Content-Disposition: attachment; filename="club-financial-history.csv"');$file=fopen('php://output','w'); $write=static function(array $row)use($file){fputcsv($file,array_map(static fn($v)=>self::csvText((string)$v),$row),',','"','');}; $write(['Record type','Club','Record ID','Dues ID','Member','Amount cents (USD)','Date','Method','Reference','Recorded by','Status / reason']); foreach($service->dues($club) as $due)$write(['dues_total',$name,$due['due_serial'],$due['due_serial'],$due['user_first_name'].' '.$due['user_last_name'],$due['amount_cents'],'','','',$due['recorded_by']??'Historical','Paid cents '.$due['paid_cents'].'; balance cents '.($due['amount_cents']-$due['paid_cents'])]); @@ -14,7 +23,7 @@ class RosterReports extends Base { fclose($file);exit; } private function rows(): array { - $service=new RosterService();$service->requireAdministrator();$id=MaintenanceService::id($_POST['club_serial']??null);$club=$service->club($id); + $service=new RosterService();$service->requireAdministrator();$id=MaintenanceService::id($_POST['club_serial']??null);(new TenantAccess())->requireManager($id);$club=$service->club($id);$this->exportBudget($id); $rows=[['Club','Username','First name','Last name','Email','Membership','Joined on']]; foreach($service->members($id) as $member)$rows[]=[$club['club_name'],$member['user_name'],$member['user_first_name'],$member['user_last_name'],$member['user_email'],$member['membership_status'],$member['joined_on']]; return $rows; @@ -37,7 +46,7 @@ class RosterReports extends Base { public function catalog(): void { $service=new RosterService();$service->requireAdministrator();$html='

Roster reports

'; if(!$service->ready()){$this->displayContent($html.'

Install the roster migration before exporting reports.

');return;} - foreach($service->clubs() as $club){$html.='

'.htmlspecialchars($club['club_name'],ENT_QUOTES,'UTF-8').'

';foreach(['csv'=>'CSV','excel'=>'Excel','pdf'=>'PDF'] as $method=>$label)$html.='
';$html.='
';} - $this->displayContent($html.''); + foreach($service->clubs(BoundedList::page('clubs'),true) as $club){if(!$service->manages((int)$club['club_serial']))continue;$html.='

'.htmlspecialchars($club['club_name'],ENT_QUOTES,'UTF-8').'

';foreach(['csv'=>'CSV','excel'=>'Excel','pdf'=>'PDF'] as $method=>$label)$html.='
';$html.='
';} + $this->displayContent($html.BoundedList::navigation('clubs','RosterReports.catalog').''); } } diff --git a/classes/RosterService.php b/classes/RosterService.php index d39e9ef..a09e1d3 100644 --- a/classes/RosterService.php +++ b/classes/RosterService.php @@ -1,31 +1,43 @@ administrator())throw new AppException('Only site administrators may manage clubs and dues.',403);} - public function ready(): bool {return (int)$this->connect()->query("SELECT COUNT(*) FROM information_schema.TABLES WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME IN ('clubs','club_memberships','club_seasons','club_dues','club_payments','club_due_adjustments','club_payment_reversals','email_verifications')")->fetchColumn()===8;} - public function clubs(): array { + public function administrator(): bool {return (new TenantAccess())->managesAny();} + public function requireAdministrator(): void {if(!$this->administrator())throw new AppException('Only assigned club administrators may manage clubs and dues.',403);} + public function manages(int $club,?PDO $db=null): bool {return (new TenantAccess())->canManage($club,$db);} + public function ready(): bool {return (int)$this->connect()->query("SELECT COUNT(*) FROM information_schema.TABLES WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME IN ('clubs','club_memberships','club_seasons','club_dues','club_payments','club_due_adjustments','club_payment_reversals','email_verifications','club_invitations','club_tickets','club_ticket_messages')")->fetchColumn()===11 && (new TenantAccess())->available();} + public function clubs(?int $page=null,bool $managedOnly=false): array { $db=$this->connect(); - if($this->administrator())return $db->query('SELECT * FROM clubs ORDER BY club_name,club_serial')->fetchAll(); - $stmt=$db->prepare("SELECT c.* FROM clubs c JOIN club_memberships m ON m.club_serial=c.club_serial JOIN users u ON u.user_serial=m.user_serial WHERE m.user_serial=? AND m.membership_status='active' AND c.club_status='active' AND u.user_status='active' AND u.user_email_verified_at IS NOT NULL ORDER BY c.club_name,c.club_serial"); - $stmt->execute([$_SESSION[self::USER_SERIAL]??0]);return $stmt->fetchAll(); + if((new TenantAccess())->isSuper($db))return BoundedList::rows($db,'SELECT * FROM clubs ORDER BY club_name,club_serial',[],$page,'clubs'); + return BoundedList::rows($db,"SELECT c.* FROM clubs c JOIN club_memberships m ON m.club_serial=c.club_serial JOIN users u ON u.user_serial=m.user_serial WHERE m.user_serial=? AND m.membership_status='active' AND (c.club_status='active' OR m.membership_role='administrator') AND u.user_status='active' AND u.user_email_verified_at IS NOT NULL".($managedOnly?" AND m.membership_role='administrator'":'')." ORDER BY c.club_name,c.club_serial",[$_SESSION[self::USER_SERIAL]??0],$page,'clubs'); } public function club(int $id,?PDO $db=null,bool $writing=false): array { $db??=$this->connect();$stmt=$db->prepare('SELECT * FROM clubs WHERE club_serial=?'.($writing?' FOR UPDATE':''));$stmt->execute([$id]);$club=$stmt->fetch(); if(!$club)throw new AppException('Club not found.',404); - if(!$this->administrator()){ - $stmt=$db->prepare("SELECT m.membership_serial FROM club_memberships m JOIN users u ON u.user_serial=m.user_serial WHERE m.club_serial=? AND m.user_serial=? AND m.membership_status='active' AND u.user_status='active' AND u.user_email_verified_at IS NOT NULL");$stmt->execute([$id,$_SESSION[self::USER_SERIAL]??0]); + if(!$this->manages($id,$db)){ + if($writing)throw new AppException('You cannot manage this club.',403); + $stmt=$db->prepare("SELECT m.membership_serial FROM club_memberships m JOIN users u ON u.user_serial=m.user_serial WHERE m.club_serial=? AND m.user_serial=? AND m.membership_status='active' AND u.user_status='active' AND u.user_email_verified_at IS NOT NULL LOCK IN SHARE MODE");$stmt->execute([$id,$_SESSION[self::USER_SERIAL]??0]); if($club['club_status']!=='active'||!$stmt->fetch())throw new AppException('You do not have access to this club.',403); } if($writing && $club['club_status']!=='active')throw new AppException('Reactivate the club before adding or changing records.',409); return $club; } - public function members(int $club): array { - $this->club($club);$stmt=$this->connect()->prepare("SELECT m.*,u.user_name,u.user_first_name,u.user_last_name,u.user_email FROM club_memberships m JOIN users u ON u.user_serial=m.user_serial WHERE m.club_serial=?".($this->administrator()?'':" AND m.membership_status='active'").' ORDER BY u.user_last_name,u.user_first_name,m.membership_serial');$stmt->execute([$club]);return $stmt->fetchAll(); + public function members(int $club,?int $page=null): array { + $this->club($club);$manage=$this->manages($club); + return BoundedList::rows($this->connect(),"SELECT m.*,u.user_name,u.user_first_name,u.user_last_name,u.user_email FROM club_memberships m JOIN users u ON u.user_serial=m.user_serial WHERE m.club_serial=?".($manage?'':" AND m.user_serial=? AND m.membership_status='active'").' ORDER BY u.user_last_name,u.user_first_name,m.membership_serial',$manage?[$club]:[$club,$_SESSION[self::USER_SERIAL]??0],$page,'members'); } - public function seasons(int $club): array {$this->club($club);$stmt=$this->connect()->prepare('SELECT * FROM club_seasons WHERE club_serial=? ORDER BY starts_on DESC,season_serial DESC');$stmt->execute([$club]);return $stmt->fetchAll();} - public function dues(int $club): array { - $this->club($club);$stmt=$this->connect()->prepare('SELECT d.*,d.amount_cents AS original_amount_cents,d.amount_cents+COALESCE((SELECT SUM(a.amount_cents) FROM club_due_adjustments a WHERE a.due_serial=d.due_serial),0) AS amount_cents,s.season_name,u.user_first_name,u.user_last_name,COALESCE((SELECT SUM(p.amount_cents) FROM club_payments p WHERE p.due_serial=d.due_serial AND NOT EXISTS(SELECT 1 FROM club_payment_reversals r WHERE r.payment_serial=p.payment_serial)),0) AS paid_cents FROM club_dues d JOIN club_memberships m ON m.membership_serial=d.membership_serial JOIN users u ON u.user_serial=m.user_serial JOIN club_seasons s ON s.season_serial=d.season_serial WHERE d.club_serial=?'.($this->administrator()?'':' AND m.user_serial=?').' ORDER BY s.starts_on DESC,u.user_last_name,d.due_serial'); - $stmt->execute($this->administrator()?[$club]:[$club,$_SESSION[self::USER_SERIAL]??0]);return $stmt->fetchAll(); + public function seasons(int $club,?int $page=null): array { + $this->club($club);return BoundedList::rows($this->connect(),'SELECT * FROM club_seasons WHERE club_serial=? ORDER BY starts_on DESC,season_serial DESC',[$club],$page,'seasons'); + } + public function member(int $club,int $membership): array { + $this->club($club);$manage=$this->manages($club); + $stmt=$this->connect()->prepare('SELECT m.*,u.user_name,u.user_first_name,u.user_last_name,u.user_email FROM club_memberships m JOIN users u ON u.user_serial=m.user_serial WHERE m.club_serial=? AND m.membership_serial=?'.($manage?'':" AND m.user_serial=? AND m.membership_status='active'")); + $stmt->execute($manage?[$club,$membership]:[$club,$membership,$_SESSION[self::USER_SERIAL]??0]); + $member=$stmt->fetch();if(!$member)throw new AppException('Membership not found in this club.',404);return $member; + } + public function dues(int $club,?int $page=null,?int $membership=null): array { + $this->club($club);$manage=$this->manages($club); + if($membership!==null)$this->member($club,$membership); + $args=$manage?[$club]:[$club,$_SESSION[self::USER_SERIAL]??0];if($membership!==null)$args[]=$membership; + return BoundedList::rows($this->connect(),'SELECT d.due_serial,d.club_serial,d.membership_serial,d.season_serial,d.created_at,d.recorded_by,d.amount_cents AS original_amount_cents,d.amount_cents+COALESCE((SELECT SUM(a.amount_cents) FROM club_due_adjustments a WHERE a.due_serial=d.due_serial),0) AS amount_cents,s.season_name,u.user_first_name,u.user_last_name,COALESCE((SELECT SUM(p.amount_cents) FROM club_payments p WHERE p.due_serial=d.due_serial AND NOT EXISTS(SELECT 1 FROM club_payment_reversals r WHERE r.payment_serial=p.payment_serial)),0) AS paid_cents FROM club_dues d JOIN club_memberships m ON m.membership_serial=d.membership_serial JOIN users u ON u.user_serial=m.user_serial JOIN club_seasons s ON s.season_serial=d.season_serial WHERE d.club_serial=?'.($manage?'':' AND m.user_serial=?').($membership===null?'':' AND d.membership_serial=?').' ORDER BY s.starts_on DESC,u.user_last_name,d.due_serial',$args,$page,'dues'); } private function text(string $text,int $limit): string {$text=trim($text);if(!$text||strlen($text)>$limit)throw new AppException('A name is required and must fit the displayed length limit.');return $text;} public static function date(string $value): string {$date=DateTime::createFromFormat('!Y-m-d',$value);if(!$date||$date->format('Y-m-d')!==$value)throw new AppException('Enter a valid date in YYYY-MM-DD format.');return $value;} @@ -34,36 +46,42 @@ class RosterService extends Base { [$whole,$fraction]=array_pad(explode('.',$value,2),2,'');return (int)$whole*100+(int)str_pad($fraction,2,'0'); } public function saveClub(int $id,string $name,string $status='active'): int { - $this->requireAdministrator();$name=$this->text($name,128);if(!in_array($status,['active','archived'],true))throw new AppException('Invalid club status.'); - $db=$this->connect();$db->beginTransaction(); - try { + if(!$id)(new TenantAccess())->requireSuper();else (new TenantAccess())->requireManager($id);$name=$this->text($name,128);if(!in_array($status,['active','archived'],true))throw new AppException('Invalid club status.'); + $db=$this->connect(); + $id=DatabaseTransaction::run($db,function(PDO $db)use($id,$name,$status){ + if(!$id)(new TenantAccess())->requireSuper($db); $before=null;if($id){$stmt=$db->prepare('SELECT * FROM clubs WHERE club_serial=? FOR UPDATE');$stmt->execute([$id]);$before=$stmt->fetch();if(!$before)throw new AppException('Club not found.',404);} + if($id)(new TenantAccess())->requireManager($id,$db); if($id){$stmt=$db->prepare('UPDATE clubs SET club_name=?,club_status=? WHERE club_serial=?');$stmt->execute([$name,$status,$id]);} else{$stmt=$db->prepare('INSERT INTO clubs(club_name,club_status) VALUES(?,?)');$stmt->execute([$name,$status]);$id=(int)$db->lastInsertId();} - Audit::required($db,(int)($_SESSION[self::USER_SERIAL]??0),'saved club '.json_encode(['club'=>$id,'before'=>$before,'name'=>$name,'status'=>$status]));$db->commit(); - }catch(Throwable $e){if($db->inTransaction())$db->rollBack();throw $e;} + Audit::required($db,(int)($_SESSION[self::USER_SERIAL]??0),'saved club '.json_encode(['club'=>$id,'before'=>$before,'name'=>$name,'status'=>$status]));return $id; + }); return $id; } - public function saveMember(int $club,int $membership,string $identifier,string $status,string $joined): void { - $this->requireAdministrator();$joined=self::date($joined);if(!in_array($status,['active','inactive'],true))throw new AppException('Invalid membership status.'); - $db=$this->connect();$db->beginTransaction(); - try{ + public function saveMember(int $club,int $membership,string $identifier,string $status,string $joined,string $memberRole='member'): void { + $this->requireAdministrator();(new TenantAccess())->requireManager($club);$joined=self::date($joined);if(!in_array($memberRole,['member','administrator'],true))throw new AppException('Invalid membership role.');if(!in_array($status,['active','inactive'],true))throw new AppException('Invalid membership status.'); + $db=$this->connect(); + DatabaseTransaction::run($db,function(PDO $db)use($club,$membership,$identifier,$status,$joined,$memberRole){ // Lock user before membership writes, matching account deletion's lock order. if($membership){$stmt=$db->prepare('SELECT user_serial FROM club_memberships WHERE membership_serial=? AND club_serial=?');$stmt->execute([$membership,$club]);$user=$stmt->fetchColumn();if(!$user)throw new AppException('Membership not found in this club.',404);} - else{$stmt=$db->prepare('SELECT user_serial FROM users WHERE user_name=? OR user_email=?');$stmt->execute([trim($identifier),trim($identifier)]);$user=$stmt->fetchColumn();if(!$user)throw new AppException('No account matches that username or email. Create the account first.',404);} + else{(new TenantAccess())->requireSuper($db);$stmt=$db->prepare('SELECT user_serial FROM users WHERE user_name=? OR user_email=?');$stmt->execute([trim($identifier),trim($identifier)]);$user=$stmt->fetchColumn();if(!$user)throw new AppException('No account matches that username or email. Create the account first.',404);} $stmt=$db->prepare('SELECT user_serial,user_status,user_email_verified_at FROM users WHERE user_serial=? FOR UPDATE');$stmt->execute([$user]);if(!($account=$stmt->fetch()))throw new AppException('Account not found.',404); if($status==='active' && ($account['user_status']!=='active'||!$account['user_email_verified_at']))throw new AppException('The account must be active and its email verified before membership can be activated.',409); $this->club($club,$db,true); $before=null;if($membership){$stmt=$db->prepare('SELECT * FROM club_memberships WHERE membership_serial=? AND club_serial=? FOR UPDATE');$stmt->execute([$membership,$club]);$before=$stmt->fetch();if(!$before)throw new AppException('Membership not found.',404);} - if($membership){$stmt=$db->prepare('UPDATE club_memberships SET membership_status=?,joined_on=? WHERE membership_serial=? AND club_serial=?');$stmt->execute([$status,$joined,$membership,$club]);} - else{$stmt=$db->prepare('INSERT INTO club_memberships(club_serial,user_serial,membership_status,joined_on) VALUES(?,?,?,?)');$stmt->execute([$club,$user,$status,$joined]);} - Audit::required($db,(int)($_SESSION[self::USER_SERIAL]??0),'saved membership '.json_encode(['membership'=>$membership?:((int)$db->lastInsertId()),'club'=>$club,'user'=>(int)$user,'before'=>$before,'status'=>$status,'joined_on'=>$joined])); - $db->commit(); - }catch(Throwable $e){if($db->inTransaction())$db->rollBack();throw $e;} + if(!(new TenantAccess())->isSuper($db) && (($before['membership_role']??'member')==='administrator'||$memberRole!=='member'))throw new AppException('Only the Super System Administrator can assign or change club administrators.',403); + if(($before['membership_role']??'')==='administrator' && $before['membership_status']==='active' && ($memberRole!=='administrator'||$status!=='active')){ + $stmt=$db->prepare("SELECT membership_serial FROM club_memberships WHERE club_serial=? AND membership_role='administrator' AND membership_status='active' ORDER BY membership_serial FOR UPDATE");$stmt->execute([$club]);if(count($stmt->fetchAll())<=1)throw new AppException('Assign another club administrator before removing the last one.',409); + } + if($membership){$stmt=$db->prepare('UPDATE club_memberships SET membership_status=?,joined_on=?,membership_role=? WHERE membership_serial=? AND club_serial=?');$stmt->execute([$status,$joined,$memberRole,$membership,$club]);} + else{$stmt=$db->prepare('INSERT INTO club_memberships(club_serial,user_serial,membership_status,joined_on,membership_role) VALUES(?,?,?,?,?)');$stmt->execute([$club,$user,$status,$joined,$memberRole]);$membership=(int)$db->lastInsertId();} + if($status==='inactive'||($before&&$before['membership_role']!==$memberRole)){$stmt=$db->prepare("UPDATE club_invitations SET invitation_status='revoked' WHERE club_serial=? AND invite_email=(SELECT user_email FROM users WHERE user_serial=?) AND invitation_status='pending'");$stmt->execute([$club,$user]);} + Audit::required($db,(int)($_SESSION[self::USER_SERIAL]??0),'saved membership '.json_encode(['membership'=>$membership?:((int)$db->lastInsertId()),'club'=>$club,'user'=>(int)$user,'before'=>$before,'status'=>$status,'membership_role'=>$memberRole,'joined_on'=>$joined])); + }); } public function addSeason(int $club,string $name,string $start,string $end): void { $this->requireAdministrator();$name=$this->text($name,100);self::date($start);self::date($end);if($end<$start)throw new AppException('Season end cannot precede its start.'); - $db=$this->connect();$db->beginTransaction();try{$this->club($club,$db,true);$stmt=$db->prepare('INSERT INTO club_seasons(club_serial,season_name,starts_on,ends_on) VALUES(?,?,?,?)');$stmt->execute([$club,$name,$start,$end]);Audit::required($db,(int)($_SESSION[self::USER_SERIAL]??0),'created season '.json_encode(['season'=>(int)$db->lastInsertId(),'club'=>$club,'name'=>$name,'start'=>$start,'end'=>$end]));$db->commit();}catch(Throwable $e){if($db->inTransaction())$db->rollBack();throw $e;} + $db=$this->connect();DatabaseTransaction::run($db,function(PDO $db)use($club,$name,$start,$end){$this->club($club,$db,true);$stmt=$db->prepare('INSERT INTO club_seasons(club_serial,season_name,starts_on,ends_on) VALUES(?,?,?,?)');$stmt->execute([$club,$name,$start,$end]);Audit::required($db,(int)($_SESSION[self::USER_SERIAL]??0),'created season '.json_encode(['season'=>(int)$db->lastInsertId(),'club'=>$club,'name'=>$name,'start'=>$start,'end'=>$end]));}); } public function charge(int $club,int $membership,int $season,string $amount): void {(new LedgerService())->charge($club,$membership,$season,$amount);} public function payment(int $club,int $due,string $amount,string $paid,string $key,string $method='unspecified',string $reference=''): void {(new LedgerService())->payment($club,$due,$amount,$paid,$key,$method,$reference);} diff --git a/classes/SignUp.php b/classes/SignUp.php index d482bfe..b8931ed 100644 --- a/classes/SignUp.php +++ b/classes/SignUp.php @@ -3,7 +3,8 @@ class SignUp extends Base { public function createAccount() { - $params = ['BTN_SUBMIT' => 'main.php', 'REGISTER_ACTION' => 'SignUp.createAccount']; + $kind=$_POST['registration_kind']??(($_GET['membership']??'')==='invited'?'invited':'new_club'); + $params = ['REGISTRATION_KIND'=>$kind,'BTN_SUBMIT' => 'main.php', 'REGISTER_ACTION' => 'SignUp.createAccount']; if (($_SERVER['REQUEST_METHOD'] ?? 'GET') === 'POST') { $this->requireCsrf(); try { @@ -11,20 +12,22 @@ class SignUp extends Base { if (!$auth->allowAttempt('signup-ip', $_SERVER['REMOTE_ADDR'] ?? '', 5, 3600)) { throw new InvalidArgumentException('Too many account requests. Please try again later.'); } - $auth->register($_POST); + if(!in_array($kind,['new_club','invited'],true))throw new InvalidArgumentException('Choose a valid signup option.'); + $input=$_POST;$input['registration_kind']=$kind;$auth->register($input); try{(new EmailVerification())->request($_POST['user_email']);} catch(Throwable $e){error_log('Signup verification delivery failed: '.$e->getMessage());} - $_SESSION['signup_success'] = true; + $_SESSION['signup_success'] = $kind; header('Location: main.php?Xaction=signup', true, 303); exit; } catch (InvalidArgumentException $e) { $params['SIGNUP_ERROR'] = $e->getMessage(); - foreach (['user_first_name', 'user_last_name', 'user_email', 'user_name'] as $field) { + foreach (['user_first_name', 'user_last_name', 'user_email', 'user_name', 'club_name'] as $field) { $params[strtoupper($field)] = $_POST[$field] ?? ''; } } } if (!empty($_SESSION['signup_success'])) { + $params['REGISTRATION_KIND'] = $_SESSION['signup_success']; $params['SIGNUP_SUCCESSFUL'] = 'TRUE'; unset($_SESSION['signup_success']); } diff --git a/classes/TenantAccess.php b/classes/TenantAccess.php new file mode 100644 index 0000000..71f2473 --- /dev/null +++ b/classes/TenantAccess.php @@ -0,0 +1,47 @@ +connect())->prepare("SELECT 1 FROM users WHERE user_serial=? AND user_role=? AND user_status='active' LOCK IN SHARE MODE"); + $stmt->execute([$user ?? ($_SESSION[self::USER_SERIAL] ?? 0), self::SUPER]); + return (bool) $stmt->fetchColumn(); + } + + public function requireSuper(?PDO $db = null): void { + if (!$this->isSuper($db)) + throw new AppException('Only a Super System Administrator may manage global accounts and settings.', 403); + } + + public function canManage(int $club, ?PDO $db = null, ?int $user = null): bool { + $db ??= $this->connect(); + $user ??= (int) ($_SESSION[self::USER_SERIAL] ?? 0); + if ($this->isSuper($db, $user)) + return true; + $stmt = $db->prepare("SELECT 1 FROM club_memberships m JOIN users u ON u.user_serial=m.user_serial WHERE m.club_serial=? AND m.user_serial=? AND m.membership_role='administrator' AND m.membership_status='active' AND u.user_status='active' AND u.user_email_verified_at IS NOT NULL LOCK IN SHARE MODE"); + $stmt->execute([$club, $user]); + return (bool) $stmt->fetchColumn(); + } + + public function available(): bool { + return (bool) $this->connect()->query("SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME='club_memberships' AND COLUMN_NAME='membership_role'")->fetchColumn(); + } + + public function managesAny(): bool { + if ($this->isSuper()) + return true; + if (!$this->available()) + return false; + $stmt = $this->connect()->prepare("SELECT 1 FROM club_memberships m JOIN users u ON u.user_serial=m.user_serial WHERE m.user_serial=? AND m.membership_role='administrator' AND m.membership_status='active' AND u.user_status='active' AND u.user_email_verified_at IS NOT NULL LIMIT 1"); + $stmt->execute([$_SESSION[self::USER_SERIAL] ?? 0]); + return (bool) $stmt->fetchColumn(); + } + + public function requireManager(int $club, ?PDO $db = null): void { + if (!$this->canManage($club, $db)) + throw new AppException('You cannot manage this club.', 403); + } +} diff --git a/composer.json b/composer.json index 80f3586..e22a190 100644 --- a/composer.json +++ b/composer.json @@ -13,7 +13,8 @@ "ext-xsl": "*", "tecnickcom/tcpdf": "^6.10", "phpmailer/phpmailer": "^7.0", - "phpoffice/phpspreadsheet": "^5.2" + "phpoffice/phpspreadsheet": "^5.2", + "spomky-labs/otphp": "^11.4" }, "scripts": { "test:auth": "php tests/auth_integration.php" diff --git a/composer.lock b/composer.lock index 5d53152..b94a7bd 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "0389de306dca31ea5873c1d9ed6a4c5d", + "content-hash": "a46cfa2681b0fe4f29817c408c11ccc1", "packages": [ { "name": "composer/pcre", @@ -267,6 +267,75 @@ }, "time": "2022-12-02T22:17:43+00:00" }, + { + "name": "paragonie/constant_time_encoding", + "version": "v3.1.3", + "source": { + "type": "git", + "url": "https://github.com/paragonie/constant_time_encoding.git", + "reference": "d5b01a39b3415c2cd581d3bd3a3575c1ebbd8e77" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/paragonie/constant_time_encoding/zipball/d5b01a39b3415c2cd581d3bd3a3575c1ebbd8e77", + "reference": "d5b01a39b3415c2cd581d3bd3a3575c1ebbd8e77", + "shasum": "" + }, + "require": { + "php": "^8" + }, + "require-dev": { + "infection/infection": "^0", + "nikic/php-fuzzer": "^0", + "phpunit/phpunit": "^9|^10|^11", + "vimeo/psalm": "^4|^5|^6" + }, + "type": "library", + "autoload": { + "psr-4": { + "ParagonIE\\ConstantTime\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Paragon Initiative Enterprises", + "email": "security@paragonie.com", + "homepage": "https://paragonie.com", + "role": "Maintainer" + }, + { + "name": "Steve 'Sc00bz' Thomas", + "email": "steve@tobtu.com", + "homepage": "https://www.tobtu.com", + "role": "Original Developer" + } + ], + "description": "Constant-time Implementations of RFC 4648 Encoding (Base-64, Base-32, Base-16)", + "keywords": [ + "base16", + "base32", + "base32_decode", + "base32_encode", + "base64", + "base64_decode", + "base64_encode", + "bin2hex", + "encoding", + "hex", + "hex2bin", + "rfc4648" + ], + "support": { + "email": "info@paragonie.com", + "issues": "https://github.com/paragonie/constant_time_encoding/issues", + "source": "https://github.com/paragonie/constant_time_encoding" + }, + "time": "2025-09-24T15:06:41+00:00" + }, { "name": "phpmailer/phpmailer", "version": "v7.0.0", @@ -460,6 +529,54 @@ }, "time": "2026-09-17T03:54:50+00:00" }, + { + "name": "psr/clock", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/clock.git", + "reference": "e41a24703d4560fd0acb709162f73b8adfc3aa0d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/clock/zipball/e41a24703d4560fd0acb709162f73b8adfc3aa0d", + "reference": "e41a24703d4560fd0acb709162f73b8adfc3aa0d", + "shasum": "" + }, + "require": { + "php": "^7.0 || ^8.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Psr\\Clock\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for reading the clock.", + "homepage": "https://github.com/php-fig/clock", + "keywords": [ + "clock", + "now", + "psr", + "psr-20", + "time" + ], + "support": { + "issues": "https://github.com/php-fig/clock/issues", + "source": "https://github.com/php-fig/clock/tree/1.0.0" + }, + "time": "2022-11-25T14:36:26+00:00" + }, { "name": "psr/simple-cache", "version": "3.0.0", @@ -511,6 +628,147 @@ }, "time": "2021-10-29T13:26:27+00:00" }, + { + "name": "spomky-labs/otphp", + "version": "11.5.0", + "source": { + "type": "git", + "url": "https://github.com/Spomky-Labs/otphp.git", + "reference": "877683d6352b80cdc7020fd43a725629c2524435" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Spomky-Labs/otphp/zipball/877683d6352b80cdc7020fd43a725629c2524435", + "reference": "877683d6352b80cdc7020fd43a725629c2524435", + "shasum": "" + }, + "require": { + "paragonie/constant_time_encoding": "^2.0 || ^3.0", + "php": ">=8.1", + "psr/clock": "^1.0", + "symfony/deprecation-contracts": "^3.2" + }, + "require-dev": { + "symfony/error-handler": "^6.4|^7.0|^8.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "OTPHP\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Florent Morselli", + "homepage": "https://github.com/Spomky" + }, + { + "name": "All contributors", + "homepage": "https://github.com/Spomky-Labs/otphp/contributors" + } + ], + "description": "A PHP library for generating one time passwords according to RFC 4226 (HOTP Algorithm) and the RFC 6238 (TOTP Algorithm) and compatible with Google Authenticator", + "homepage": "https://github.com/Spomky-Labs/otphp", + "keywords": [ + "FreeOTP", + "RFC 4226", + "RFC 6238", + "google authenticator", + "hotp", + "otp", + "totp" + ], + "support": { + "issues": "https://github.com/Spomky-Labs/otphp/issues", + "source": "https://github.com/Spomky-Labs/otphp/tree/11.5.0" + }, + "funding": [ + { + "url": "https://github.com/Spomky", + "type": "github" + }, + { + "url": "https://www.patreon.com/FlorentMorselli", + "type": "patreon" + } + ], + "time": "2026-06-06T23:41:24+00:00" + }, + { + "name": "symfony/deprecation-contracts", + "version": "v3.7.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/deprecation-contracts.git", + "reference": "f3202fa1b5097b0af062dc978b32ecf63404e31d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/f3202fa1b5097b0af062dc978b32ecf63404e31d", + "reference": "f3202fa1b5097b0af062dc978b32ecf63404e31d", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.7-dev" + } + }, + "autoload": { + "files": [ + "function.php" + ] + }, + "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": "A generic function and convention to trigger deprecation notices", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.7.1" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2026-06-05T06:23:12+00:00" + }, { "name": "tecnickcom/tcpdf", "version": "6.10.0", diff --git a/css/suneditor-3.3.3.min.css b/css/suneditor-3.3.3.min.css new file mode 100644 index 0000000..c0663a0 --- /dev/null +++ b/css/suneditor-3.3.3.min.css @@ -0,0 +1,28 @@ +.sun-editor,.sun-editor-editable{--se-caret-color:#333;--se-drag-caret-color:#4592ff;--se-placeholder-color:#bbb;--se-edit-font-color:#333;--se-edit-font-pre:#666;--se-edit-font-quote:#999;--se-edit-background-color:#fff;--se-edit-background-pre:#f9f9f9;--se-edit-border-light:#e1e1e1;--se-edit-border-dark:#b1b1b1;--se-edit-border-dark-n1:#c1c1c1;--se-edit-border-dark-n2:#d1d1d1;--se-edit-border-table:#cecece;--se-edit-anchor:#0056b3;--se-edit-anchor-on-back:#e8f7ff;--se-edit-anchor-on-font:#0093ff;--se-edit-hr-color:#333;--se-edit-hr-on-back:#c7deff;--se-edit-active:#4592ff;--se-edit-hover:#e0f4ff;--se-edit-outline:#9e9e9e;--se-main-out-color:#dadada;--se-main-color:#18181b;--se-main-color-lighter:#4c4c4d;--se-main-background-color:#fff;--se-code-view-color:#24292f;--se-main-font-color:#333;--se-code-view-background-color:#fff;--se-code-view-line-color:#57606a;--se-code-view-line-background-color:#f6f8fa;--se-markdown-view-color:#24292f;--se-markdown-view-background-color:#fff;--se-markdown-view-line-color:#57606a;--se-markdown-view-line-background-color:#f6f8fa;--se-main-divider-color:#e1e1e1;--se-main-border-color:#d1d1d1;--se-main-outline-color:#b1b1b1;--se-main-shadow-color:#ececec;--se-statusbar-font-color:#666;--se-overlay-background-color:#000;--se-find-match-color:#ffd50066;--se-find-current-color:#ff9632b3;--se-find-no-match-color:#ff50501f;--se-hover-color:#000;--se-hover-dark-color:#ccc;--se-hover-dark2-color:#bfbfbf;--se-hover-dark3-color:#b0b0b0;--se-hover-light-color:#e1e1e1;--se-hover-light2-color:#e6e6e6;--se-hover-light3-color:#d9d9d9;--se-active-color:#5cd2e6;--se-active-hover-color:#2964b7;--se-active-dark-color:#80bdff;--se-active-dark2-color:#407dd1;--se-active-dark3-color:#4592ff;--se-active-dark4-color:#3f9dff;--se-active-dark5-color:#1275ff;--se-active-light-color:#e6f2ff;--se-active-light2-color:#eaf3ff;--se-active-light3-color:#d0e3ff;--se-active-light4-color:#dbeaff;--se-active-light5-color:#c4ddff;--se-active-light6-color:#b7ccf2;--se-shadow-layer-color:#00000040;--se-shadow-layer:0 1px 2px #0000000f,0 8px 24px #0000001f;--se-shadow-controller:0 1px 2px #0000000f,0 4px 14px #0000001f;--se-drag-over-color:#f0c20a;--se-block-handle-color:var(--se-main-color-lighter);--se-block-handle-btn-hover-bg:#37352f14;--se-block-handle-btn-active-bg:#37352f24;--se-block-hover-bg:#37352f0a;--se-block-hover-outline:#37352f0a;--se-block-drag-indicator-color:var(--se-active-dark3-color);--se-select-menu-hover-bg:#eef3f9;--se-select-menu-active-bg:#dde7f3;--se-modal-background-color:#fff;--se-modal-color:#333;--se-modal-border-color:#e5e5e5;--se-modal-anchor-color:#004cff;--se-modal-preview-color:#666;--se-modal-file-input-background-color:#f9f9f9;--se-modal-input-disabled-color:#999;--se-modal-input-disabled-background-color:#f3f3f3;--se-dropdown-font-color:#555;--se-controller-border-color:#999;--se-controller-background-color:#fff;--se-controller-color:#333;--se-shadow-controller-color:#0003;--se-input-btn-border-color:#ccc;--se-input-btn-disabled-color:#bdbdbd;--se-table-picker-color:#f5f5f5;--se-table-picker-border-color:#ddd;--se-table-picker-highlight-color:#cce0ff;--se-table-picker-highlight-border-color:#90b5e2;--se-success-color:green;--se-success-dark-color:#628562;--se-success-dark2-color:#419c41;--se-success-dark3-color:#006c00;--se-success-light-color:#dff4e6;--se-success-light2-color:#d5f3e0;--se-success-light3-color:#c1f4d3;--se-success-light4-color:#769c76;--se-success-light5-color:#89b589;--se-error-color:#b94a48;--se-error-dark-color:#e1a6a2;--se-error-dark2-color:#db8d8c;--se-error-dark3-color:#d17872;--se-error-light-color:#f5d0c8;--se-error-light2-color:#eed3d7;--se-error-light3-color:#f2dede;--se-error-light4-color:#f7deda;--se-error-light5-color:#f8e3e1;--se-doc-background:#f2f5fa;--se-doc-info-page-font-color:#f5f5f5;--se-doc-info-page-background-color:#b1b1b1;--se-doc-info-font-color:#4c4c4c;--se-doc-info-active-color:#4a32ff;--se-loading-color:#07d;--se-show-blocks-color:#3f9dff;--se-show-blocks-li-color:#d539ff;--se-show-blocks-pre-color:#34c38f;--se-show-blocks-component-color:#f4b124;--se-edit-inner-padding:1.5em;--se-edit-inner-padding-doc-type:2.5rem;--se-edit-scroll-margin:3em;--se-border-radius:6px;--se-border-radius-lg:8px;--se-min-height:65px;--se-scroll-padding:2em;--se-modal-input-width:70px;--se-input-btn-size:32px;--se-icon-size:18px;--se-icon-size-command-menu:16px;--se-block-handle-area-width:52px;--se-block-handle-btn-size:24px;--se-block-handle-btn-icon-size:18px;--se-block-handle-gap:1px;--se-block-drag-indicator-height:2px;--se-doc-min-padding:1rem;--se-doc-max-padding:1.5rem;--se-doc-padding-factor:0.5;--se-doc-info-width:18%;--se-doc-info-min-width:16ch;--se-doc-info-inner-padding:2ch;--se-doc-info-inner-line-padding:0.5ch;--se-doc-info-page-width:16px;--se-doc-info-inner-line-indent-h1:0em;--se-doc-info-inner-line-indent-h2:0.4em;--se-doc-info-inner-line-indent-h3:0.8em;--se-doc-info-inner-line-indent-h4:1.2em;--se-doc-info-inner-line-indent-h5:1.6em;--se-doc-info-inner-line-indent-h6:2em;--se-edit-font-size:16px;--se-edit-line-height:1.5em;--se-main-font-family:Helvetica Neue;--se-content-font-family:Helvetica Neue;--se-main-font-size:14px;--se-markdown-font-family:ui-monospace,SFMono-Regular,"SF Mono",Menlo,Consolas,"Liberation Mono",monospace;--se-codeview-font-family:ui-monospace,SFMono-Regular,"SF Mono",Menlo,Consolas,"Liberation Mono",monospace;--se-btn-font-size:14px;--se-statusbar-font-size:12px;--se-modal-title-font-size:15px;--se-modal-input-font-size:14px;--se-browser-title-font-size:16px;--se-controller-font-size:14px;--se-doc-info-font-size:14px;--se-doc-info-inner-line-weight-h1:700;--se-doc-info-inner-line-weight-h2:500;--se-doc-info-inner-line-weight-h3:400;--se-doc-info-inner-line-weight-h4:300;--se-doc-info-inner-line-weight-h5:300;--se-doc-info-inner-line-weight-h6:300}.sun-editor{background-color:var(--se-main-background-color);border:1px solid var(--se-main-out-color);box-sizing:border-box;color:var(--se-main-color);font-family:var(--se-main-font-family);font-size:var(--se-main-font-size);height:auto;width:auto}.sun-editor *{box-sizing:border-box;overflow:visible}.sun-editor-common blockquote,.sun-editor-common body,.sun-editor-common button,.sun-editor-common code,.sun-editor-common dd,.sun-editor-common div,.sun-editor-common dl,.sun-editor-common dt,.sun-editor-common fieldset,.sun-editor-common form,.sun-editor-common h1,.sun-editor-common h2,.sun-editor-common h3,.sun-editor-common h4,.sun-editor-common h5,.sun-editor-common h6,.sun-editor-common input,.sun-editor-common legend,.sun-editor-common li,.sun-editor-common ol,.sun-editor-common p,.sun-editor-common pre,.sun-editor-common select,.sun-editor-common td,.sun-editor-common textarea,.sun-editor-common th,.sun-editor-common ul{border:0;margin:0;padding:0}.sun-editor-common input,.sun-editor-common select,.sun-editor-common textarea{background-color:inherit}.sun-editor-common dl,.sun-editor-common menu,.sun-editor-common ol,.sun-editor-common ul{list-style:none}.sun-editor-common hr{margin:6px 0!important}.sun-editor textarea{border:0;padding:0;resize:none}.sun-editor button{background-color:initial;border:0;cursor:pointer;outline:none;touch-action:manipulation}.sun-editor button,.sun-editor input,.sun-editor select,.sun-editor textarea{vertical-align:middle}.sun-editor button span{display:block;margin:0;padding:0}.sun-editor button .se-txt{display:block;line-height:2;margin-top:0;max-height:24px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.sun-editor .se-wrapper.se-type-document{--se-doc-padding:clamp(var(--se-doc-min-padding),var(--se-doc-min-padding) + calc(var(--se-doc-padding-factor)*1vw),var(--se-doc-max-padding));background-color:var(--se-doc-background);box-shadow:inset 0 4px 4px #0000001a;padding:var(--se-doc-padding)}.sun-editor .se-wrapper.se-type-document>.se-wrapper-inner{box-shadow:0 0 5px #0000001a}.sun-editor .se-wrapper.se-type-document .se-document-lines{background-color:initial;font-size:var(--se-doc-info-font-size);min-width:var(--se-doc-info-min-width);overflow-x:hidden;overflow-y:auto;width:var(--se-doc-info-width);z-index:1}.sun-editor .se-wrapper.se-type-document .se-document-lines.se-document-responsible{min-width:unset!important}.sun-editor .se-wrapper.se-type-document .se-document-lines .se-document-lines-inner{padding:var(--se-doc-info-inner-padding);padding-right:var(--se-doc-info-inner-line-padding)}.sun-editor .se-wrapper.se-type-document .se-document-lines .se-document-lines-inner>div.se-doc-item{color:var(--se-doc-info-font-color);cursor:pointer;display:inline-block;overflow:hidden;padding:var(--se-doc-info-inner-line-padding);text-overflow:ellipsis;white-space:nowrap;width:100%}.sun-editor .se-wrapper.se-type-document .se-document-lines .se-document-lines-inner>div.se-doc-item:hover{text-decoration:underline}.sun-editor .se-wrapper.se-type-document .se-document-lines .se-document-lines-inner>div.se-doc-item.active{color:var(--se-doc-info-active-color)}.sun-editor .se-wrapper.se-type-document .se-document-lines .se-document-lines-inner>div.se-doc-h1{font-weight:var(--se-doc-info-inner-line-weight-h1);padding-left:var(--se-doc-info-inner-line-indent-h1)}.sun-editor .se-wrapper.se-type-document .se-document-lines .se-document-lines-inner>div.se-doc-h2{font-weight:var(--se-doc-info-inner-line-weight-h2);padding-left:var(--se-doc-info-inner-line-indent-h2)}.sun-editor .se-wrapper.se-type-document .se-document-lines .se-document-lines-inner>div.se-doc-h3{font-weight:var(--se-doc-info-inner-line-weight-h3);padding-left:var(--se-doc-info-inner-line-indent-h3)}.sun-editor .se-wrapper.se-type-document .se-document-lines .se-document-lines-inner>div.se-doc-h4{font-weight:var(--se-doc-info-inner-line-weight-h4);padding-left:var(--se-doc-info-inner-line-indent-h4)}.sun-editor .se-wrapper.se-type-document .se-document-lines .se-document-lines-inner>div.se-doc-h5{font-weight:var(--se-doc-info-inner-line-weight-h5);padding-left:var(--se-doc-info-inner-line-indent-h5)}.sun-editor .se-wrapper.se-type-document .se-document-lines .se-document-lines-inner>div.se-doc-h6{font-weight:var(--se-doc-info-inner-line-weight-h6);padding-left:var(--se-doc-info-inner-line-indent-h6)}.sun-editor .se-wrapper.se-type-document .se-document-page{pointer-events:none;position:relative;text-align:center;z-index:1}.sun-editor .se-wrapper.se-type-document .se-document-page>div{background-color:var(--se-doc-info-page-background-color);color:var(--se-doc-info-page-font-color);font-size:inherit;left:0;margin-left:1px;padding:1px 0;position:absolute;width:var(--se-doc-info-page-width)}.sun-editor .se-wrapper.se-type-document .se-document-page>div>div.se-document-page-line{border-bottom:1px dashed var(--se-doc-info-page-background-color);display:block;height:0;position:absolute;right:100%;top:0;z-index:1}.sun-editor .se-wrapper.se-type-document .se-placeholder{left:var(--se-doc-padding);padding:var(--se-edit-inner-padding-doc-type);right:var(--se-doc-padding);top:var(--se-doc-padding);z-index:2}.sun-editor .se-wrapper.se-type-document.se-type-document-header .se-placeholder{margin-left:max(var(--se-doc-info-min-width),var(--se-doc-info-width))}.sun-editor .se-wrapper.se-type-document.se-mode-block .se-placeholder{margin-left:var(--se-block-handle-area-width)}.sun-editor .se-wrapper.se-type-document.se-mode-block.se-type-document-header .se-placeholder{margin-left:calc(var(--se-block-handle-area-width) + max(var(--se-doc-info-min-width), var(--se-doc-info-width)))}.sun-editor .se-wrapper .CodeMirror,.sun-editor .se-wrapper .cm-editor,.sun-editor .se-wrapper .se-code-viewer-mirror{font-size:var(--se-main-font-size)}.sun-editor button *{backface-visibility:hidden;-webkit-backface-visibility:hidden;-moz-backface-visibility:hidden;pointer-events:none}.sun-editor button{color:var(--se-main-color)}.sun-editor .se-btn{border-color:var(--se-input-btn-border-color);border-radius:var(--se-border-radius);border-style:solid;border-width:0;float:left;font-size:var(--se-btn-font-size);height:var(--se-input-btn-size);line-height:1.8;margin:1px;padding:0;transition:border-color .13s ease,background-color .13s ease,color .13s ease;width:var(--se-input-btn-size)}.sun-editor .se-form-group button.se-btn{border-width:1px}.sun-editor .se-btn:not(.on):not(.active):enabled:focus,.sun-editor .se-btn:not(.on):not(.active):enabled:hover{background-color:var(--se-hover-light-color);border-color:var(--se-hover-dark-color);color:var(--se-hover-color)}.sun-editor .se-btn:not(.on):not(.active):enabled.__se__active,.sun-editor .se-btn:not(.on):not(.active):enabled:active{background-color:var(--se-hover-light3-color);transition:background-color .08s ease}.sun-editor .se-menu-list li:hover .se-btn-input input:enabled,.sun-editor .se-menu-list li:hover .se-side-btn-a:not(.on):not(.active):enabled,.sun-editor .se-menu-list li:hover .se-side-btn-after:not(.on):not(.active):enabled,.sun-editor .se-menu-list li:hover .se-side-btn-b:not(.on):not(.active):enabled,.sun-editor .se-menu-list li:hover .se-side-btn-before:not(.on):not(.active):enabled{border-color:var(--se-hover-dark-color);border-style:solid;border-width:1px}.sun-editor .se-menu-list li .se-btn-input.active input:enabled,.sun-editor .se-menu-list li .se-btn-input.on input:enabled,.sun-editor .se-menu-list li .se-side-btn-after.active:enabled,.sun-editor .se-menu-list li .se-side-btn-after.on:enabled,.sun-editor .se-menu-list li .se-side-btn-before.active:enabled,.sun-editor .se-menu-list li .se-side-btn-before.on:enabled{border-color:var(--se-active-dark3-color)}.sun-editor .se-menu-list li .se-side-btn-after.active:enabled,.sun-editor .se-menu-list li .se-side-btn-after.on:enabled{border-left:1px solid;border-right:0}.sun-editor .se-menu-list li .se-side-btn-before.active:enabled,.sun-editor .se-menu-list li .se-side-btn-before.on:enabled{border-left:0;border-right:1px solid}.sun-editor .se-menu-list li .se-btn-input.active input:enabled,.sun-editor .se-menu-list li .se-btn-input.on input:enabled{border-style:solid;border-width:1px}.sun-editor .se-menu-list li:hover .se-btn-input.active input:enabled,.sun-editor .se-menu-list li:hover .se-btn-input.on input:enabled,.sun-editor .se-menu-list li:hover .se-side-btn-after.active:enabled,.sun-editor .se-menu-list li:hover .se-side-btn-after.on:enabled,.sun-editor .se-menu-list li:hover .se-side-btn-before.active:enabled,.sun-editor .se-menu-list li:hover .se-side-btn-before.on:enabled{border-color:var(--se-active-dark4-color)}.sun-editor .se-btn:enabled.on{background-color:var(--se-active-light4-color);border-color:var(--se-active-light5-color);color:var(--se-active-dark5-color)}.sun-editor .se-btn:enabled.on:focus,.sun-editor .se-btn:enabled.on:hover{background-color:var(--se-active-light3-color);border-color:var(--se-active-light5-color);color:var(--se-active-hover-color)}.sun-editor .se-btn:enabled.on.__se__active,.sun-editor .se-btn:enabled.on:active{background-color:var(--se-active-light5-color);color:var(--se-active-hover-color);transition:background-color .08s ease}.sun-editor .se-btn:enabled.active{background-color:var(--se-active-light4-color);border-color:var(--se-active-dark-color);color:var(--se-active-dark3-color)}.sun-editor .se-btn:enabled.active:focus,.sun-editor .se-btn:enabled.active:hover{background-color:var(--se-active-light5-color);border-color:var(--se-active-dark4-color);color:var(--se-active-hover-color)}.sun-editor .se-btn:enabled.active.__se__active,.sun-editor .se-btn:enabled.active:active{background-color:var(--se-active-light6-color);color:var(--se-active-hover-color);transition:background-color .08s ease;z-index:1}.sun-editor .se-btn.se-btn-plain,.sun-editor .se-btn.se-btn-plain:not(.on):not(.active):enabled:focus,.sun-editor .se-btn.se-btn-plain:not(.on):not(.active):enabled:hover{background-color:initial;border-color:#0000;box-shadow:none}.sun-editor .se-btn.se-btn-plain:not(.on):not(.active):enabled.__se__active,.sun-editor .se-btn.se-btn-plain:not(.on):not(.active):enabled:active{background-color:initial;border-color:#0000!important;box-shadow:none;outline:none!important}.sun-editor .se-btn-primary{background-color:var(--se-active-dark5-color);border:1px solid var(--se-active-dark5-color);border-radius:var(--se-border-radius);color:#fff;font-weight:500;outline:0 none;transition:border-color .13s ease,background-color .13s ease,color .13s ease}.sun-editor .se-btn-primary:focus,.sun-editor .se-btn-primary:hover{background-color:var(--se-active-hover-color);border-color:var(--se-active-hover-color);color:#fff}.sun-editor .se-btn-primary.__se__active,.sun-editor .se-btn-primary:active{background-color:var(--se-active-hover-color);transition:background-color .08s ease}.sun-editor .se-btn.se-btn-success{border-color:var(--se-success-light5-color);color:var(--se-success-color)}.sun-editor .se-btn.se-btn-success:not(.on):not(.active):enabled:focus,.sun-editor .se-btn.se-btn-success:not(.on):not(.active):enabled:hover{background-color:var(--se-success-light-color);border-color:var(--se-success-light5-color)}.sun-editor .se-btn.se-btn-success:not(.on):not(.active):enabled.__se__active,.sun-editor .se-btn.se-btn-success:not(.on):not(.active):enabled:active{background-color:var(--se-success-light-color);transition:background-color .08s ease}.sun-editor .se-btn.se-btn-success:enabled.on{background-color:var(--se-success-light-color);border-color:var(--se-success-light5-color);color:var(--se-success-color)}.sun-editor .se-btn.se-btn-success:enabled.on:focus,.sun-editor .se-btn.se-btn-success:enabled.on:hover{background-color:var(--se-success-light2-color);border-color:var(--se-success-light4-color);color:var(--se-success-color)}.sun-editor .se-btn.se-btn-success:enabled.on.__se__active,.sun-editor .se-btn.se-btn-success:enabled.on:active{background-color:var(--se-success-light2-color);color:var(--se-success-color);transition:background-color .08s ease}.sun-editor .se-btn.se-btn-success:enabled.active{background-color:var(--se-success-light2-color);border-color:var(--se-success-dark2-color);color:var(--se-success-color)}.sun-editor .se-btn.se-btn-success:enabled.active:focus,.sun-editor .se-btn.se-btn-success:enabled.active:hover{background-color:var(--se-success-light3-color);border-color:var(--se-success-dark2-color);color:var(--se-success-dark3-color)}.sun-editor .se-btn.se-btn-success:enabled.active.__se__active,.sun-editor .se-btn.se-btn-success:enabled.active:active{background-color:var(--se-success-light3-color);color:var(--se-success-dark3-color);transition:background-color .08s ease}.sun-editor .se-btn.se-btn-danger{border-color:var(--se-error-dark-color);color:var(--se-error-color)}.sun-editor .se-btn.se-btn-danger:not(.on):not(.active):enabled:focus,.sun-editor .se-btn.se-btn-danger:not(.on):not(.active):enabled:hover{background-color:var(--se-error-light5-color);border-color:var(--se-error-dark-color)}.sun-editor .se-btn.se-btn-danger:not(.on):not(.active):enabled.__se__active,.sun-editor .se-btn.se-btn-danger:not(.on):not(.active):enabled:active{background-color:var(--se-error-light5-color);transition:background-color .08s ease}.sun-editor .se-btn.se-btn-danger:enabled.on{background-color:var(--se-error-light5-color);border-color:var(--se-error-dark-color);color:var(--se-error-color)}.sun-editor .se-btn.se-btn-danger:enabled.on:focus,.sun-editor .se-btn.se-btn-danger:enabled.on:hover{background-color:var(--se-error-light4-color);border-color:var(--se-error-dark-color);color:var(--se-error-color)}.sun-editor .se-btn.se-btn-danger:enabled.on.__se__active,.sun-editor .se-btn.se-btn-danger:enabled.on:active{background-color:var(--se-error-light-color);color:var(--se-error-color);transition:background-color .08s ease}.sun-editor .se-btn.se-btn-danger:enabled.active{background-color:var(--se-error-light4-color);border-color:var(--se-error-dark3-color);color:var(--se-error-color)}.sun-editor .se-btn.se-btn-danger:enabled.active:focus,.sun-editor .se-btn.se-btn-danger:enabled.active:hover{background-color:var(--se-error-light-color);border-color:var(--se-error-dark3-color);color:var(--se-error-color)}.sun-editor .se-btn.se-btn-danger:enabled.active.__se__active,.sun-editor .se-btn.se-btn-danger:enabled.active:active{background-color:var(--se-error-light-color);color:var(--se-error-color);transition:background-color .08s ease}.sun-editor input,.sun-editor select,.sun-editor textarea{border:1px solid var(--se-input-btn-border-color);border-radius:var(--se-border-radius);color:var(--se-main-color)}.sun-editor .se-btn:disabled,.sun-editor button:disabled,.sun-editor input:disabled{color:var(--se-input-btn-disabled-color);cursor:default}.sun-editor .se-btn-list{cursor:pointer;font-size:var(--se-btn-font-size);height:auto;line-height:normal;min-height:32px;padding:0 14px;text-align:left;text-decoration:none;text-indent:0;width:100%}.sun-editor .se-btn-list.default_value{border:1px dashed var(--se-main-outline-color)}.sun-editor .se-sub-list:has(:not([style*="display: none"])){border-bottom:1px dashed var(--se-main-outline-color);color:color-mix(in srgb,currentColor 45%,#0000);cursor:auto;font-size:.75rem;letter-spacing:.25px;padding:14px 14px 3px}.sun-editor .se-btn.se-btn-tool-pageNavigator>input{color:var(--se-main-color-lighter);text-align:center;width:var(--se-input-btn-size)}.sun-editor .se-btn.se-btn-tool-pageNavigator>input[type=number]{-webkit-appearance:textfield;-moz-appearance:textfield;appearance:textfield}.sun-editor .se-btn.se-btn-tool-pageNavigator>input[type=number]::-webkit-inner-spin-button,.sun-editor .se-btn.se-btn-tool-pageNavigator>input[type=number]::-webkit-outer-spin-button{-webkit-appearance:none;-moz-appearance:none;appearance:none;margin:0}.sun-editor .se-btn.se-btn-tool-pageNavigator~span{align-content:center;font-size:var(--se-main-font-size);margin-left:-10px;text-align:center}.sun-editor .se-btn.se-btn-tool-pageNavigator~span:before{content:"/";margin:0 .6em}.sun-editor svg{fill:currentColor;vertical-align:super}.sun-editor .se-svg,.sun-editor button>svg{display:block;fill:currentColor;float:none;height:var(--se-icon-size);margin:auto;text-align:center;width:var(--se-icon-size)}.sun-editor button>svg.se-ci{height:15px;width:15px}.sun-editor svg.se-io{fill:none;stroke:currentColor;stroke-linecap:round;stroke-linejoin:round;stroke-width:2}.sun-editor svg.se-io-sharp{transform:translateZ(0)}.sun-editor .se-text-prefix-icon{float:left;height:var(--se-icon-size);width:var(--se-icon-size)}.sun-editor .se-text-prefix-icon svg{vertical-align:middle}.sun-editor button.se-sub-arrow-btn{width:18px}.sun-editor button.se-sub-arrow-btn svg{width:8px}.sun-editor button.se-sub-btn{width:24px}.sun-editor button.se-sub-btn svg{width:12px}.sun-editor .se-side-btn{border-radius:0;margin-left:0;margin-right:0}.sun-editor .se-side-btn-a{border-radius:var(--se-border-radius) 0 0 var(--se-border-radius);float:left;margin-right:0}.sun-editor .se-side-btn-b{border-radius:0 var(--se-border-radius) var(--se-border-radius) 0;float:left;margin-left:0}.sun-editor .se-side-btn-before{border-radius:var(--se-border-radius) 0 0 var(--se-border-radius);float:left;margin-right:0}.sun-editor .se-side-btn-after{border-radius:0 var(--se-border-radius) var(--se-border-radius) 0;margin-left:0}.sun-editor .se-menu-list li:has(>button.se-side-btn-before) .se-btn-input input{border-bottom-left-radius:0;border-top-left-radius:0}.sun-editor .se-menu-list li:has(>button.se-side-btn-after) .se-btn-input input{border-bottom-right-radius:0;border-top-right-radius:0}.sun-editor button.se-btn-list>* li:before{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCI+PHBhdGggc3Ryb2tlPSIjZmZmIiBkPSJNMTkgMTNINXYtMmgxNHoiLz48L3N2Zz4=);background-size:cover;content:"";display:inline-block;height:13px;opacity:.5;width:18px}.sun-editor .se-btn-select>svg{float:right;height:8px!important;width:8px!important}.sun-editor .se-select-item .se-list-icon{display:inline-block;height:16px;margin:0 6px 0 0;vertical-align:middle;width:16px}.sun-editor .se-btn-list>.se-list-icon{display:inline-block;height:16px;margin:-1px 10px 0 0;vertical-align:middle;width:16px}.sun-editor button>i:before{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-size:var(--se-modal-title-font-size);font-style:normal;font-variant:normal;line-height:2;text-rendering:auto}.sun-editor button>[class=se-icon-text]{font-size:20px;line-height:1}.sun-editor .se-arrow,.sun-editor .se-arrow:after{border:12px solid #0000;display:block;height:0;margin-left:-12px;margin-right:0;position:absolute;width:0}.sun-editor .se-controller .se-arrow{left:20px;margin-left:-12px;margin-right:0;right:auto}.sun-editor .se-arrow.se-arrow-up{border-bottom-color:var(--se-controller-border-color);border-top-width:0;top:-12px}.sun-editor .se-arrow.se-arrow-up:after{border-bottom-color:var(--se-main-background-color);border-top-width:0;content:" ";top:1px}.sun-editor .se-arrow.se-arrow-down{border-bottom-width:0;border-top-color:var(--se-controller-border-color);bottom:-12px}.sun-editor .se-arrow.se-arrow-down:after{border-bottom-width:0;border-top-color:var(--se-controller-background-color);content:" ";top:-14px}.sun-editor .se-container{height:auto;position:relative;width:auto}.sun-editor .se-loading-box{background-color:initial;display:none;height:100%;left:0;position:fixed;top:0;width:100%;z-index:2147483647}.sun-editor .se-container .se-loading-box{position:absolute}.sun-editor .se-loading-box .se-loading-effect{-webkit-animation:spinner .8s linear infinite;animation:spinner .8s linear infinite;border:2px solid #0000;border-radius:50%;border-right:2px solid var(--se-loading-color);border-top:2px solid var(--se-loading-color);display:block;height:44px;left:50%;margin:-25px 0 0 -25px;position:absolute;top:50%;width:44px}.sun-editor .se-line-breaker-component{background-color:var(--se-main-background-color);border:1px solid var(--se-drag-over-color);border-radius:var(--se-border-radius);color:var(--se-drag-over-color);cursor:pointer;display:none;height:24px;opacity:.95;position:absolute;transition:opacity .3s ease,color .3s ease,background-color .3s ease;width:24px;z-index:2147483647}.sun-editor .se-line-breaker-component.se-on-selected{background-color:var(--se-main-background-color);border:1px solid var(--se-active-color);color:var(--se-active-color)}.sun-editor .se-line-breaker-component:hover{background-color:var(--se-active-dark3-color);border-color:var(--se-active-color);color:var(--se-main-background-color);opacity:.9}.sun-editor .se-toolbar{background-color:var(--se-main-background-color);display:block;height:auto;margin:0;outline:1px solid var(--se-main-divider-color);overflow:visible;padding:0;position:sticky;top:0;width:100%;z-index:7}.sun-editor .se-toolbar-shadow{background-color:initial!important;border:none!important;display:block!important;height:0!important;margin:0!important;outline:none!important;overflow:visible!important;padding:0!important;position:relative!important;visibility:hidden!important;width:100%!important;z-index:0!important}.sun-editor .se-toolbar.se-toolbar-inline{display:none;position:absolute}.sun-editor .se-toolbar.se-toolbar-balloon{box-shadow:var(--se-shadow-layer);-webkit-box-shadow:var(--se-shadow-layer);display:none;position:absolute;width:auto;z-index:2147483646}.sun-editor .se-toolbar.se-toolbar-relative{position:relative;top:auto}.sun-editor .se-toolbar.se-toolbar-sticky{position:fixed;top:0}.sun-editor .se-toolbar-sticky-dummy{display:none;position:static;z-index:-1}.sun-editor .se-toolbar.se-toolbar-bottom{bottom:0;top:auto}.sun-editor .se-toolbar.se-toolbar-bottom .se-btn-tray{display:flex;flex-wrap:wrap;padding:4px 3px}.sun-editor .se-toolbar.se-toolbar-bottom .se-btn-tray>.se-toolbar-more-layer{border-top:none;order:-1;width:100%}.sun-editor .se-toolbar.se-toolbar-bottom .se-toolbar-more-layer .se-more-layer{border-bottom:1px solid var(--se-main-divider-color);border-top:none;margin-bottom:4px}.sun-editor .se-toolbar.se-toolbar-sticky.se-toolbar-bottom{bottom:0;top:auto}.sun-editor .se-toolbar.se-toolbar-bottom .se-tooltip .se-tooltip-inner{bottom:120%;top:auto}.sun-editor .se-toolbar.se-toolbar-bottom .se-tooltip .se-tooltip-inner .se-tooltip-text:after{border-color:var(--se-main-font-color) #0000 #0000 #0000;bottom:auto;top:100%}.sun-editor .se-toolbar .se-arrow.se-arrow-up{border-bottom-color:var(--se-main-divider-color)}.sun-editor .se-toolbar .se-arrow.se-arrow-up:after{border-bottom-color:var(--se-main-background-color)}.sun-editor .se-toolbar .se-arrow.se-arrow-down{border-top-color:var(--se-main-divider-color)}.sun-editor .se-toolbar .se-arrow.se-arrow-down:after{border-top-color:var(--se-main-background-color)}.sun-editor .se-wrapper.se-mode-block{display:flex;flex-direction:row}.sun-editor.se-rtl .se-wrapper.se-mode-block{flex-direction:row-reverse}.sun-editor .se-block-handle-area{flex-shrink:0;overflow:visible;position:relative;width:var(--se-block-handle-area-width);z-index:2}.sun-editor .se-wrapper.se-mode-block .se-wrapper-inner{flex:1;min-width:0;position:relative;z-index:1}.sun-editor .se-block-handle{align-items:center;color:var(--se-block-handle-color);display:none;gap:var(--se-block-handle-gap);position:absolute;transition:top .2s cubic-bezier(.25,.46,.45,.94),left .2s cubic-bezier(.25,.46,.45,.94),right .2s cubic-bezier(.25,.46,.45,.94);will-change:top,left,right;z-index:10}.sun-editor .se-block-handle.se-no-transition{transition:none}.sun-editor .se-block-handle-btn{align-items:center;border-radius:var(--se-border-radius);cursor:pointer;display:flex;height:var(--se-block-handle-btn-size);justify-content:center;opacity:.55;transition:opacity .15s,background-color .08s ease;width:var(--se-block-handle-btn-size)}.sun-editor .se-block-handle-btn:hover{background-color:var(--se-block-handle-btn-hover-bg);opacity:1}.sun-editor .se-block-handle-btn:active{background-color:var(--se-block-handle-btn-active-bg);opacity:1}.sun-editor .se-block-handle-btn svg{height:var(--se-block-handle-btn-icon-size);width:var(--se-block-handle-btn-icon-size)}.sun-editor .se-block-handle-drag{cursor:grab}.sun-editor .se-block-handle-drag:active{cursor:grabbing}.sun-editor .se-block-hover:not(.se-component-selected){background-color:var(--se-block-hover-bg);border-radius:var(--se-border-radius);outline:2px solid var(--se-block-hover-outline)}.sun-editor .se-block-drag-indicator{background-color:var(--se-block-drag-indicator-color);border-radius:1px;height:var(--se-block-drag-indicator-height);pointer-events:none;position:absolute;z-index:10}.sun-editor .se-block-drag-indicator:before{border:0 solid #0000;border-color:#0000 #0000 #0000 var(--se-block-drag-indicator-color);border-width:5px 0 5px 6px;content:"";height:0;left:-3px;position:absolute;top:-4px;width:0}.sun-editor .se-block-drag-indicator:after{border:0 solid #0000;border-color:#0000 var(--se-block-drag-indicator-color) #0000 #0000;border-width:5px 6px 5px 0;content:"";height:0;position:absolute;right:-3px;top:-4px;width:0}.sun-editor .se-block-dragging{transition:opacity .1s}.sun-editor .se-block-menu-icon{align-items:center;display:inline-flex;height:var(--se-icon-size-command-menu);margin-left:4px;margin-right:12px;vertical-align:middle;width:var(--se-icon-size-command-menu)}.sun-editor .se-block-menu-icon svg{height:100%;width:100%}.sun-editor .se-block-menu-label{vertical-align:middle}.sun-editor .se-block-menu-label-full{padding-left:22px}.sun-editor .se-block-submenu-item{align-items:center;display:flex;gap:6px;line-height:1.4;padding:2px 8px}.sun-editor .se-block-submenu-item .se-list-icon,.sun-editor .se-block-submenu-item svg{display:inline-block;flex-shrink:0;height:var(--se-icon-size-command-menu);margin:0 6px 0 0;vertical-align:middle;width:var(--se-icon-size-command-menu)}.sun-editor .se-block-submenu-item .se-list-icon svg{height:100%;width:100%}.sun-editor .se-block-dragging{opacity:.4}.sun-editor .se-btn-module{display:inline-block}.sun-editor .se-btn-module-border{border:none;border-radius:var(--se-border-radius);margin-left:1px;margin-right:1px}.sun-editor .se-toolbar-separator-vertical{background-color:var(--se-main-divider-color);display:inline-block;height:var(--se-input-btn-size);margin:1px;vertical-align:top;width:1px}.sun-editor .se-btn-module-enter{background-color:initial;display:block;height:0;margin:0;padding:0;width:100%}.sun-editor .se-toolbar-more-layer{background-color:var(--se-main-background-color);margin:0 -3px}.sun-editor .se-toolbar-more-layer .se-more-layer{border-top:1px solid var(--se-main-divider-color);display:none}.sun-editor .se-toolbar-more-layer .se-more-layer .se-more-form{display:inline-block;height:auto;padding:4px 3px 0;width:100%}.sun-editor .se-btn-module .se-btn-more.se-btn-more-text{padding:0 4px;width:auto}.sun-editor .se-menu-list,.sun-editor .se-menu-list li{float:left;margin:0;padding:0}.sun-editor .se-menu-list li{position:relative}.sun-editor .se-menu-list li.se-toolbar-hidden-btn{display:none}.sun-editor .se-menu-list li .se-toolbar-btn:not(input){border-color:#0000}.sun-editor .se-btn-select{display:flex;padding:4px 6px;width:auto}.sun-editor .se-btn-select .se-txt{align-items:center;display:flex;flex:auto;margin-right:4px;text-align:left}.sun-editor .se-btn-select .se-not-arrow-text{flex:auto;margin:0;text-align:center}.sun-editor .se-btn-select.on .se-txt+svg{transform:rotate(-180deg)}.sun-editor .se-btn-select.se-btn-tool-font{width:128px}.sun-editor .se-btn-select.se-btn-tool-format{width:96px}.sun-editor .se-btn-select.se-btn-tool-font-size .se-txt{margin:0;width:66px}.sun-editor .se-btn-select.se-btn-tool-font-size .se-not-arrow-text{width:50px}.sun-editor .se-btn-input{border:0!important;padding:0!important}.sun-editor .se-btn-input input{border:0;border-radius:var(--se-border-radius);font-size:var(--se-main-font-size);height:var(--se-input-btn-size)}.sun-editor .se-btn-input input:hover{border:1px solid var(--se-main-border-color)}.sun-editor .se-btn-input input:focus{border:1px solid var(--se-active-color)!important;outline:0}.sun-editor .se-btn-tray{height:auto;margin:0;padding:4px 3px 0;position:relative;width:100%}.sun-editor .se-menu-tray{height:0;left:0;position:absolute;top:0;width:100%;z-index:2147483646}.sun-editor .se-block-handle[popover],.sun-editor .se-controller[popover],.sun-editor.sun-editor-carrier-wrapper .se-drag-cursor[popover]{inset:unset;margin:0}.sun-editor .se-back-wrapper[popover],.sun-editor .se-block-handle[popover],.sun-editor .se-browser[popover],.sun-editor .se-loading-box[popover],.sun-editor .se-menu-tray[popover],.sun-editor .se-modal-area[popover],.sun-editor .se-toast[popover]{background:none;border:none;color:inherit;overflow:visible;padding:0}.sun-editor .se-dropdown{overflow-x:hidden;overflow-y:auto}.sun-editor .se-menu-container{overflow-x:unset;overflow-y:unset}.sun-editor .se-list-layer{background-color:var(--se-main-background-color);border:1px solid var(--se-main-divider-color);border-radius:var(--se-border-radius-lg);box-shadow:var(--se-shadow-layer);display:none;height:auto;left:0;outline:0 none;padding:4px;position:absolute;top:0;z-index:5}.sun-editor .se-list-layer .se-list-inner{margin:0;overflow:visible;padding:0}.sun-editor .se-list-layer button{margin:0 0 2px;width:100%}.sun-editor .se-list-inner ul{margin:auto;padding:0;width:100%}.sun-editor .se-list-inner :not(.se-list-horizontal) li>button{min-width:100%;width:-webkit-max-content;width:-moz-max-content;width:max-content}.sun-editor .se-list-inner .se-list-basic li{max-width:100%;width:auto}.sun-editor .se-list-inner input{border-radius:0}.sun-editor .se-list-inner ul.se-list-carrier{height:52px;width:165px}.sun-editor .se-list-inner ul.se-list-carrier li button>ol,.sun-editor .se-list-inner ul.se-list-carrier li button>ul{font-size:10px}.sun-editor .se-list-inner .se-list-checked li .se-svg{float:left;padding:6px 6px 0 0}.sun-editor .se-list-inner .se-list-checked li .se-svg>svg{display:none}.sun-editor .se-list-inner .se-list-checked li.se-checked *{color:var(--se-active-dark3-color)}.sun-editor .se-list-inner .se-list-checked li.se-checked .se-svg>svg{display:block}.sun-editor .se-list-inner .se-list-horizontal{display:flex;padding:2px}.sun-editor .se-list-inner .se-list-horizontal li{margin:0 2px;padding:0}.sun-editor .se-list-layer.se-list-font-size{max-height:300px;min-width:140px}.sun-editor .se-list-layer.se-list-code-block{max-height:310px;min-width:140px}.sun-editor .se-list-layer.se-list-font-family{min-width:156px}.sun-editor .se-list-layer.se-list-font-family .default{border-bottom:1px solid var(--se-input-btn-border-color)}.sun-editor .se-list-layer.se-list-line{width:125px}.sun-editor .se-list-layer.se-list-line hr{border-color:var(--se-edit-hr-color);border-width:1px 0 0;height:1px}.sun-editor .se-list-layer.se-list-align .se-list-inner{left:9px}.sun-editor .se-list-layer.se-list-format{min-width:156px}.sun-editor .se-list-layer.se-list-format li{padding:0;width:100%}.sun-editor .se-list-layer.se-list-format ul .se-btn-list{line-height:100%}.sun-editor .se-list-layer.se-list-format ul .se-btn-list[data-value=h1]{height:40px}.sun-editor .se-list-layer.se-list-format ul .se-btn-list[data-value=h2]{height:34px}.sun-editor .se-list-layer.se-list-format ul p{font-size:var(--se-main-font-size)}.sun-editor .se-list-layer.se-list-format ul div{font-size:var(--se-main-font-size);padding:4px 2px}.sun-editor .se-list-layer.se-list-format ul h1{font-size:2em;font-weight:700}.sun-editor .se-list-layer.se-list-format ul h2{font-size:1.5em;font-weight:700}.sun-editor .se-list-layer.se-list-format ul h3{font-size:1.17em;font-weight:700}.sun-editor .se-list-layer.se-list-format ul h4{font-size:1em;font-weight:700}.sun-editor .se-list-layer.se-list-format ul h5{font-size:.83em;font-weight:700}.sun-editor .se-list-layer.se-list-format ul h6{font-size:.67em;font-weight:700}.sun-editor .se-list-layer.se-list-format ul blockquote{background-color:initial;border-color:var(--se-edit-border-dark);border-style:solid;border-width:0 0 0 5px;color:var(--se-edit-font-quote);font-size:var(--se-main-font-size);height:22px;line-height:1.5;margin:0;padding:0 0 0 7px}.sun-editor .se-list-layer.se-list-format ul pre{background-color:var(--se-edit-background-pre);border:1px solid var(--se-edit-border-light);border-radius:var(--se-border-radius);color:var(--se-edit-font-pre);font-size:var(--se-main-font-size);margin:0;padding:4px 11px}.sun-editor-editable[contenteditable=true],.sun-editor-editable[contenteditable=true] *{scroll-margin:var(--se-edit-scroll-margin)}.sun-editor-editable[contenteditable=true].se-copy-format-cursor{cursor:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIxNiIgdmlld0JveD0iMCAwIDI0IDE2Ij48ZGVmcz48ZmlsdGVyIGlkPSJhIiBjb2xvci1pbnRlcnBvbGF0aW9uLWZpbHRlcnM9InNSR0IiPjxmZU1vcnBob2xvZ3kgaW49IlNvdXJjZUFscGhhIiBvcGVyYXRvcj0iZGlsYXRlIiByYWRpdXM9IjEiIHJlc3VsdD0iZGlsYXRlZCIvPjxmZUZsb29kIGZsb29kLWNvbG9yPSIjZmZmIiByZXN1bHQ9IndoaXRlIi8+PGZlQ29tcG9zaXRlIGluPSJ3aGl0ZSIgaW4yPSJkaWxhdGVkIiBvcGVyYXRvcj0iaW4iIHJlc3VsdD0ib3V0bGluZSIvPjxmZU1lcmdlPjxmZU1lcmdlTm9kZSBpbj0ib3V0bGluZSIvPjxmZU1lcmdlTm9kZSBpbj0iU291cmNlR3JhcGhpYyIvPjwvZmVNZXJnZT48L2ZpbHRlcj48L2RlZnM+PGcgZmlsdGVyPSJ1cmwoI2EpIj48cGF0aCBkPSJNNC4zMzIgMTIuNjY4YzAgLjM2Ny4xNTIuNjY0LjMzNi42NjRoLjY2NHYxLjMzNkg0LjVjLS4xODQgMC0uNS0uMzAxLS41LS42NjggMCAuMzY3LS4zMTYuNjY4LS41LjY2OGgtLjgzMnYtMS4zMzZoLjY2NGMuMTg0IDAgLjMzNi0uMjk3LjMzNi0uNjY0VjMuMzMyYzAtLjM2Ny0uMTUyLS42NjQtLjMzNi0uNjY0aC0uNjY0VjEuMzMySDMuNWMuMTg0IDAgLjUuMzAxLjUuNjY4IDAtLjM2Ny4zMTYtLjY2OC41LS42NjhoLjgzMnYxLjMzNmgtLjY2NGMtLjE4NCAwLS4zMzYuMjk3LS4zMzYuNjY0Wk0yMCAyLjY2OFYyYS42Ny42NyAwIDAgMC0uNjY4LS42NjhoLThhLjY2Ny42NjcgMCAwIDAtLjY2NC42Njh2Mi42NjhjMCAuMzY3LjI5Ny42NjQuNjY0LjY2NGg4QS42NjUuNjY1IDAgMCAwIDIwIDQuNjY4VjRoLjY2OHYyLjY2OEgxNFYxNGMwIC4zNjcuMjk3LjY2OC42NjguNjY4SDE2YS42Ny42NyAwIDAgMCAuNjY4LS42NjhWOEgyMlYyLjY2OFoiLz48L2c+PC9zdmc+) 0 8,text}.sun-editor-editable[contenteditable=true] table td:not(.se-selected-table-cell):hover:before,.sun-editor-editable[contenteditable=true] table th:not(.se-selected-table-cell):hover:before{background-color:initial;content:"";cursor:ew-resize;height:100%;left:-2px;position:absolute;top:0;width:4px}.sun-editor-editable[contenteditable=true] table td:not(.se-selected-table-cell):hover:after,.sun-editor-editable[contenteditable=true] table th:not(.se-selected-table-cell):hover:after{background-color:initial;content:"";cursor:ew-resize;height:100%;position:absolute;right:-2px;top:0;width:4px}.sun-editor .se-table-resize-line{height:100%;margin-left:-3px;top:0;width:6px}.sun-editor .se-table-resize-line,.sun-editor .se-table-resize-row{background-color:var(--se-active-dark-color);display:none;opacity:.4;pointer-events:none;position:absolute;z-index:2}.sun-editor .se-table-resize-row{height:6px;left:0;margin-top:-3px;width:100%}.sun-editor .se-table-resize-line-prev{border-left:1px dashed var(--se-drag-over-color);height:100%;margin-left:-1px;top:0;width:4px}.sun-editor .se-table-resize-line-prev,.sun-editor .se-table-resize-row-prev{background-color:initial;display:none;opacity:.8;pointer-events:none;position:absolute;z-index:2}.sun-editor .se-table-resize-row-prev{border-top:1px dashed var(--se-drag-over-color);height:4px;left:0;margin-top:-1px;width:100%}.sun-editor .se-selector-table{-webkit-background-clip:padding-box;background-clip:padding-box;background-color:var(--se-main-background-color);border:1px solid var(--se-input-btn-border-color);border-radius:var(--se-border-radius);box-shadow:var(--se-shadow-layer);display:none;float:left;font-size:var(--se-main-font-size);left:1px;list-style:none;margin:2px 0 0;overflow:hidden;padding:5px 0;position:absolute;text-align:left;top:var(--se-input-btn-size);z-index:5}.sun-editor .se-selector-table .se-table-size{font-size:18px;padding:0 5px}.sun-editor .se-selector-table .se-table-size-picker{cursor:pointer;font-size:18px;height:10em;position:absolute!important;width:10em;z-index:3}.sun-editor .se-selector-table .se-table-size-highlighted{background-color:var(--se-table-picker-highlight-color);background-image:linear-gradient(to right,var(--se-table-picker-highlight-border-color) 1px,#0000 1px),linear-gradient(to bottom,var(--se-table-picker-highlight-border-color) 1px,#0000 1px);background-size:1em 1em;border-bottom:1px solid var(--se-table-picker-highlight-border-color);border-right:1px solid var(--se-table-picker-highlight-border-color);font-size:18px;height:1em;position:absolute!important;width:1em;z-index:2}.sun-editor .se-selector-table .se-table-size-unhighlighted{background-color:var(--se-table-picker-color);background-image:linear-gradient(to right,var(--se-table-picker-border-color) 1px,#0000 1px),linear-gradient(to bottom,var(--se-table-picker-border-color) 1px,#0000 1px);background-size:1em 1em;border-bottom:1px solid var(--se-table-picker-border-color);border-right:1px solid var(--se-table-picker-border-color);font-size:18px;height:5em;position:relative!important;width:5em;z-index:1}.sun-editor .se-selector-table .se-table-size-display{padding-left:5px}.sun-editor .se-list-layer.se-table-split{top:36px}.sun-editor .se-list-layer .se-selector-color{display:block;height:auto;margin:auto;max-width:252px;padding:0;width:-webkit-max-content;width:-moz-max-content;width:max-content}.sun-editor .se-list-layer .se-selector-color .se-color-pallet{height:100%;padding:0;width:100%}.sun-editor .se-list-layer .se-selector-color .se-color-pallet li{display:flex;float:left;margin:0;position:relative}.sun-editor .se-list-layer .se-selector-color .se-color-pallet button{border:0;border-radius:0;cursor:default;display:block;height:28px;margin:0;text-indent:-9999px;transition:transform .2s,box-shadow .2s;width:28px}.sun-editor .se-list-layer .se-selector-color .se-color-pallet button.active,.sun-editor .se-list-layer .se-selector-color .se-color-pallet button:hover{box-shadow:inset 0 0 0 1px #0000;transform:scale(.8)}.sun-editor .se-list-layer .se-selector-color .se-color-pallet button.active>svg{color:#fff;stroke:#000;stroke-width:2px}.sun-editor .se-list-layer .se-selector-color .se-color-pallet:first-child li:first-child button{border-top-left-radius:var(--se-border-radius)}.sun-editor .se-list-layer .se-selector-color .se-color-pallet:first-child li:last-child button{border-top-right-radius:var(--se-border-radius)}.sun-editor .se-list-layer .se-selector-color .se-color-pallet:last-of-type li:first-child button{border-bottom-left-radius:var(--se-border-radius)}.sun-editor .se-list-layer .se-selector-color .se-color-pallet:last-of-type li:last-child button{border-bottom-right-radius:var(--se-border-radius)}.sun-editor .se-hue-slider{padding:14px}.sun-editor .se-hue-slider-container{border-radius:50%;height:auto;outline:2px solid #fff;position:relative;width:auto}.sun-editor .se-hue-slider-container .se-hue-wheel{border-radius:50%;cursor:pointer}.sun-editor .se-hue-slider-container .se-hue-wheel-pointer{background-color:initial;border:2px solid #fff;border-radius:50%;box-shadow:0 0 2px #000;height:10px;left:50%;outline:2px solid #000;pointer-events:none;position:absolute;top:50%;transform:translate(-50%,-50%);width:10px}.sun-editor .se-hue-gradient-container{height:28px;margin-top:14px;outline:2px solid #fff;position:relative}.sun-editor .se-hue-gradient-container .se-hue-gradient{background:linear-gradient(90deg,#000,#fff);cursor:pointer;height:28px;position:relative}.sun-editor .se-hue-gradient-container .se-hue-gradient-pointer{background-color:initial;border:2px solid #fff;border-radius:50%;box-shadow:0 0 2px #000;height:14px;left:calc(100% - 14px);outline:2px solid #000;pointer-events:none;position:absolute;top:14px;transform:translate(-50%,-50%);width:14px}.sun-editor .se-hue-final-hex{display:flex;margin-top:10px}.sun-editor .se-form-group{display:flex;height:auto;min-height:40px;padding:4px;width:100%}.sun-editor .se-form-group.se-form-w0{padding-left:0;padding-right:0}.sun-editor .se-form-group.se-form-h0{padding-bottom:0;padding-top:0}.sun-editor .se-btn-group input,.sun-editor .se-form-group input{border:1px solid var(--se-input-btn-border-color);display:inline-block;flex:auto;font-size:var(--se-btn-font-size);height:var(--se-input-btn-size);margin:1px 0;padding:0 4px;width:auto}.sun-editor .se-btn-group input{margin:1px 3px}.sun-editor .se-dropdown-form-group button,.sun-editor .se-form-group button{float:right;height:var(--se-input-btn-size);margin:1px;width:var(--se-input-btn-size)}.sun-editor .se-form-group.se-form-flex-btn button{flex:auto;float:none}.sun-editor .se-form-group .se-group-item{position:relative}.sun-editor .se-form-group label{display:inline-block;font-weight:700;margin-bottom:5px;max-width:100%}.sun-editor .se-form-group-label{height:auto;padding:0 4px;width:100%}.sun-editor .se-form-group-label label{font-size:var(--se-main-font-size);font-weight:700}.sun-editor .se-dropdown .se-form-group input{color:var(--se-dropdown-font-color);height:var(--se-input-btn-size)}.sun-editor .se-dropdown .se-form-group .se-color-input:focus{border-bottom:3px solid var(--se-main-outline-color)}.sun-editor .se-wrapper{display:flex;height:auto;overflow:hidden;position:relative!important;width:100%;z-index:1}.sun-editor .se-wrapper .se-wrapper-inner{height:100%;min-height:var(--se-min-height)}.sun-editor .se-wrapper .se-wrapper-inner,.sun-editor body.sun-editor-editable{max-width:100%;overflow-x:auto;overflow-y:auto;width:100%;-webkit-overflow-scrolling:touch;user-select:auto;-o-user-select:auto;-moz-user-select:auto;-khtml-user-select:auto;-webkit-user-select:auto;-ms-user-select:auto}.sun-editor .se-wrapper .se-wrapper-inner:focus,.sun-editor body.sun-editor-editable:focus{outline:none}.sun-editor .se-wrapper[style*="--se-editor-inner-width"] .se-wrapper-inner{padding-inline:max(var(--se-edit-inner-padding),calc((100% - var(--se-editor-inner-width))/2))}.sun-editor .se-wrapper.se-mode-block[style*="--se-editor-inner-width"] .se-wrapper-inner{padding-inline-start:max(var(--se-edit-inner-padding),calc((100% - var(--se-editor-inner-width))/2 - var(--se-block-handle-area-width)))}.sun-editor .se-wrapper .se-code-wrapper{overflow:hidden;width:100%}.sun-editor .se-wrapper .se-code-wrapper>div{flex:1;min-width:0}.sun-editor .se-wrapper .se-code-wrapper .se-code-view-line{background-color:var(--se-code-view-line-background-color);color:var(--se-code-view-line-color);font-size:var(--se-main-font-size);line-height:1.5;overflow:hidden;padding:4px 6px;resize:none!important;text-align:right;width:50px}.sun-editor .se-wrapper .se-code-viewer{background-color:var(--se-code-view-background-color);color:var(--se-code-view-color);flex:1;font-family:var(--se-codeview-font-family);font-size:var(--se-main-font-size);line-height:1.5;margin:0;min-width:0;overflow-x:auto;padding:4px;resize:none!important;tab-size:4;white-space:pre;word-wrap:normal}.sun-editor .se-wrapper .se-markdown-wrapper{overflow:hidden;width:100%}.sun-editor .se-wrapper .se-markdown-wrapper .se-markdown-view-line{background-color:var(--se-markdown-view-line-background-color);color:var(--se-markdown-view-line-color);font-size:var(--se-main-font-size);line-height:1.5;overflow:hidden;padding:4px 6px;resize:none!important;text-align:right;width:50px}.sun-editor .se-wrapper .se-markdown-viewer{background-color:var(--se-markdown-view-background-color);color:var(--se-markdown-view-color);flex:1;font-family:var(--se-markdown-font-family);font-size:var(--se-main-font-size);line-height:1.5;margin:0;min-width:0;overflow-x:auto;padding:4px;resize:none!important;tab-size:4;white-space:pre;word-wrap:normal}.sun-editor .se-wrapper .se-wrapper-wysiwyg{caret-color:var(--se-caret-color);display:block;position:relative}.sun-editor-editable[contenteditable=true] .katex *,.sun-editor-editable[contenteditable=true] .se-disable-pointer *,.sun-editor-editable[contenteditable=true] .se-math *{pointer-events:none}.sun-editor .se-wrapper .se-placeholder{backface-visibility:hidden;-webkit-backface-visibility:hidden;-moz-backface-visibility:hidden;color:var(--se-main-outline-color);display:none;font-size:var(--se-main-font-size);left:0;line-height:1.5;margin:0;overflow:hidden;padding:var(--se-edit-inner-padding);pointer-events:none;position:absolute;right:0;text-overflow:ellipsis;top:0;white-space:nowrap;z-index:1}.sun-editor .se-wrapper .se-placeholder-line{position:relative}.sun-editor .se-wrapper .se-placeholder-line:before{box-sizing:border-box;color:var(--se-main-outline-color);content:attr(data-se-placeholder-line);inset:0;overflow:hidden;padding:inherit;pointer-events:none;position:absolute;text-align:inherit;text-overflow:ellipsis;user-select:none;-webkit-user-select:none;white-space:nowrap}.sun-editor .se-wrapper li.se-placeholder-line{overflow:hidden}.sun-editor .se-wrapper li.se-placeholder-line:before{inset:auto;max-width:100%;padding:0}.sun-editor .se-status-bar{background-color:var(--se-main-background-color);border-top:1px solid var(--se-main-divider-color);cursor:ns-resize;display:flex;height:auto;min-height:20px;padding:0 4px;width:auto}.sun-editor .se-status-bar.se-resizing-none{cursor:default}.sun-editor .se-back-wrapper{background-color:initial;cursor:default;display:none;height:100%;left:0;position:fixed;top:0;user-select:none;-o-user-select:none;-moz-user-select:none;-khtml-user-select:none;-webkit-user-select:none;-ms-user-select:none;width:100%;z-index:2147483647}.sun-editor .se-status-bar .se-navigation{flex:auto;line-height:1.5}.sun-editor .se-status-bar .se-navigation,.sun-editor .se-status-bar .se-word-counter-wrapper{background:#0000;color:var(--se-statusbar-font-color);font-size:var(--se-statusbar-font-size);height:auto;margin:0;padding:0;position:relative;width:auto}.sun-editor .se-status-bar .se-word-counter-wrapper .se-word-label{margin-right:4px}.sun-editor .se-status-bar .se-char-counter-wrapper.se-with-word-counter{margin-left:.6em}.sun-editor .se-status-bar .se-char-counter-wrapper{background:#0000;color:var(--se-statusbar-font-color);display:block;flex:none;font-size:var(--se-statusbar-font-size);height:auto;margin:0;padding:0;position:relative;width:auto}.sun-editor .se-status-bar .se-char-counter-wrapper.se-blink{-webkit-animation:blinker .2s linear infinite;animation:blinker .2s linear infinite;color:var(--se-error-color)}.sun-editor .se-status-bar .se-char-counter-wrapper .se-char-label{margin-right:4px}.sun-editor .se-modal-area{display:none;height:100%;left:0;position:fixed;top:0;width:100%;z-index:2147483646}.sun-editor .se-modal-area.se-backdrop-show{display:block}.sun-editor .se-modal-area button,.sun-editor .se-modal-area input,.sun-editor .se-modal-area label{color:var(--se-main-color);font-size:var(--se-modal-input-font-size);line-height:1.5;margin:0}.sun-editor .se-modal-area .se-modal-back{background-color:var(--se-overlay-background-color);opacity:.5}.sun-editor .se-modal-area .se-modal-back,.sun-editor .se-modal-area .se-modal-inner{height:100%;left:0;position:absolute;top:0;width:100%}.sun-editor .se-modal-area .se-modal-inner .se-modal-content{-webkit-background-clip:padding-box;background-clip:padding-box;background-color:var(--se-modal-background-color);border:1px solid #0003;border-radius:var(--se-border-radius-lg);box-shadow:var(--se-shadow-layer);color:var(--se-modal-color);display:none;margin:1.75rem auto;max-width:500px;outline:0;position:relative;width:auto}.sun-editor .se-modal-area .se-modal-inner .se-modal-content.se-modal-show{display:block}.sun-editor .se-modal-area .se-modal-inner .se-modal-content .se-modal-resize-handle-w{bottom:0;cursor:ns-resize;display:block;height:10px;margin:0;position:relative;width:100%}.sun-editor .se-modal-area .se-modal-inner .se-modal-content .se-modal-resize-handle-w:before{background-color:var(--se-main-outline-color);content:"";display:block;height:1px;margin:1px 0;position:relative;width:100%}.sun-editor .se-modal-area .se-modal-inner .se-modal-content .se-modal-resize-handle-h{cursor:ew-resize;display:block;height:calc(100% - 27px);position:absolute;right:0;top:15px;width:10px}.sun-editor .se-modal-area .se-modal-inner .se-modal-content .se-modal-resize-handle-h:before{background-color:var(--se-main-outline-color);content:"";display:block;height:100%;margin:0 1px;position:relative;width:1px}.sun-editor .se-modal-area .se-modal-inner .se-modal-content .se-modal-resize-handle-c{bottom:1px;cursor:nwse-resize;display:block;height:9px;position:absolute;right:4px;width:9px}.sun-editor .se-modal-area .se-modal-inner .se-modal-content .se-modal-resize-handle-c:after,.sun-editor .se-modal-area .se-modal-inner .se-modal-content .se-modal-resize-handle-c:before{background-color:var(--se-main-outline-color);content:"";display:block;position:absolute}.sun-editor .se-modal-area .se-modal-inner .se-modal-content .se-modal-resize-handle-c:before{height:2px;left:0;top:50%;transform:translateY(-50%);width:100%}.sun-editor .se-modal-area .se-modal-inner .se-modal-content .se-modal-resize-handle-c:after{height:100%;left:50%;top:0;transform:translateX(-50%);width:2px}.sun-editor .se-modal-area .se-modal-inner .se-modal-content .se-modal-resize-handle-c.active:after,.sun-editor .se-modal-area .se-modal-inner .se-modal-content .se-modal-resize-handle-c.active:before,.sun-editor .se-modal-area .se-modal-inner .se-modal-content .se-modal-resize-handle-c:hover:after,.sun-editor .se-modal-area .se-modal-inner .se-modal-content .se-modal-resize-handle-c:hover:before,.sun-editor .se-modal-area .se-modal-inner .se-modal-content .se-modal-resize-handle-h.active:before,.sun-editor .se-modal-area .se-modal-inner .se-modal-content .se-modal-resize-handle-h:hover:before,.sun-editor .se-modal-area .se-modal-inner .se-modal-content .se-modal-resize-handle-w.active:before,.sun-editor .se-modal-area .se-modal-inner .se-modal-content .se-modal-resize-handle-w:hover:before{background-color:var(--se-active-dark4-color)}.sun-editor .se-modal-area .se-modal-inner .se-modal-content.se-modal-large{max-width:750px;width:100%}.sun-editor .se-modal-area .se-modal-inner .se-modal-content.se-modal-large .se-modal-body{height:50vh}.sun-editor .se-modal-area .se-modal-inner .se-modal-content.se-modal-responsive{height:-webkit-max-content;height:-moz-max-content;height:max-content;max-height:90vh;max-width:100%;width:-webkit-max-content;width:-moz-max-content;width:max-content}@media screen and (max-width:509px){.sun-editor .se-modal-area .se-modal-inner .se-modal-content{max-width:100%!important;min-width:100%!important;width:100%!important}}.sun-editor .se-modal-area .se-modal-inner .se-modal-content.se-modal-responsive .se-modal-resize-form{max-width:100%}.sun-editor .se-modal-area .se-modal-inner .se-modal-content label{display:inline-block;font-weight:700;margin-bottom:5px;max-width:100%}.sun-editor .se-modal-area .se-modal-inner .se-modal-content .se-btn-primary{border-radius:var(--se-border-radius);color:#fff;display:inline-block;font-size:var(--se-modal-input-font-size);font-weight:500;line-height:1.4;margin:0 0 10px!important;padding:5px 11px;text-align:center;touch-action:manipulation;vertical-align:middle;white-space:nowrap}.sun-editor .se-modal-area .se-modal-inner .se-modal-header{border-bottom:1px solid var(--se-modal-border-color);height:50px;padding:6px 15px}.sun-editor .se-modal-area .se-modal-inner .se-modal-header .se-close-btn{filter:alpha(opacity=100);float:right;font-weight:700;opacity:1;text-shadow:0 1px 0 var(--se-main-background-color)}.sun-editor .se-modal-area .se-modal-inner .se-modal-header .se-modal-title{float:left;font-size:var(--se-modal-title-font-size);font-weight:700;line-height:2.5;margin:0;padding:0}.sun-editor .se-modal-area .se-modal-inner .se-modal-body{padding:15px 15px 10px;position:relative}.sun-editor .se-modal-area .se-modal-inner .se-modal-body-top{padding:0 15px 5px;position:relative}.sun-editor .se-modal-area .se-modal-inner .se-modal-body-bottom{padding:5px 15px 0;position:relative}.sun-editor .se-modal-area .se-modal-inner .se-modal-hr{border-bottom:1px dashed var(--se-modal-color);margin-bottom:6px}.sun-editor .se-modal-area .se-modal-inner .se-modal-form{margin-bottom:10px}.sun-editor .se-modal-area .se-modal-inner .se-modal-form .se-modal-flex-form{display:flex;position:relative}.sun-editor .se-modal-area .se-modal-inner .se-modal-form .se-modal-flex-form .se-modal-flex-group{border:1px dashed var(--se-modal-border-color);margin-right:4px;padding:4px 0 4px 4px}.sun-editor .se-modal-area .se-modal-inner .se-modal-form .se-modal-flex-form .se-btn{border:1px solid var(--se-input-btn-border-color);margin-left:0;margin-right:4px}.sun-editor .se-modal-area .se-modal-inner .se-modal-form-footer{margin-bottom:0;margin-top:10px}.sun-editor .se-modal-area .se-modal-inner input:disabled{background-color:var(--se-modal-input-disabled-background-color)}.sun-editor .se-modal-area .se-modal-inner .se-modal-size-text{width:100%}.sun-editor .se-modal-area .se-modal-inner .se-modal-size-text .size-h,.sun-editor .se-modal-area .se-modal-inner .se-modal-size-text .size-w{text-align:center;width:var(--se-modal-input-width)}.sun-editor .se-modal-area .se-modal-inner .se-modal-size-x{margin:0 8px;text-align:center;width:25px}.sun-editor .se-modal-area .se-modal-inner .se-modal-footer{border-top:1px solid var(--se-modal-border-color);height:auto;min-height:55px;padding:10px 15px 0;text-align:right}.sun-editor .se-modal-area .se-modal-inner .se-modal-footer .se-btn{float:left}.sun-editor .se-modal-area .se-modal-inner .se-modal-footer>div{float:left;line-height:1.7}.sun-editor .se-modal-area .se-modal-inner .se-modal-footer>div>label{margin:0 5px 0 0}.sun-editor .se-modal-area .se-modal-inner .se-modal-btn-radio{margin-left:12px;margin-right:6px}.sun-editor .se-modal-area .se-modal-inner .se-modal-btn-check{margin-left:12px;margin-right:4px}.sun-editor .se-modal-area .se-modal-inner .se-modal-btn-check:disabled+span{color:var(--se-modal-input-disabled-color)}.sun-editor .se-modal-area .se-modal-inner .se-modal-form-footer .se-modal-btn-check{margin-left:0;margin-right:4px}.sun-editor .se-modal-area .se-modal-inner .se-modal-form-footer label:first-child{margin-left:0;margin-right:16px}.sun-editor .se-modal-area .se-modal-inner .se-modal-form .se-modal-form-files{align-items:center;display:flex;position:relative}.sun-editor .se-modal-area .se-modal-inner .se-modal-form .se-modal-form-files>input{flex:auto}.sun-editor .se-modal-area .se-modal-inner .se-modal-form .se-modal-form-files .se-modal-files-edge-button{border:1px solid var(--se-input-btn-border-color);flex:none;margin-left:1px;opacity:.8}.sun-editor .se-modal-area .se-modal-inner .se-modal-form .se-input-select{display:inline-block;font-size:var(--se-modal-input-font-size);height:var(--se-input-btn-size);line-height:1.4;text-align:center;width:auto}.sun-editor .se-modal-area .se-modal-inner .se-modal-form .se-input-control{display:inline-block;font-size:var(--se-modal-input-font-size);height:var(--se-input-btn-size);line-height:1.4;text-align:center;width:var(--se-modal-input-width)}.sun-editor .se-modal-area .se-modal-inner .se-modal-form .se-flex-input-wrapper{display:block;height:auto;padding:0;position:relative;width:100%}.sun-editor .se-modal-area .se-modal-inner .se-modal-form .se-flex-input-wrapper>.se-input-form-abs{background-color:var(--se-modal-file-input-background-color);border:2px dashed var(--se-input-btn-border-color);display:block;height:100%;margin:0;padding:0;pointer-events:none;position:absolute;width:100%}.sun-editor .se-modal-area .se-modal-inner .se-modal-form .se-flex-input-wrapper>.se-input-form-abs *{pointer-events:none;vertical-align:middle}.sun-editor .se-modal-area .se-modal-inner .se-modal-form .se-flex-input-wrapper>.se-input-form-abs>div{display:block;height:100%;margin:auto;padding-top:3px;position:relative;width:100%}.sun-editor + .se-modal-area + .se-modal-inner + .se-modal-form + .se-flex-input-wrapper>.se-input-form-abs>div + .se-input-file-w{margin:auto;max-width:100%;padding:0 4px;width:-webkit-max-content;width:-moz-max-content;width:max-content}.sun-editor + .se-modal-area + .se-modal-inner + .se-modal-form + .se-flex-input-wrapper>.se-input-form-abs>div + .se-input-file-icon-files,.sun-editor + .se-modal-area + .se-modal-inner + .se-modal-form + .se-flex-input-wrapper>.se-input-form-abs>div + .se-input-file-icon-up{display:inline-block;width:20px}.sun-editor + .se-modal-area + .se-modal-inner + .se-modal-form + .se-flex-input-wrapper>.se-input-form-abs>div + .se-input-file-icon-files{display:none}.sun-editor + .se-modal-area + .se-modal-inner + .se-modal-form + .se-flex-input-wrapper>.se-input-form-abs>div + .se-input-file-cnt{display:inline;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.sun-editor .se-modal-area .se-modal-inner .se-modal-form .se-input-form{display:block;font-size:var(--se-modal-input-font-size);height:var(--se-input-btn-size);line-height:1.4;padding:0 4px;width:100%}.sun-editor .se-modal-area .se-modal-inner .se-modal-form .se-input-form.se-input-url{direction:ltr}.sun-editor .se-modal-area .se-modal-inner .se-modal-form .se-input-form.se-input-url:disabled{color:var(--se-modal-input-disabled-color);text-decoration:line-through}.sun-editor .se-modal-area .se-modal-inner .se-modal-form .se-modal-ratio{margin-left:4px;width:var(--se-modal-input-width)}.sun-editor .se-modal-area .se-modal-inner .se-modal-form a{color:var(--se-modal-anchor-color)}.sun-editor .se-modal-area .se-modal-inner .se-modal-btn-revert{border:1px solid var(--se-input-btn-border-color);float:right}.sun-editor .se-modal-tabs{border-bottom:1px solid var(--se-modal-border-color);height:25px;width:100%}.sun-editor .se-modal-tabs button{background-color:var(--se-modal-border-color);border-right:1px solid var(--se-modal-border-color);float:left;outline:none;padding:2px 13px;transition:.3s}.sun-editor .se-modal-tabs button.active,.sun-editor .se-modal-tabs button:hover{background-color:var(--se-main-background-color)}.sun-editor .se-modal-tabs button.active{border-bottom:0}.sun-editor .se-modal-area .se-modal-inner .se-modal-form .se-input-form.se-math-exp{border:1px solid var(--se-active-dark4-color);direction:ltr;font-size:var(--se-main-font-size);padding:4px}.sun-editor .se-modal-area .se-modal-inner .se-modal-form .se-input-select.se-math-size{height:28px;margin-left:1em;width:6em}.sun-editor .se-modal-area .se-modal-inner .se-modal-form .se-math-preview{font-size:var(--se-main-font-size)}.sun-editor .se-modal-area .se-modal-inner .se-modal-form .se-math-preview>span{box-shadow:0 0 0 .1rem var(--se-active-light3-color);display:inline-block}.sun-editor .se-modal-area .se-modal-inner .se-modal-form .se-math-preview>span *{direction:ltr}.sun-editor .se-modal-area .se-modal-inner .se-modal-form .se-math-preview>.se-math-error{box-shadow:0 0 0 .1rem var(--se-error-light3-color);color:var(--se-error-color)}.sun-editor .se-modal-area .se-modal-inner .se-modal-form .se-math-preview>.se-math-error svg{color:var(--se-error-color);height:30px;width:auto}.sun-editor .se-modal-area .se-modal-inner .se-modal-form .se-math-preview .MathJax{margin:.5em 0!important}.sun-editor .se-modal-area .se-modal-inner .se-link-preview{background-color:initial;color:var(--se-modal-preview-color);display:block;font-family:inherit;font-size:var(--se-main-font-size);font-weight:400;height:auto;max-height:none;overflow:hidden;padding-top:4px;text-overflow:ellipsis;white-space:pre;word-break:break-all}.sun-editor .se-modal-area .se-modal-inner .se-anchor-preview-form{display:flex;margin-top:4px;width:100%}.sun-editor .se-modal-area .se-modal-inner .se-anchor-preview-form .se-svg.se-anchor-preview-icon{color:var(--se-active-dark3-color);display:none;flex:unset;line-height:1;margin:2px}.sun-editor .se-modal-area .se-modal-inner .se-anchor-preview-form .se-link-preview{flex:1;margin:0}.sun-editor .se-modal-area .se-modal-inner .se-anchor-rel{height:var(--se-input-btn-size);position:relative}.sun-editor .se-modal-area .se-modal-inner .se-anchor-rel-btn{border-width:1px}.sun-editor .se-modal-area .se-modal-inner .se-anchor-rel-wrapper{align-items:center;display:flex;height:var(--se-input-btn-size);line-height:1;padding:0 6px}.sun-editor .se-modal-area .se-modal-inner .se-anchor-rel-preview{overflow-wrap:break-word;text-align:left;white-space:pre-wrap;word-break:break-word}.sun-editor .se-modal-area .se-modal-inner .se-modal-body .se-drawing-canvas{outline:1px solid var(--se-main-outline-color)}.sun-editor .se-controller{display:none;overflow:visible;position:absolute;z-index:2147483646}.sun-editor .se-controller[popover]:popover-open{border:1px solid var(--se-controller-border-color);inset:unset;letter-spacing:normal;margin:0;padding:2px 2px 0;position:absolute;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;word-break:normal;word-spacing:normal;word-wrap:normal;-webkit-background-clip:padding-box;background-clip:padding-box;background-color:var(--se-controller-background-color);border-radius:var(--se-border-radius);color:var(--se-controller-color);line-break:auto;white-space:normal}.sun-editor .se-controller.se-empty-controller{border:none!important;padding:0!important}.sun-editor .se-controller.se-controller-simple-input{padding:4px 3px 0}.sun-editor .se-controller:not(.se-resizing-container){box-shadow:var(--se-shadow-controller)}.sun-editor-editable[contenteditable=true] figure a,.sun-editor-editable[contenteditable=true] figure iframe,.sun-editor-editable[contenteditable=true] figure img,.sun-editor-editable[contenteditable=true] figure video{z-index:0}.sun-editor-editable[contenteditable=true] figure figcaption{display:block;z-index:11}.sun-editor-editable[contenteditable=true]:not(.se-read-only) figure:not(.se-input-component):after{background:#0000;bottom:0;content:"";cursor:default;display:block;left:0;position:absolute;right:0;top:0;z-index:10}.sun-editor-editable[contenteditable=true] .se-component{outline:1px dashed var(--se-main-divider-color)}.sun-editor-editable[contenteditable=true] figure,.sun-editor-editable[contenteditable=true] hr{outline:2px solid #0000}.sun-editor-editable[contenteditable=true] .se-component.se-component-selected>figure,.sun-editor-editable[contenteditable=true] .se-component:not(:has(figure)).se-component-selected,.sun-editor-editable[contenteditable=true] figure.se-component-selected{outline:2px solid var(--se-active-dark-color);transition:outline-color .2s ease-in-out,outline-width .2s ease-in-out}.sun-editor-editable[contenteditable=true] + .se-component + figure.se-figure-selected:not(.se-figure-over-selected):after{pointer-events:none}.sun-editor-editable[contenteditable=true] .se-copy{background-color:var(--se-main-border-color);box-shadow:0 0 0 .25rem var(--se-active-dark5-color);opacity:.3;transition:box-shadow .15s ease-in-out}.sun-editor-editable[contenteditable=true] .se-component:not(:has(figure)).se-component-selected.se-drag-over,.sun-editor-editable[contenteditable=true] .se-figure-selected.se-drag-over,.sun-editor-editable[contenteditable=true] hr.se-component-selected.se-drag-over{outline:3px solid var(--se-drag-over-color)!important}.sun-editor-editable[contenteditable=true] figure.se-drag-over>iframe{pointer-events:none}.sun-editor .se-controller .se-controller-display{font-size:var(--se-main-font-size);margin:4px 0;padding:0 10px}.sun-editor .se-controller .se-btn-group{display:flex;left:0;margin:0;padding:0 0 2px;position:relative;top:0}.sun-editor .se-controller .se-btn-group .se-btn-group-sub{display:none;left:50%;min-width:auto;width:-webkit-max-content;width:-moz-max-content;width:max-content}.sun-editor .se-controller .se-btn-group .se-btn-group-sub button{margin:0;min-width:72px}.sun-editor .se-controller .se-btn-group button{border:none;border-radius:var(--se-border-radius);display:inline-block;font-size:var(--se-btn-font-size);font-weight:400;height:auto;line-height:1.5;margin:1px;min-height:var(--se-input-btn-size);position:relative;text-align:center;touch-action:manipulation;white-space:nowrap}.sun-editor .se-controller .se-controller-content{left:0;margin:0;padding:0 0 2px;position:relative;top:0}.sun-editor .se-controller .se-controller-header{border-bottom:1px solid var(--se-modal-border-color);height:38px;padding:4px;width:100%}.sun-editor .se-controller .se-controller-body{font-size:var(--se-main-font-size);padding:4px 4px 1px;position:relative;width:100%}.sun-editor .se-controller .se-controller-body .se-btn:disabled,.sun-editor .se-controller .se-controller-body button:disabled,.sun-editor .se-controller .se-controller-body input:disabled{background-color:var(--se-main-shadow-color)}.sun-editor .se-controller .se-controller-header .se-close-btn{filter:alpha(opacity=100);float:right;font-weight:700;height:28px;min-height:28px;opacity:1;text-shadow:0 1px 0 var(--se-main-background-color);width:28px}.sun-editor .se-controller .se-controller-header .se-controller-title{float:left;font-size:var(--se-main-font-size);font-weight:700;line-height:2.2;margin:0;padding:0}.sun-editor .se-controller-resizing{font-size:var(--se-controller-font-size);font-style:normal;font-weight:400;line-height:1.4}.sun-editor .se-resizing-container{backface-visibility:hidden;-webkit-backface-visibility:hidden;-moz-backface-visibility:hidden;background-color:initial!important;border:0;display:none;outline:none;padding:0;pointer-events:none;position:absolute;z-index:6}.sun-editor .se-drag-handle{background-color:var(--se-active-dark-color);border:0;color:var(--se-main-background-color);cursor:move;display:none;height:20px;outline:2px solid #0000;padding:1px;pointer-events:auto;position:absolute;width:20px;z-index:2147483646}.sun-editor .se-drag-handle.se-drag-handle-full{cursor:default}.sun-editor .se-drag-handle>svg{max-height:100%;max-width:100%;pointer-events:none}.sun-editor .se-drag-handle:hover{background-color:var(--se-drag-over-color)}.sun-editor .se-drag-handle.se-dragging{opacity:0}.sun-editor .se-resizing-container .se-resize-dot{border:0;display:inline-block;outline:2px solid var(--se-active-dark-color);padding:0;position:absolute}.sun-editor .se-resizing-container.se-resize-ing .se-resize-dot{outline:2px solid var(--se-active-dark3-color)}.sun-editor .se-resizing-container .se-resize-dot>span{background-color:var(--se-active-dark3-color);border:1px solid var(--se-active-dark3-color);border-radius:1px;height:7px;pointer-events:auto;position:absolute;width:7px}.sun-editor .se-resizing-container .se-resize-dot>span.tl{border-radius:4px;cursor:nwse-resize;left:-6px;top:-6px}.sun-editor .se-resizing-container .se-resize-dot>span.tr{border-radius:4px;cursor:nesw-resize;right:-6px;top:-6px}.sun-editor .se-resizing-container .se-resize-dot>span.bl{border-radius:4px;bottom:-6px;cursor:nesw-resize;left:-6px}.sun-editor .se-resizing-container .se-resize-dot>span.br{border-radius:4px;bottom:-6px;cursor:nwse-resize;right:-6px}.sun-editor .se-resizing-container .se-resize-dot>span.lw{bottom:calc(50% - 4px);cursor:ew-resize;left:-7px;width:5px}.sun-editor .se-resizing-container .se-resize-dot>span.th{cursor:ns-resize;height:5px;left:calc(50% - 4px);top:-7px}.sun-editor .se-resizing-container .se-resize-dot>span.rw{bottom:calc(50% - 4px);cursor:ew-resize;right:-7px;width:5px}.sun-editor .se-resizing-container .se-resize-dot>span.bh{bottom:-7px;cursor:ns-resize;height:5px;right:calc(50% - 4px)}.sun-editor .se-resizing-container .se-resize-display{background-color:var(--se-main-font-color);border-radius:var(--se-border-radius);bottom:0;color:var(--se-main-background-color);font-size:var(--se-btn-font-size);left:auto;margin:2px;opacity:.75;padding:5px;pointer-events:none;position:absolute;right:0}.sun-editor .se-resizing-container.se-resize-ing .se-resize-display{opacity:1}.sun-editor .se-controller-table,.sun-editor .se-controller-table-cell{font-size:var(--se-controller-font-size);font-style:normal;font-weight:400;line-height:1.4;width:auto}.sun-editor .se-controller.se-table-props .se-border-style,.sun-editor .se-controller.se-table-props .se-color-input{width:var(--se-modal-input-width)}.sun-editor .se-controller.se-table-props .__se__border_size{width:52px}.sun-editor .se-controller.se-table-props .se-table-props-align li{margin-right:2px}.sun-editor .se-controller.se-table-props .se-table-props-align .se-form-group div:last-child{flex:auto;margin:0 8px}.sun-editor .se-controller-link{font-size:var(--se-controller-font-size);font-style:normal;font-weight:400;line-height:1.4}.sun-editor .se-controller-link:after,.sun-editor .se-controller-link:before{box-sizing:border-box}.sun-editor .se-controller-link .link-content{margin:0;padding:0}.sun-editor .se-controller-link .link-content a{color:var(--se-active-dark3-color);display:inline-block;margin-left:5px;max-width:200px;overflow:hidden;text-overflow:ellipsis;vertical-align:middle;white-space:nowrap}.sun-editor .se-select-menu{background-color:var(--se-main-background-color);border:1px solid var(--se-main-divider-color);border-radius:var(--se-border-radius-lg);box-shadow:var(--se-shadow-layer);display:none;height:auto;left:0;margin:0;min-width:auto;outline:0 none;overflow-x:visible;overflow-y:visible;overflow:visible;padding:4px 0;position:absolute;top:0;width:-webkit-max-content;width:-moz-max-content;width:max-content;z-index:2147483646}.sun-editor .se-select-menu ul{margin:0;max-width:100%;min-width:-moz-max-content;min-width:-webkit-max-content;min-width:-o-max-content;min-width:-ms-max-content;padding:0;width:auto;word-break:break-all}.sun-editor .se-select-menu .se-select-item{border-radius:var(--se-border-radius);cursor:pointer;font-size:var(--se-btn-font-size);line-height:32px;list-style:none;margin:1px 4px;min-height:32px;padding:0 6px;position:relative;transition:background-color .08s ease}.sun-editor .se-select-menu .se-select-item .se-btn-list{margin:0;min-height:32px;padding:0}.sun-editor .se-select-menu .se-select-item .se-btn-list>span{margin:0;padding:0}.sun-editor .se-select-menu .se-select-item .se-select-on,.sun-editor .se-select-menu .se-select-item.se-select-on{color:var(--se-active-dark3-color)}.sun-editor .se-select-menu.se-select-menu-mouse-move .se-select-item:hover,.sun-editor .se-select-menu:not(.se-select-menu-mouse-move) .se-select-item.se-select-cursor{background-color:var(--se-select-menu-hover-bg)}.sun-editor .se-select-menu.se-select-menu-mouse-move .se-select-item.__se__active,.sun-editor .se-select-menu.se-select-menu-mouse-move .se-select-item:active{background-color:var(--se-select-menu-active-bg)}.sun-editor .se-select-menu .se-select-item>.se-cmd-row{align-items:center;background:#0000;border:0;color:inherit;cursor:pointer;display:flex;font:inherit;line-height:1;margin:0;min-height:32px;padding:0;text-align:inherit;width:100%}.sun-editor .se-select-menu .se-select-item>.se-cmd-row.active{color:var(--se-active-color)}.sun-editor .se-select-menu .se-select-item>.se-cmd-row:disabled{cursor:not-allowed;opacity:.4}.sun-editor .se-modal-form-files .se-select-menu{height:auto;width:100%}.sun-editor .se-select-menu.se-figure-select-list{width:74px}.sun-editor .se-select-menu .se-has-submenu{position:relative}.sun-editor .se-select-menu .se-select-item:has(>.se-submenu-arrow){padding-right:26px}.sun-editor .se-select-menu.se-block-action-menu .se-select-item:has(>.se-submenu-arrow){padding-right:28px}.sun-editor .se-select-menu .se-submenu-arrow{align-items:center;display:inline-flex;height:16px;opacity:.8;pointer-events:none;position:absolute;right:4px;top:50%;transform:translateY(-50%);width:16px}.sun-editor .se-select-menu .se-submenu-arrow svg{height:100%;width:100%}.sun-editor .se-select-menu>.se-select-submenu{background-color:var(--se-main-background-color);border:1px solid var(--se-main-divider-color);border-radius:var(--se-border-radius-lg);box-shadow:var(--se-shadow-layer);display:none;min-width:100px;padding:4px 0;position:absolute;z-index:1}.sun-editor .se-select-menu>.se-select-submenu[popover]{color:inherit;inset:unset;margin:0;position:fixed}.sun-editor .se-select-menu>.se-select-submenu[popover]:popover-open{display:block}.sun-editor .se-select-menu.se-rtl,.sun-editor .se-select-menu.se-rtl>.se-select-submenu{direction:rtl}.sun-editor .se-select-menu.se-rtl .se-submenu-arrow{left:4px;right:auto}.sun-editor .se-select-menu.se-rtl .se-select-item:has(>.se-submenu-arrow){padding-left:26px;padding-right:6px}.sun-editor .se-select-menu.se-rtl.se-block-action-menu .se-select-item:has(>.se-submenu-arrow){padding-left:28px;padding-right:10px}.sun-editor .se-select-menu.se-rtl .se-block-menu-label-full{padding-left:0;padding-right:22px}.sun-editor .se-browser{display:none;height:100%;left:0;position:fixed;top:0;width:100%;z-index:2147483646}.sun-editor .se-browser button,.sun-editor .se-browser input,.sun-editor .se-browser label{color:var(--se-main-color);font-size:var(--se-modal-input-font-size);line-height:1.5;margin:0}.sun-editor .se-browser .se-browser-back{background-color:var(--se-overlay-background-color);opacity:.5}.sun-editor .se-browser .se-browser-back,.sun-editor .se-browser .se-browser-inner{display:block;height:100%;left:0;position:absolute;top:0;width:100%}.sun-editor .se-browser .se-browser-inner .se-browser-content{-webkit-background-clip:padding-box;background-clip:padding-box;background-color:var(--se-main-background-color);border:1px solid #0003;border-radius:var(--se-border-radius-lg);box-shadow:var(--se-shadow-layer);margin:20px auto;max-width:100%;outline:0;position:relative;width:1024px}.sun-editor .se-browser .se-browser-header{border-bottom:1px solid var(--se-modal-border-color);height:auto;min-height:50px;padding:6px 15px}.sun-editor .se-browser .se-browser-header .se-browser-close{filter:alpha(opacity=100);float:right;font-weight:700;opacity:1;text-shadow:0 1px 0 var(--se-main-background-color)}.sun-editor .se-browser .se-browser-header .se-browser-title{font-size:var(--se-browser-title-font-size);font-weight:700;line-height:2.2;margin:0;padding:0}.sun-editor .se-browser .se-browser-wrapper{display:flex;position:relative}.sun-editor .se-browser .se-browser-main{flex:auto}.sun-editor .se-browser .se-browser-bar{border-bottom:1px solid var(--se-modal-border-color);height:auto;padding:0 15px}.sun-editor .se-browser .se-browser-side>div{overflow-y:auto}.sun-editor .se-browser .se-browser-side>div:not(.se-side-open-btn){border-right:1px solid var(--se-modal-border-color);color:var(--se-edit-font-color);flex-direction:row;height:100%;line-height:1.5;min-width:220px;padding:4px}.sun-editor .se-browser .se-browser-side .se-menu-icon{display:inline-block;height:16px;margin:-1px 10px 0 0;vertical-align:middle;width:16px}.sun-editor .se-browser .se-browser-search .se-side-open-btn{border:1px solid var(--se-input-btn-border-color);color:var(--se-edit-font-color);display:none;margin:8px 0 0 8px;opacity:.8}.sun-editor .se-browser .se-browser-side.se-side-show>div{display:block!important}.sun-editor .se-browser .se-browser-side>div .se-menu-hidden{display:none}.sun-editor .se-browser .se-menu-folder{cursor:pointer}.sun-editor .se-browser .se-menu-folder>div:not(.se-menu-child){display:flex;padding:8px 10px 8px 20px}.sun-editor .se-browser .se-menu-folder>div>button{margin-left:-20px}.sun-editor .se-browser .se-menu-folder .se-menu-folder-item{padding:8px 8px 8px 24px}.sun-editor .se-browser .se-menu-folder>div:not(.se-menu-child)>.se-menu-icon>*{padding-top:3px}.sun-editor .se-browser .se-menu-folder .se-menu-folder-item>.se-menu-icon>*{margin-top:-1px}.sun-editor .se-browser .se-menu-folder div:not(.se-menu-child):not(.active):hover{background-color:var(--se-main-divider-color);border-color:var(--se-main-border-color)}.sun-editor .se-browser .se-menu-folder div.active>button{color:var(--se-active-dark5-color)}.sun-editor .se-browser .se-browser-search .se-side-open-btn.active,.sun-editor .se-browser .se-menu-folder div.active{background-color:var(--se-active-light2-color);color:var(--se-active-dark5-color)}.sun-editor .se-browser .se-menu-folder.active{border-left:2px solid var(--se-active-dark4-color);margin-left:-2px}.sun-editor .se-browser .se-browser-tags{display:block;font-size:var(--se-main-font-size);margin-top:-5px;padding:0;text-align:left;width:100%}.sun-editor .se-browser .se-browser-tags a{-moz-background-clip:padding;-webkit-background-clip:padding-box;background-clip:padding-box;background-color:var(--se-main-divider-color);border-radius:32px;-moz-border-radius:32px;-webkit-border-radius:32px;color:var(--se-main-font-color);cursor:pointer;display:inline-block;margin:8px 0 8px 8px;padding:6px 12px;text-decoration:none}.sun-editor .se-browser .se-browser-search{display:flex;font-size:var(--se-main-font-size);height:48px;margin:0 -15px;padding:0;text-align:left;width:100%}.sun-editor .se-browser .se-browser-search .se-browser-search-form{display:flex;flex-direction:row;max-width:100%;width:400px}.sun-editor .se-browser .se-browser-search .se-browser-search-form>*{margin:8px}.sun-editor .se-browser .se-browser-search .se-browser-search-form>.se-btn{margin-left:0;margin-right:0}.sun-editor .se-browser .se-browser-search-input-wrap{flex:auto;position:relative}.sun-editor .se-browser .se-browser-search-input-wrap input{-moz-background-clip:padding;-webkit-background-clip:padding-box;background-clip:padding-box;background-color:initial;border-radius:var(--se-border-radius);-moz-border-radius:var(--se-border-radius);-webkit-border-radius:var(--se-border-radius);box-sizing:border-box;color:var(--se-main-font-color);padding:3px 24px 3px 6px;text-decoration:none;width:100%}.sun-editor .se-browser .se-browser-search-clear{opacity:.35;padding:0 2px;position:absolute;right:2px;top:50%;transform:translateY(-50%)}.sun-editor .se-browser .se-browser-search-clear:hover{opacity:.8}.sun-editor .se-browser .se-browser-search button{float:none}.sun-editor .se-browser .se-browser-tags a:hover{background-color:var(--se-main-divider-color);transition:background-color .2s ease-in-out}.sun-editor .se-browser .se-browser-tags a:active{background-color:var(--se-main-border-color)}.sun-editor .se-browser .se-browser-tags a.on{background-color:var(--se-active-light3-color);color:var(--se-active-dark3-color)}.sun-editor .se-browser .se-browser-tags a.on:hover{background-color:var(--se-active-light5-color);transition:background-color .2s ease-in-out}.sun-editor .se-browser .se-browser-tags a.on:active{background-color:var(--se-active-light5-color)}.sun-editor .se-browser .se-browser-body{height:auto;min-height:350px;overflow-y:auto;padding:10px;position:relative}.sun-editor .se-browser .se-browser-body .se-browser-list{position:relative;width:100%}@media screen and (max-width:992px){.sun-editor .se-browser .se-browser-inner .se-browser-content{width:748px}.sun-editor .se-browser .se-browser-side>div:not(.se-side-open-btn){min-width:180px}}@media screen and (max-width:768px){.sun-editor .se-browser .se-browser-inner .se-browser-content{width:600px}.sun-editor .se-browser .se-browser-side>div:not(.se-side-open-btn){min-width:150px}}@media screen and (max-width:552px){.sun-editor .se-browser .se-browser-side>div:not(.se-side-open-btn){display:none}.sun-editor .se-browser .se-browser-search .se-side-open-btn{display:block}.sun-editor .se-browser .se-browser-side{background-color:var(--se-main-background-color);height:calc(100% - 49px);opacity:.95;position:absolute;top:49px;z-index:2}}.sun-editor .se-browser .se-browser-list .se-file-item-column{display:block;float:left;height:auto;position:relative}.sun-editor .se-browser .se-browser-list.se-preview-list .se-file-item-column{margin:0 10px;width:calc(25% - 20px)}@media screen and (max-width:992px){.sun-editor .se-browser .se-browser-list.se-preview-list .se-file-item-column{width:calc(33% - 20px)}}@media screen and (max-width:768px){.sun-editor .se-browser .se-browser-list.se-preview-list .se-file-item-column{width:calc(50% - 20px)}}.sun-editor .se-browser .se-browser-list.se-preview-list .se-file-item-img{border-radius:var(--se-border-radius);cursor:pointer;display:block;height:auto;margin:10px 0;outline:0;position:relative;width:100%}.sun-editor .se-browser .se-browser-list.se-preview-list .se-file-item-img:hover{box-shadow:0 0 0 .2rem var(--se-active-color);opacity:.8;transition:box-shadow .1s ease-in-out}.sun-editor .se-browser .se-browser-list.se-preview-list .se-file-item-img>img{border-radius:var(--se-border-radius);display:block;height:auto;outline:0;position:relative;width:100%}.sun-editor .se-browser .se-browser-list.se-preview-list .se-file-item-img>.se-file-name-image{background-color:initial;border-bottom-left-radius:var(--se-border-radius);border-bottom-right-radius:var(--se-border-radius);bottom:0;color:var(--se-main-background-color);font-size:var(--se-main-font-size);height:30px;left:0;padding:5px 10px;pointer-events:none;position:absolute;width:100%;z-index:1}.sun-editor .se-browser .se-browser-list.se-preview-list .se-file-item-img>.se-file-name-image.se-file-name-back{background-color:var(--se-main-font-color);opacity:.6;pointer-events:none}.sun-editor .se-browser .se-file-name-image mark{background-color:var(--se-active-color);border-radius:2px;color:var(--se-active-font-color);padding:0 1px}.sun-editor .se-browser .se-browser-list.se-preview-list .se-file-item-img>*{align-items:center;display:flex;justify-content:center}.sun-editor .se-browser .se-browser-list.se-preview-list .se-file-item-img>.se-browser-empty-thumbnail{background-color:var(--se-active-light-color);border-radius:var(--se-border-radius);height:170px;max-height:100%;width:100%}.sun-editor .se-browser .se-browser-list.se-preview-list .se-file-item-img>.se-browser-empty-thumbnail>svg{color:var(--se-active-color);height:auto;margin-bottom:30px;max-width:100%;width:90px}.sun-editor .se-alert-content{background-color:var(--se-main-background-color);border:1px solid #0003;border-radius:var(--se-border-radius);box-shadow:var(--se-shadow-layer);height:auto;margin:auto;max-width:500px;opacity:0;padding:15px;position:relative;top:35%;transform:scale(.9);transition:opacity .25s ease,transform .25s ease;visibility:hidden;width:auto;word-break:break-all;z-index:7}.sun-editor .se-alert-content.se-modal-show{animation:se-alert-in .25s ease forwards;opacity:1;transform:scale(1);visibility:visible}.sun-editor .se-alert-content button{float:right;padding:0}.sun-editor .se-alert-content.se-alert-success{border-color:var(--se-success-light4-color);color:var(--se-success-color)}.sun-editor .se-alert-content.se-alert-error{border-color:var(--se-error-light4-color);color:var(--se-error-color)}.sun-editor .se-toast{background:#0000;display:none;height:100%;left:0;pointer-events:none;position:fixed;top:0;width:100%;z-index:2147483646}.sun-editor .se-toast .se-toast-container{background-color:var(--se-main-font-color);border:1px solid #0003;border-radius:var(--se-border-radius);box-shadow:var(--se-shadow-layer);color:var(--se-main-background-color);font-size:.9em;height:max-content;line-height:unset;margin:auto;max-width:100%;opacity:0;padding:7px;position:relative;text-align:center;top:35%;transform:scale(.9);transform:translateY(20px);transition:opacity .25s ease,transform .25s ease;width:max-content;word-break:break-all}.sun-editor .se-toast .se-toast-container.se-toast-show{animation:toast-in .3s ease-out forwards,toast-out .3s ease-in 3s forwards;opacity:1}.sun-editor .se-toast.se-toast-success .se-toast-container{background-color:var(--se-success-color);border-color:var(--se-success-light4-color)}.sun-editor .se-toast.se-toast-error .se-toast-container{background-color:var(--se-error-color);border-color:var(--se-error-light3-color)}.sun-editor input:not(.se-toolbar-btn):focus,.sun-editor select:focus,.sun-editor textarea:focus{border-color:var(--se-active-dark-color);box-shadow:0 0 0 .2rem var(--se-active-light3-color);outline:0;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out}.sun-editor .se-tooltip{font-size:var(--se-main-font-size);overflow:visible;position:relative}.sun-editor .se-tooltip .se-tooltip-inner{backface-visibility:hidden;-webkit-backface-visibility:hidden;-moz-backface-visibility:hidden;background:#0000;bottom:auto;display:block;float:none;height:auto;left:50%;line-height:1.5;margin:0;opacity:0;padding:0;pointer-events:none;position:absolute;top:120%;transition:opacity .13s ease;visibility:hidden;width:auto;z-index:1}.sun-editor .se-tooltip .se-tooltip-inner .se-tooltip-text{background-color:var(--se-main-font-color);border-radius:var(--se-border-radius);color:var(--se-main-background-color);cursor:auto;display:inline-block;font-size:.9em;height:auto;left:-50%;line-height:unset;margin:0;padding:4px 6px;position:relative;text-align:center;white-space:nowrap;width:auto}.sun-editor .se-tooltip .se-tooltip-inner .se-tooltip-text:after{border-color:#0000 #0000 var(--se-main-font-color) #0000;border-style:solid;border-width:5px;bottom:100%;content:"";left:50%;margin-left:-5px;position:absolute}.sun-editor .se-tooltip:hover .se-tooltip-inner{opacity:1;visibility:visible}.sun-editor :not(.se-shortcut-hide) .se-tooltip .se-tooltip-inner .se-tooltip-text .se-shortcut{display:block!important}.sun-editor .se-shortcut-hide .se-tooltip .se-tooltip-inner .se-tooltip-text .se-shortcut{display:none!important}.sun-editor .se-tooltip .se-tooltip-inner .se-tooltip-text .se-shortcut>.se-shortcut-key{display:inline;font-weight:700}.sun-editor input.se-color-input{border:0;border-bottom:2px solid var(--se-main-outline-color);border-radius:0;margin:0 2px;outline:none;text-transform:uppercase;width:72px}.sun-editor input.se-color-input::-webkit-input-placeholder{font-size:.9em;text-transform:none}.sun-editor input.se-color-input::-moz-placeholder{font-size:.9em;text-transform:none}.sun-editor input.se-color-input:-ms-input-placeholder{font-size:.9em;text-transform:none}.sun-editor input.se-color-input::-ms-input-placeholder{font-size:.9em;text-transform:none}.sun-editor input.se-color-input::placeholder{font-size:.9em;text-transform:none}.sun-editor input.se-color-input::-webkit-search-cancel-button{-webkit-appearance:none;background:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCI+PHBhdGggZD0iTTEzLjQ2IDEyIDE5IDE3LjU0VjE5aC0xLjQ2TDEyIDEzLjQ2IDYuNDYgMTlINXYtMS40NkwxMC41NCAxMiA1IDYuNDZWNWgxLjQ2TDEyIDEwLjU0IDE3LjU0IDVIMTl2MS40NnoiLz48L3N2Zz4=) no-repeat 50%;background-size:cover;height:15px;width:15px}.sun-editor .se-visible-hidden{visibility:hidden}.sun-editor-editable table td.se-selected-table-cell:after,.sun-editor-editable table th.se-selected-table-cell:after{background-color:var(--se-active-light3-color);bottom:-1px;content:"";height:100%;left:-1px;opacity:.3;position:absolute;right:-1px;top:-1px;width:100%}.sun-editor-editable[contenteditable=true] table td.se-selected-cell-focus,.sun-editor-editable[contenteditable=true] table th.se-selected-cell-focus{outline:2px dashed var(--se-active-dark3-color);z-index:1}.sun-editor-editable pre[data-se-lang]{position:relative}.sun-editor-editable pre[data-se-lang]:before{color:var(--se-secondary-color);content:attr(data-se-lang);font-size:11px;opacity:.7;padding:2px 8px;pointer-events:none;position:absolute;right:0;top:0}.sun-editor-editable[contenteditable=true] pre.se-pre-code-focus{outline:2px solid var(--se-active-color);outline-offset:-2px}.sun-editor-editable pre[data-se-lang].se-pre-code-focus:before{display:none}.sun-editor-editable.se-rtl pre[data-se-lang]:before{left:0;right:auto}.sun-editor .se-code-lang{display:none;padding:0;position:absolute}.sun-editor .se-code-lang-button{align-items:center;background-color:var(--se-edit-background-pre,#f9f9f9);border:1px solid var(--se-border-color);border-radius:var(--se-border-radius);box-shadow:0;color:var(--se-edit-font-pre,#666);cursor:pointer;display:inline-flex;font-family:monospace;font-size:11px;gap:4px;line-height:1.4;margin:0;opacity:.75;padding:4px;transition:opacity .15s;white-space:nowrap}.sun-editor .se-code-lang-button:hover{box-shadow:0 1px 3px #0000001f;opacity:1}.sun-editor .se-code-lang-icon{font-size:10px;font-weight:700;opacity:.5}.sun-editor .se-find-replace{background-color:var(--se-main-background-color);border:1px solid var(--se-main-border-color);border-radius:0 0 0 var(--se-border-radius);border-right:none;border-top:none;box-shadow:-2px 2px 6px #0000001a;display:none;flex-direction:column;gap:4px;margin-left:auto;max-width:100%;padding:6px 8px;position:sticky;width:fit-content;z-index:6}.sun-editor .se-find-replace.se-find-replace-open{display:flex}.sun-editor .se-find-replace-row{align-items:center;display:flex;flex-wrap:wrap;gap:4px;justify-content:flex-end}.sun-editor .se-find-replace-row-replace{display:flex;justify-content:flex-start}.sun-editor .se-find-replace .se-find-input-wrapper{flex:1 1 180px;max-width:420px;position:relative}.sun-editor .se-find-replace .se-find-replace-input{background-color:var(--se-main-background-color);border:1px solid var(--se-main-border-color);border-radius:var(--se-border-radius);box-sizing:border-box;color:var(--se-main-color);font-size:var(--se-main-font-size);height:26px;outline:none;padding:2px 100px 2px 6px;width:100%}.sun-editor .se-find-replace .se-find-replace-input:focus{border-color:var(--se-active-color);box-shadow:0 0 0 1px var(--se-active-color)}.sun-editor .se-find-replace .se-find-replace-input.se-find-no-match{background-color:var(--se-find-no-match-color,#ff50501f)}.sun-editor .se-find-replace .se-find-replace-toggle{background-color:initial;color:var(--se-main-color-lighter);font-size:11px;position:absolute;right:1px;top:50%;transform:translateY(-50%);white-space:nowrap}.sun-editor .se-find-replace .se-find-replace-toggle>*{align-items:center;display:flex;float:left;height:24px;justify-content:center;margin:0}.sun-editor .se-find-replace .se-find-replace-toggle .se-find-replace-info{padding:0 2px}.sun-editor .se-find-replace .se-find-replace-toggle .se-find-replace-info .se-find-replace-count{color:var(--se-main-color-lighter)}.sun-editor .se-find-replace .se-find-replace-toggle>button.on{border:none}.sun-editor .se-find-replace .se-find-replace-buttons{display:flex;flex-shrink:0;gap:1px}.sun-editor .se-find-replace .se-find-replace-btn{align-items:center;border:1px solid #0000;display:flex;font-size:11px;height:24px;justify-content:center;transition:opacity .15s,background-color .15s;width:24px}.sun-editor .se-find-replace .se-find-replace-row .se-find-replace-btn{background-color:initial}.sun-editor .se-find-replace .se-find-replace-btn svg{fill:currentColor;height:16px;width:16px}.sun-editor mark.se-find-mark,.sun-editor-editable mark.se-find-mark{background-color:var(--se-find-match-color,#ffd50066);border-radius:1px;color:inherit;margin:0;padding:0}.sun-editor mark.se-find-mark.se-find-current,.sun-editor-editable mark.se-find-mark.se-find-current{background-color:var(--se-find-current-color,#ff9632b3)}.sun-editor.se-rtl .se-icon-flip-rtl .se-svg,.sun-editor.se-rtl .se-icon-flip-rtl svg{transform:scaleX(-1)}.sun-editor.se-rtl .se-text-prefix-icon{float:right}.sun-editor.se-rtl .se-btn-select svg{margin:auto 1px}.sun-editor.se-rtl .se-find-replace{border-left:none;border-radius:0 0 var(--se-border-radius) 0;border-right:1px solid var(--se-main-border-color);box-shadow:2px 2px 6px #0000001a;margin-left:0;margin-right:auto}.sun-editor.se-rtl .se-find-replace-row{justify-content:flex-start}.sun-editor.se-rtl .se-btn-tray,.sun-editor.se-rtl .se-find-replace-input,.sun-editor.se-rtl .se-input-form,.sun-editor.se-rtl .se-status-bar{direction:rtl}.sun-editor.se-rtl .se-status-bar .se-word-counter-wrapper .se-word-label{margin-left:4px;margin-right:0}.sun-editor.se-rtl .se-status-bar .se-char-counter-wrapper.se-with-word-counter{margin-left:0;margin-right:.6em}.sun-editor.se-rtl .se-btn-select .se-txt{direction:rtl;flex:auto;margin-left:4px;text-align:right}.sun-editor.se-rtl .se-side-btn{float:right}.sun-editor.se-rtl .se-side-btn-b{border-radius:var(--se-border-radius) 0 0 var(--se-border-radius);float:right;margin-right:0}.sun-editor.se-rtl .se-side-btn-a{border-radius:0 var(--se-border-radius) var(--se-border-radius) 0;float:right;margin-left:0}.sun-editor.se-rtl .se-side-btn-after{border-radius:var(--se-border-radius) 0 0 var(--se-border-radius);margin-right:0}.sun-editor.se-rtl .se-side-btn-before{border-radius:0 var(--se-border-radius) var(--se-border-radius) 0;float:right;margin-left:0}.sun-editor.se-rtl .se-menu-list li:has(>button.se-side-btn-before) .se-btn-input input{border-bottom-right-radius:0;border-top-right-radius:0}.sun-editor.se-rtl .se-menu-list li:has(>button.se-side-btn-after) .se-btn-input input{border-bottom-left-radius:0;border-top-left-radius:0}.sun-editor.se-rtl .se-menu-list li .se-side-btn-after.active:enabled,.sun-editor.se-rtl .se-menu-list li .se-side-btn-after.on:enabled{border-left:0;border-right:1px solid}.sun-editor.se-rtl .se-menu-list li .se-side-btn-before.active:enabled,.sun-editor.se-rtl .se-menu-list li .se-side-btn-before.on:enabled{border-left:1px solid;border-right:0}.sun-editor.se-rtl .se-btn-list{text-align:right}.sun-editor.se-rtl .se-btn-list>.se-list-icon{margin:-1px 0 0 10px}.sun-editor.se-rtl .se-menu-list:not(.se-menu-dir-fix),.sun-editor.se-rtl .se-menu-list:not(.se-menu-dir-fix) li{float:right}.sun-editor.se-rtl .se-list-layer *{direction:rtl}.sun-editor.se-rtl .se-list-layer.se-list-format ul blockquote{border-bottom:0;border-left-width:0;border-right-width:5px;border-top:0;padding:0 7px 0 0}.sun-editor.se-rtl .se-select-item .se-list-icon{margin:0 0 0 6px}.sun-editor.se-rtl .se-block-handle{flex-direction:row-reverse}.sun-editor.se-rtl .se-block-menu-icon{margin-left:12px;margin-right:4px}.sun-editor.se-rtl .se-block-submenu-item svg{margin:0 0 0 6px}.sun-editor.se-rtl .se-submenu-arrow svg{transform:scaleX(-1)}.sun-editor.se-rtl .se-list-layer .se-selector-color .se-color-pallet li{float:right}.sun-editor.se-rtl .se-list-layer .se-selector-color .se-color-pallet:first-child li:first-child button{border-top-left-radius:0;border-top-right-radius:var(--se-border-radius)}.sun-editor.se-rtl .se-list-layer .se-selector-color .se-color-pallet:first-child li:last-child button{border-top-left-radius:var(--se-border-radius);border-top-right-radius:0}.sun-editor.se-rtl .se-list-layer .se-selector-color .se-color-pallet:last-of-type li:first-child button{border-bottom-left-radius:0;border-bottom-right-radius:var(--se-border-radius)}.sun-editor.se-rtl .se-list-layer .se-selector-color .se-color-pallet:last-of-type li:last-child button{border-bottom-left-radius:var(--se-border-radius);border-bottom-right-radius:0}.sun-editor.se-rtl .se-list-inner .se-list-checked li button>.se-svg{float:right;padding:6px 0 0 6px}.sun-editor.se-rtl .se-tooltip .se-tooltip-inner .se-tooltip-text,.sun-editor.se-rtl .se-wrapper .se-placeholder{direction:rtl}.sun-editor.se-rtl .se-tooltip .se-tooltip-inner .se-tooltip-text .se-shortcut{direction:ltr}.sun-editor.se-rtl .se-modal-area *{direction:rtl}.sun-editor.se-rtl .se-modal-area .se-modal-inner .se-modal-form .se-modal-ratio{margin-left:0;margin-right:4px}.sun-editor.se-rtl .se-modal-area .se-modal-inner .se-modal-header .se-close-btn{float:left}.sun-editor.se-rtl .se-modal-area .se-modal-inner .se-modal-header .se-modal-title{float:right}.sun-editor.se-rtl .se-modal-area .se-modal-inner .se-modal-form .se-modal-form-files .se-modal-files-edge-button{margin-left:0;margin-right:1px}.sun-editor.se-rtl .se-modal-area .se-modal-inner .se-modal-form .se-modal-flex-form .se-btn{margin-left:4px;margin-right:0}.sun-editor.se-rtl .se-modal-tabs button{float:right}.sun-editor.se-rtl .se-modal-area .se-modal-inner .se-modal-size-text{padding-right:var(--se-input-btn-size)}.sun-editor.se-rtl .se-modal-area .se-modal-inner .se-modal-form .se-modal-flex-form .se-modal-flex-group{margin-left:4px;margin-right:0;padding-left:0;padding-right:4px}.sun-editor.se-rtl .se-modal-area .se-modal-inner .se-modal-footer .se-btn-primary{float:left}.sun-editor.se-rtl .se-modal-area .se-modal-inner .se-modal-footer>div{float:right}.sun-editor.se-rtl .se-modal-area .se-modal-inner .se-modal-footer>div>label{margin:0 0 0 5px}.sun-editor.se-rtl .se-modal-area .se-modal-inner .se-modal-form-footer label:first-child{margin-left:16px;margin-right:0}.sun-editor.se-rtl .se-modal-area .se-modal-inner .se-anchor-rel-preview{margin-left:4px;text-align:right}.sun-editor.se-rtl .se-modal-area .se-modal-inner .se-modal-btn-revert{float:left}.sun-editor.se-rtl .se-modal-area .se-modal-inner .se-anchor-rel-btn{float:right}.sun-editor.se-rtl .se-browser *{direction:rtl}.sun-editor.se-rtl .se-browser .se-browser-tags{text-align:right}.sun-editor.se-rtl .se-browser .se-browser-tags a{margin:8px 8px 0}.sun-editor.se-rtl .se-browser .se-browser-header .se-browser-close{float:left}.sun-editor.se-rtl .se-browser .se-browser-side>div{border-left:1px solid var(--se-modal-border-color);border-right:none;flex-direction:row-reverse}.sun-editor.se-rtl .se-browser .se-menu-folder>div:not(.se-menu-child){padding:8px 20px 8px 10px}.sun-editor.se-rtl .se-browser .se-menu-folder>div>button{margin-left:0;margin-right:-20px}.sun-editor.se-rtl .se-browser .se-menu-folder.active{border-left:none;border-right:2px solid var(--se-active-dark4-color);margin-left:0;margin-right:-2px}.sun-editor.se-rtl .se-browser .se-browser-search .se-browser-search-form{flex-direction:row-reverse;margin:2px 8px}.sun-editor.se-rtl .se-browser .se-browser-search-input-wrap input{padding:3px 6px 3px 24px}.sun-editor.se-rtl .se-browser .se-browser-search-clear{left:2px;right:auto}.sun-editor.se-rtl .se-browser .se-browser-side .se-menu-icon{margin:0 0 0 10px}.sun-editor.se-rtl .se-browser .se-browser-search .se-side-open-btn{margin:8px 8px 0 0}.sun-editor.se-rtl .se-controller .se-btn-group,.sun-editor.se-rtl .se-controller .se-controller-body{direction:rtl}.sun-editor.se-rtl .se-resizing-container .se-resize-display{direction:rtl;left:0;right:auto}.sun-editor.se-rtl .se-controller .se-controller-header .se-close-btn{float:left}.sun-editor.se-rtl .se-controller .se-controller-header .se-controller-title{float:right}.sun-editor.se-rtl .se-controller.se-table-props .se-table-props-align li{margin-left:2px;margin-right:0}.sun-editor.se-rtl .se-controller .se-arrow{left:auto;margin-left:0;margin-right:-11px;right:20px}.sun-editor-editable.se-rtl[contenteditable=true].se-copy-format-cursor{cursor:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIxNiIgdmlld0JveD0iMCAwIDI0IDE2Ij48ZGVmcz48ZmlsdGVyIGlkPSJhIiBjb2xvci1pbnRlcnBvbGF0aW9uLWZpbHRlcnM9InNSR0IiPjxmZU1vcnBob2xvZ3kgaW49IlNvdXJjZUFscGhhIiBvcGVyYXRvcj0iZGlsYXRlIiByYWRpdXM9IjEiIHJlc3VsdD0iZGlsYXRlZCIvPjxmZUZsb29kIGZsb29kLWNvbG9yPSIjZmZmIiByZXN1bHQ9IndoaXRlIi8+PGZlQ29tcG9zaXRlIGluPSJ3aGl0ZSIgaW4yPSJkaWxhdGVkIiBvcGVyYXRvcj0iaW4iIHJlc3VsdD0ib3V0bGluZSIvPjxmZU1lcmdlPjxmZU1lcmdlTm9kZSBpbj0ib3V0bGluZSIvPjxmZU1lcmdlTm9kZSBpbj0iU291cmNlR3JhcGhpYyIvPjwvZmVNZXJnZT48L2ZpbHRlcj48L2RlZnM+PGcgZmlsdGVyPSJ1cmwoI2EpIiB0cmFuc2Zvcm09Im1hdHJpeCgtMSAwIDAgMSAyNCAwKSI+PHBhdGggZD0iTTQuMzMyIDEyLjY2OGMwIC4zNjcuMTUyLjY2NC4zMzYuNjY0aC42NjR2MS4zMzZINC41Yy0uMTg0IDAtLjUtLjMwMS0uNS0uNjY4IDAgLjM2Ny0uMzE2LjY2OC0uNS42NjhoLS44MzJ2LTEuMzM2aC42NjRjLjE4NCAwIC4zMzYtLjI5Ny4zMzYtLjY2NFYzLjMzMmMwLS4zNjctLjE1Mi0uNjY0LS4zMzYtLjY2NGgtLjY2NFYxLjMzMkgzLjVjLjE4NCAwIC41LjMwMS41LjY2OCAwLS4zNjcuMzE2LS42NjguNS0uNjY4aC44MzJ2MS4zMzZoLS42NjRjLS4xODQgMC0uMzM2LjI5Ny0uMzM2LjY2NFpNMjAgMi42NjhWMmEuNjcuNjcgMCAwIDAtLjY2OC0uNjY4aC04YS42NjcuNjY3IDAgMCAwLS42NjQuNjY4djIuNjY4YzAgLjM2Ny4yOTcuNjY0LjY2NC42NjRoOEEuNjY1LjY2NSAwIDAgMCAyMCA0LjY2OFY0aC42Njh2Mi42NjhIMTRWMTRjMCAuMzY3LjI5Ny42NjguNjY4LjY2OEgxNmEuNjcuNjcgMCAwIDAgLjY2OC0uNjY4VjhIMjJWMi42NjhaIi8+PC9nPjwvc3ZnPg==) 24 0,text}.sun-editor.se-rtl .se-wrapper.se-type-document .se-document-lines .se-document-lines-inner{direction:rtl;padding-left:var(--se-doc-info-inner-line-padding);padding-right:var(--se-doc-info-inner-padding)}.sun-editor.se-rtl .se-wrapper.se-type-document .se-document-lines .se-document-lines-inner>div.se-doc-h1{padding-left:var(--se-doc-info-inner-line-padding);padding-right:var(--se-doc-info-inner-line-indent-h1)}.sun-editor.se-rtl .se-wrapper.se-type-document .se-document-lines .se-document-lines-inner>div.se-doc-h2{padding-left:var(--se-doc-info-inner-line-padding);padding-right:var(--se-doc-info-inner-line-indent-h2)}.sun-editor.se-rtl .se-wrapper.se-type-document .se-document-lines .se-document-lines-inner>div.se-doc-h3{padding-left:var(--se-doc-info-inner-line-padding);padding-right:var(--se-doc-info-inner-line-indent-h3)}.sun-editor.se-rtl .se-wrapper.se-type-document .se-document-lines .se-document-lines-inner>div.se-doc-h4{padding-left:var(--se-doc-info-inner-line-padding);padding-right:var(--se-doc-info-inner-line-indent-h4)}.sun-editor.se-rtl .se-wrapper.se-type-document .se-document-lines .se-document-lines-inner>div.se-doc-h5{padding-left:var(--se-doc-info-inner-line-padding);padding-right:var(--se-doc-info-inner-line-indent-h5)}.sun-editor.se-rtl .se-wrapper.se-type-document .se-document-lines .se-document-lines-inner>div.se-doc-h6{padding-left:var(--se-doc-info-inner-line-padding);padding-right:var(--se-doc-info-inner-line-indent-h6)}.sun-editor.se-rtl .se-wrapper.se-type-document .se-document-page{direction:rtl}.sun-editor.se-rtl .se-wrapper.se-type-document .se-document-page>div{left:revert;margin-left:0;margin-right:1px;right:0}.sun-editor.se-rtl .se-wrapper.se-type-document .se-document-page>div>div.se-document-page-line{left:100%;right:unset}.sun-editor.se-rtl .se-wrapper.se-type-document.se-type-document-header .se-placeholder{margin-left:0;margin-right:max(var(--se-doc-info-min-width),var(--se-doc-info-width))}.sun-editor.se-rtl .se-wrapper.se-type-document.se-mode-block .se-placeholder{margin-left:0;margin-right:var(--se-block-handle-area-width)}.sun-editor.se-rtl .se-wrapper.se-type-document.se-mode-block.se-type-document-header .se-placeholder{margin-left:0;margin-right:calc(var(--se-block-handle-area-width) + max(var(--se-doc-info-min-width), var(--se-doc-info-width)))}.sun-editor.se-rtl .se-modal-area .se-modal-inner .se-modal-footer .se-btn{float:right}.sun-editor.se-rtl .se-modal-area .se-modal-inner .se-modal-content .se-modal-resize-handle-h{left:0;right:unset}.sun-editor.se-rtl .se-modal-area .se-modal-inner .se-modal-content .se-modal-resize-handle-c{cursor:nesw-resize;left:4px;right:unset}.sun-editor.se-rtl .se-selector-table .se-table-size-picker,.sun-editor.se-rtl .se-selector-table .se-table-size-unhighlighted{right:0}.sun-editor.se-rtl .se-selector-table .se-table-size-highlighted{right:5px}.sun-editor .se-btn-module-border.module-float-left{float:left}.sun-editor .se-btn-module-border.module-float-right{float:right}.sun-editor .se-wrapper.se-type-document.se-source-view-status{padding:0}.sun-editor .se-wrapper.se-type-document.se-source-view-status .se-document-lines,.sun-editor .se-wrapper.se-type-document.se-source-view-status .se-document-pages{display:none}.sun-editor .se-error{color:var(--se-error-color)}.sun-editor input.se-error,.sun-editor select.se-error,.sun-editor textarea.se-error{border:1px solid var(--se-error-dark2-color)!important}.sun-editor input.se-error:focus,.sun-editor select.se-error:focus,.sun-editor textarea.se-error:focus{border:1px solid var(--se-error-color)!important;box-shadow:0 0 0 .2rem var(--se-error-light2-color);outline:0;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out}.sun-editor hr.__se__solid{border-style:solid none none}.sun-editor hr.__se__dotted{border-style:dotted none none}.sun-editor hr.__se__dashed{border-style:dashed none none}.sun-editor .se-select-menu .se-select-item .se-autocomplete-item span+span{margin:0 4px;opacity:.5}.sun-editor .se-slash-command-menu .se-slash-empty{display:block;font-size:12px;opacity:.6;padding:6px 10px}.sun-editor-editable.se-show-block div,.sun-editor-editable.se-show-block h1,.sun-editor-editable.se-show-block h2,.sun-editor-editable.se-show-block h3,.sun-editor-editable.se-show-block h4,.sun-editor-editable.se-show-block h5,.sun-editor-editable.se-show-block h6,.sun-editor-editable.se-show-block li,.sun-editor-editable.se-show-block ol,.sun-editor-editable.se-show-block p,.sun-editor-editable.se-show-block pre,.sun-editor-editable.se-show-block ul{border:1px dashed var(--se-show-blocks-color)!important;padding:14px 8px 8px!important}.sun-editor-editable.se-show-block ol,.sun-editor-editable.se-show-block ul{border:1px dashed var(--se-show-blocks-li-color)!important}.sun-editor-editable.se-show-block pre{border:1px dashed var(--se-show-blocks-pre-color)!important}.sun-editor-editable.se-show-block div.se-component{border:1px dashed var(--se-show-blocks-component-color)!important;padding:1px!important}.sun-editor-editable.se-show-block p{background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA0AAAAPAQMAAAAF7dc0AAAABlBMVEWAgID////n1o2sAAAAAnRSTlP/AOW3MEoAAAAaSURBVAjXY/j/gwGCPvxg+F4BQiAGDP1HQQByxxw0gqOzIwAAAABJRU5ErkJggg==) no-repeat}.sun-editor-editable.se-show-block div:not(.se-component){background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABUAAAAPAQMAAAAxlBYoAAAABlBMVEWAgID////n1o2sAAAAAnRSTlP/AOW3MEoAAAAmSURBVAjXY/j//wcDDH+8XsHwDYi/hwNx1A8w/nYLKH4XoQYJAwCXnSgcl2MOPgAAAABJRU5ErkJggg==) no-repeat}.sun-editor-editable.se-show-block h1{background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAPAQMAAAA4f7ZSAAAABlBMVEWAgID////n1o2sAAAAAnRSTlP/AOW3MEoAAAAfSURBVAjXY/j/v4EBhr+9B+LzEPrDeygfhI8j1CBhAEhmJGY4Rf6uAAAAAElFTkSuQmCC) no-repeat}.sun-editor-editable.se-show-block h2{background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAPAQMAAAA4f7ZSAAAABlBMVEWAgID////n1o2sAAAAAnRSTlP/AOW3MEoAAAAmSURBVAjXY/j/v4EBhr+dB+LtQPy9geEDEH97D8T3gbgdoQYJAwA51iPuD2haEAAAAABJRU5ErkJggg==) no-repeat}.sun-editor-editable.se-show-block h3{background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAPAQMAAAA4f7ZSAAAABlBMVEWAgID////n1o2sAAAAAnRSTlP/AOW3MEoAAAAiSURBVAjXY/j/v4EBhr+dB+LtQPy9geHDeQgN5p9HqEHCADeWI+69VG2MAAAAAElFTkSuQmCC) no-repeat}.sun-editor-editable.se-show-block h4{background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAPAQMAAADTSA1RAAAABlBMVEWAgID////n1o2sAAAAAnRSTlP/AOW3MEoAAAAiSURBVAjXY/j//wADDH97DsTXIfjDdiDdDMTfIRhZHRQDAKJOJ6L+K3y7AAAAAElFTkSuQmCC) no-repeat}.sun-editor-editable.se-show-block h5{background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAPAQMAAAA4f7ZSAAAABlBMVEWAgID////n1o2sAAAAAnRSTlP/AOW3MEoAAAAlSURBVAjXY/j/v4EBhr+1A/F+IO5vYPiwHUh/B2IQfR6hBgkDABlWIy5uM+9GAAAAAElFTkSuQmCC) no-repeat}.sun-editor-editable.se-show-block h6{background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAPAQMAAAA4f7ZSAAAABlBMVEWAgID////n1o2sAAAAAnRSTlP/AOW3MEoAAAAiSURBVAjXY/j/v4EBhr+dB+LtQLy/geFDP5S9HSKOrA6KAR9GIza1ptJnAAAAAElFTkSuQmCC) no-repeat}.sun-editor-editable.se-show-block li{background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAPCAYAAADkmO9VAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAA7SURBVDhPYxgFcNDQ0PAfykQBIHEYhgoRB/BpwCfHBKWpBkaggYxQGgOgBzyQD1aLLA4TGwWDGjAwAACR3RcEU9Ui+wAAAABJRU5ErkJggg==) no-repeat}.sun-editor-editable.se-show-block ol{background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAYAAABiDJ37AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAABHSURBVDhPYxgFcNDQ0PAfhKFcFIBLHCdA1oBNM0kGEmMAPgOZoDTVANUNxAqQvURMECADRiiNAWCagDSGGhyW4DRrMAEGBgAu0SX6WpGgjAAAAABJRU5ErkJggg==) no-repeat}.sun-editor-editable.se-show-block ul{background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAYAAABiDJ37AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAA1SURBVDhPYxgFDA0NDf+hTBSALI5LDQgwQWmqgVEDKQcsUBoF4ItFGEBXA+QzQpmDGjAwAAA8DQ4Lni6gdAAAAABJRU5ErkJggg==) no-repeat}.sun-editor.sun-editor-carrier-wrapper{border:none!important;display:block!important;height:0!important;margin:0!important;outline:none!important;padding:0!important;position:static!important;width:0!important}.sun-editor.sun-editor-carrier-wrapper .se-drag-cursor{background-color:var(--se-drag-caret-color);display:none;pointer-events:none;position:absolute;width:2px;z-index:2147483646}.sun-editor.sun-editor-carrier-wrapper .se-drag-cursor:before{background-color:initial;border:0 solid #0000;border-color:var(--se-drag-caret-color) #0000 #0000 #0000;border-width:6px 5px 0;content:"";height:0;margin-left:-4px;margin-right:0;position:absolute;top:-3px;width:0}.sun-editor.sun-editor-carrier-wrapper .se-drag-cursor:after{background-color:initial;border:5px solid #0000;border-top:0 solid #0000;border-color:#0000 #0000 var(--se-drag-caret-color) #0000;bottom:-3px;content:"";height:0;margin-left:-4px;margin-right:0;position:absolute;width:0}.sun-editor-editable[contenteditable=true] .se-page-break{align-items:center;clear:both;display:flex;height:24px;justify-content:center;margin:0;padding:0;position:relative;visibility:visible!important;width:100%;z-index:1}.sun-editor-editable[contenteditable=true] .se-page-break:after{background:#0000;color:var(--se-doc-info-page-background-color);content:"⎯⎯⎯⎯⎯⎯";font-size:var(--se-main-font-size);padding:0 5px;position:absolute;top:0}@-webkit-keyframes blinker{50%{opacity:0}}@keyframes blinker{50%{opacity:0}}@-webkit-keyframes spinner{to{transform:rotate(361deg)}}@keyframes spinner{to{transform:rotate(361deg)}}@keyframes toast-in{to{opacity:1;transform:translateY(0)}}@keyframes toast-out{to{opacity:0;transform:translateY(-10px)}}@keyframes se-alert-in{0%{opacity:0;transform:scale(.9)}to{opacity:1;transform:scale(1)}}@keyframes se-alert-out{0%{opacity:1;transform:scale(1)}to{opacity:0;transform:scale(.95)}}.sun-editor-editable{background-color:var(--se-edit-background-color);box-sizing:border-box;color:var(--se-edit-font-color);font-family:var(--se-content-font-family);font-size:var(--se-edit-font-size);word-break:normal;word-wrap:break-word;margin:0;padding:var(--se-edit-inner-padding)}.sun-editor-editable *{box-sizing:border-box;color:inherit;font-family:inherit;font-size:inherit;line-height:var(--se-edit-line-height)}.sun-editor-editable.se-document-page-mirror-a4,.sun-editor-editable.se-type-document-editable-a4{padding:var(--se-edit-inner-padding-doc-type);width:21cm!important}.sun-editor-editable.se-rtl,.sun-editor-editable.se-rtl *{direction:rtl}.sun-editor-editable .se-component>figure{direction:ltr}.sun-editor-editable .se-component>figure>*{margin:0}.sun-editor-editable .se-component>figure>blockquote{margin:0;min-height:100px;position:relative}.sun-editor-editable .se-component>figure>blockquote:before{-webkit-animation:spin 1s linear infinite;animation:spin 1s linear infinite;border:3px solid #f3f3f3;border-radius:50%;border-top-color:#3498db;content:"";display:block;height:30px;left:50%;position:absolute;top:50%;width:30px}@-webkit-keyframes spin{0%{transform:translate(-50%,-50%) rotate(0deg)}to{transform:translate(-50%,-50%) rotate(1turn)}}@keyframes spin{0%{transform:translate(-50%,-50%) rotate(0deg)}to{transform:translate(-50%,-50%) rotate(1turn)}}.sun-editor-editable audio,.sun-editor-editable figcaption,.sun-editor-editable figure,.sun-editor-editable iframe,.sun-editor-editable img,.sun-editor-editable td,.sun-editor-editable th,.sun-editor-editable video{position:relative}.sun-editor-editable span{display:inline;margin:0;padding:0;vertical-align:initial}.sun-editor-editable span.se-math{display:inline-block}.sun-editor-editable span.se-math *{direction:ltr}.sun-editor-editable span>.MathJax{margin:.5em 0!important}.sun-editor-editable a{color:var(--se-edit-anchor);text-decoration:none;white-space:nowrap}.sun-editor-editable span[style~="color:"] a{color:inherit}.sun-editor-editable a:focus,.sun-editor-editable a:hover{color:var(--se-edit-anchor-on-font);cursor:pointer;text-decoration:underline}.sun-editor-editable a.on{background-color:var(--se-edit-anchor-on-back);color:var(--se-edit-anchor-on-font)}.sun-editor-editable a[data-se-anchor]{background:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyMCIgaGVpZ2h0PSIyMCIgdmlld0JveD0iMCAwIDIwIDIwIj48cGF0aCBkPSJNMTQuMTY4IDE1IDEwIDEzLjE4NCA1LjgzMiAxNVY0LjE2OGg4LjMzNm0wLTEuNjY4SDUuODMyYy0uOTE4IDAtMS42NjQuNzQ2LTEuNjY0IDEuNjY4VjE3LjVMMTAgMTVsNS44MzIgMi41VjQuMTY4YzAtLjkyNi0uNzUtMS42NjgtMS42NjQtMS42NjhtMCAwIiBzdHlsZT0ic3Ryb2tlOm5vbmU7ZmlsbC1ydWxlOm5vbnplcm87ZmlsbDojMDAwO2ZpbGwtb3BhY2l0eToxIi8+PC9zdmc+) no-repeat;cursor:default;display:inline-block;height:20px;padding:0 10px;vertical-align:bottom;width:20px}.sun-editor-editable pre{background-color:var(--se-edit-background-pre);border:1px solid var(--se-edit-border-light);border-radius:2px;color:var(--se-edit-font-pre);display:block;font-family:monospace;line-height:1.45;margin:0 0 10px;padding:8px;white-space:pre-wrap!important;word-wrap:break-word;overflow:visible}.sun-editor-editable ol{list-style-type:decimal}.sun-editor-editable ol,.sun-editor-editable ul{display:block;list-style-position:inside;-webkit-margin-before:1em;margin-block-start:1em;-webkit-margin-after:1em;margin-block-end:1em;-webkit-margin-start:0;margin-inline-start:0;-webkit-margin-end:0;margin-inline-end:0;-webkit-padding-start:40px;padding-inline-start:40px}.sun-editor-editable ul{list-style-type:disc}.sun-editor-editable li{display:list-item;margin-bottom:5px;text-align:-webkit-match-parent}.sun-editor-editable ol ol,.sun-editor-editable ol ul,.sun-editor-editable ul ol,.sun-editor-editable ul ul{margin:0}.sun-editor-editable ol ol,.sun-editor-editable ul ol{list-style-type:lower-alpha}.sun-editor-editable ol ol ol,.sun-editor-editable ul ol ol,.sun-editor-editable ul ul ol{list-style-type:upper-roman}.sun-editor-editable ol ul,.sun-editor-editable ul ul{list-style-type:circle}.sun-editor-editable ol ol ul,.sun-editor-editable ol ul ul,.sun-editor-editable ul ul ul{list-style-type:square}.sun-editor-editable sub,.sun-editor-editable sup{font-size:75%;line-height:0}.sun-editor-editable sub{vertical-align:sub}.sun-editor-editable sup{vertical-align:super}.sun-editor-editable p{display:block;margin:0 0 10px}.sun-editor-editable div{display:block;margin:0;padding:0}.sun-editor-editable blockquote{color:var(--se-edit-font-quote);display:block;font-family:inherit;font-size:inherit;-webkit-margin-before:1em;margin-block-start:1em;-webkit-margin-after:1em;margin-block-end:1em;-webkit-margin-start:0;margin-inline-start:0;-webkit-margin-end:0;border-color:var(--se-edit-border-dark);border-style:solid;border-width:0 0 0 5px;margin-inline-end:0;padding:0 5px 0 20px}.sun-editor-editable blockquote blockquote{border-color:var(--se-edit-border-dark-n1)}.sun-editor-editable blockquote blockquote blockquote{border-color:var(--se-edit-border-dark-n2)}.sun-editor-editable blockquote blockquote blockquote blockquote{border-color:var(--se-edit-border-light)}.sun-editor-editable.se-rtl blockquote{border-left-width:0;border-right-width:5px;padding-left:5px;padding-right:20px}.sun-editor-editable h1{display:block;font-size:2em;-webkit-margin-before:.67em;margin-block-start:.67em;-webkit-margin-after:.67em;margin-block-end:.67em;-webkit-margin-start:0;margin-inline-start:0;-webkit-margin-end:0;font-weight:700;margin-inline-end:0}.sun-editor-editable h2{display:block;font-size:1.5em;-webkit-margin-before:.83em;margin-block-start:.83em;-webkit-margin-after:.83em;margin-block-end:.83em;-webkit-margin-start:0;margin-inline-start:0;-webkit-margin-end:0;font-weight:700;margin-inline-end:0}.sun-editor-editable h3{display:block;font-size:1.17em;-webkit-margin-before:1em;margin-block-start:1em;-webkit-margin-after:1em;margin-block-end:1em;-webkit-margin-start:0;margin-inline-start:0;-webkit-margin-end:0;font-weight:700;margin-inline-end:0}.sun-editor-editable h4{display:block;font-size:1em;-webkit-margin-before:1.33em;margin-block-start:1.33em;-webkit-margin-after:1.33em;margin-block-end:1.33em;-webkit-margin-start:0;margin-inline-start:0;-webkit-margin-end:0;font-weight:700;margin-inline-end:0}.sun-editor-editable h5{display:block;font-size:.83em;-webkit-margin-before:1.67em;margin-block-start:1.67em;-webkit-margin-after:1.67em;margin-block-end:1.67em;-webkit-margin-start:0;margin-inline-start:0;-webkit-margin-end:0;font-weight:700;margin-inline-end:0}.sun-editor-editable h6{display:block;font-size:.67em;-webkit-margin-before:2.33em;margin-block-start:2.33em;-webkit-margin-after:2.33em;margin-block-end:2.33em;-webkit-margin-start:0;margin-inline-start:0;-webkit-margin-end:0;font-weight:700;margin-inline-end:0}.sun-editor-editable hr{border-color:var(--se-edit-hr-color);-o-border-image:initial;border-image:initial;border-width:1px 0 0;display:flex;height:20px;margin-bottom:0;margin-top:20px}.sun-editor-editable hr.__se__solid{border-style:solid none none}.sun-editor-editable hr.__se__dotted{border-style:dotted none none}.sun-editor-editable hr.__se__dashed{border-style:dashed none none}.sun-editor-editable hr.on{border-color:var(--se-edit-active);box-shadow:0 0 0 .1rem var(--se-edit-hr-on-back)}.sun-editor-editable table{background-color:var(--se-edit-background-color);border-collapse:collapse;border-color:var(--se-edit-border-table);border-spacing:0;border-style:solid;border-width:1px;display:table;margin:0;max-width:100%;table-layout:auto!important;width:100%}.sun-editor-editable.se-rtl table{background-color:var(--se-edit-background-color);margin:0 0 10px auto}.sun-editor-editable table caption{background-color:var(--se-edit-background-pre);border:1px solid var(--se-edit-border-table);caption-side:top;margin:0;outline:none;padding:.5em;text-align:unset}.sun-editor-editable table caption.se-table-caption-top{border-bottom:0;caption-side:top}.sun-editor-editable table caption.se-table-caption-bottom{border-top:0;caption-side:bottom}.sun-editor-editable table thead{border-bottom:2px solid var(--se-edit-font-color)}.sun-editor-editable table tr{box-sizing:border-box;position:relative}.sun-editor-editable table th{background-color:#f3f3f3}.sun-editor-editable table td,.sun-editor-editable table th{background-clip:padding-box;background-color:inherit;border-color:var(--se-edit-border-table);border-style:solid;border-width:1px;min-width:2em;padding:.4em;position:relative;vertical-align:middle}.sun-editor-editable table.se-table-layout-fixed{table-layout:fixed!important}.sun-editor-editable.se-disabled *{user-select:none;-o-user-select:none;-moz-user-select:none;-khtml-user-select:none;-webkit-user-select:none;-ms-user-select:none}.sun-editor-editable .se-component:not(.se-input-component),.sun-editor-editable hr{-webkit-user-modify:read-only;-moz-user-modify:read-only;-webkit-user-select:all;-moz-user-select:all;-ms-user-select:all;user-select:all}.sun-editor-editable figure figcaption{-webkit-user-modify:read-write;-moz-user-modify:read-write;-webkit-user-select:text;-moz-user-select:text;-ms-user-select:text;user-select:text}.sun-editor-editable .se-component{background-color:inherit;display:flex;margin:0 0 10px;padding:1px}.sun-editor-editable .se-component.se-file-figure>figure{outline:1px solid #bbb;padding:1em}.sun-editor-editable .se-component.se-file-figure>figure>a[data-se-file-download]{color:var(--se-edit-font-color);margin:0 4px}.sun-editor-editable .se-component.se-file-figure>figure>a:before{content:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCI+PHBhdGggZD0iTTIwIDE4SDRWOGgxNm0wLTJoLThsLTItMkg0Yy0xLjExIDAtMiAuODktMiAydjEyYTIgMiAwIDAgMCAyIDJoMTZhMiAyIDAgMCAwIDItMlY4YTIgMiAwIDAgMC0yLTIiLz48L3N2Zz4=);display:inline-block;height:auto;vertical-align:middle;width:1.5em}.sun-editor-editable .__se__float-left{float:left;margin-right:4px}.sun-editor-editable .__se__float-right{float:right;margin-left:4px}.sun-editor-editable .__se__float-center{float:center}.sun-editor-editable .__se__float-none{float:none}.sun-editor-editable audio,.sun-editor-editable iframe,.sun-editor-editable img,.sun-editor-editable video{cursor:default;display:block;height:auto;margin:0;max-width:100%;padding:0;width:auto}.sun-editor-editable .se-image-container,.sun-editor-editable .se-video-container{height:auto;max-width:100%;width:auto}.sun-editor-editable figure{display:block;margin:0;min-width:20px;outline:none;padding:0}.sun-editor-editable .se-component figure{padding:0}.sun-editor-editable .se-flex-component{margin:0 0 10px;max-width:100%;min-width:auto;width:100%}.sun-editor-editable figure.se-flex-component{width:max-content}.sun-editor-editable .se-inline-component{display:inline-block;margin:0;max-width:100%;min-width:-webkit-min-content;min-width:-moz-min-content;min-width:min-content;padding:0;width:auto}.sun-editor-editable figure.se-scroll-figure-x{overflow-x:auto;padding:0 1px}.sun-editor-editable figure.se-scroll-figure-y{overflow-y:auto;padding:1px 0}.sun-editor-editable figure.se-scroll-figure-xy{overflow-x:auto;overflow-y:auto;padding:1px}.sun-editor-editable .__se__float-center figure,.sun-editor-editable .__se__float-left figure,.sun-editor-editable .__se__float-right figure{margin:auto!important}.sun-editor-editable figure figcaption{background-color:var(--se-edit-background-pre);margin:0;outline:none;padding:1em .5em}.sun-editor-editable figure figcaption p{line-height:2;margin:0}.sun-editor-editable .se-image-container a img{margin:1px;outline:1px solid var(--se-edit-active);padding:1px}.sun-editor-editable .se-video-container iframe,.sun-editor-editable .se-video-container video{border:0;height:100%;left:0;outline:1px solid var(--se-edit-outline);position:absolute;top:0;width:100%}.sun-editor-editable .se-video-container figure{left:0;max-width:100%;width:100%}.sun-editor-editable audio{height:54px;width:300px}.sun-editor-editable .se-page-break{visibility:hidden;page-break-before:always;margin:0;padding:0}.sun-editor .__se__p-bordered,.sun-editor-editable .__se__p-bordered{border-bottom:1px solid #b1b1b1;border-top:1px solid #b1b1b1;padding:4px 0}.sun-editor .__se__p-spaced,.sun-editor-editable .__se__p-spaced{letter-spacing:1px}.sun-editor .__se__p-neon,.sun-editor-editable .__se__p-neon{-webkit-animation:neonFlicker 1.5s infinite alternate;animation:neonFlicker 1.5s infinite alternate;background:#000;border:2px solid #fff;border-radius:6px;color:#fff;font-style:italic;font-weight:200;padding:6px 4px;text-transform:uppercase}@-webkit-keyframes neonFlicker{0%,19%,21%,23%,25%,54%,56%,to{box-shadow:0 0 .5px #fff,inset 0 0 .5px #fff,0 0 2px #08f,inset 0 0 2px #08f,0 0 4px #08f,inset 0 0 4px #08f;text-shadow:-.2rem -.2rem 1rem #fff,.2rem .2rem 1rem #fff,0 0 2px #f40,0 0 4px #f40,0 0 6px #f40,0 0 8px #f40,0 0 10px #f40}20%,24%,55%{box-shadow:none;text-shadow:none}}@keyframes neonFlicker{0%,19%,21%,23%,25%,54%,56%,to{box-shadow:0 0 .5px #fff,inset 0 0 .5px #fff,0 0 2px #08f,inset 0 0 2px #08f,0 0 4px #08f,inset 0 0 4px #08f;text-shadow:-.2rem -.2rem 1rem #fff,.2rem .2rem 1rem #fff,0 0 2px #f40,0 0 4px #f40,0 0 6px #f40,0 0 8px #f40,0 0 10px #f40}20%,24%,55%{box-shadow:none;text-shadow:none}}.sun-editor .__se__t-shadow,.sun-editor-editable .__se__t-shadow{text-shadow:-.2rem -.2rem 1rem #fff,.2rem .2rem 1rem #fff,0 0 .2rem #999,0 0 .4rem #888,0 0 .6rem #777,0 0 .8rem #666,0 0 1rem #555}.sun-editor .__se__t-code,.sun-editor-editable .__se__t-code{background-color:#1b1f230d;border-radius:6px;color:#666;font-family:monospace;padding:.2em .4em} \ No newline at end of file diff --git a/deploy/runtime-grants.sql.example b/deploy/runtime-grants.sql.example index 4fd80a0..63bf296 100644 --- a/deploy/runtime-grants.sql.example +++ b/deploy/runtime-grants.sql.example @@ -22,3 +22,11 @@ GRANT INSERT ON huntingclubroster.club_due_adjustments TO 'hcr_runtime'@'app-hos GRANT INSERT ON huntingclubroster.club_payment_reversals TO 'hcr_runtime'@'app-host.example'; -- No schema-changing privileges, journal UPDATE/DELETE, or financial UPDATE/DELETE. -- Use separate credentials for migrations and backup/restore jobs. + +GRANT INSERT, UPDATE ON huntingclubroster.club_invitations TO 'hcr_runtime'@'app-host.example'; +GRANT INSERT, UPDATE ON huntingclubroster.club_tickets TO 'hcr_runtime'@'app-host.example'; +GRANT INSERT ON huntingclubroster.club_ticket_messages TO 'hcr_runtime'@'app-host.example'; + +GRANT INSERT, UPDATE, DELETE ON huntingclubroster.user_mfa TO 'hcr_runtime'@'app-host.example'; +GRANT INSERT, DELETE ON huntingclubroster.mfa_recovery TO 'hcr_runtime'@'app-host.example'; +GRANT INSERT, UPDATE ON huntingclubroster.club_resource_usage TO 'hcr_runtime'@'app-host.example'; diff --git a/js/addAlert.js b/js/addAlert.js index 83eea96..37fbbd8 100644 --- a/js/addAlert.js +++ b/js/addAlert.js @@ -5,53 +5,13 @@ $(document).ready(function () { - var $application = $("#APPLICATION_MNEMONIC").val(), $sessionStorage = JSON.parse(sessionStorage.getItem($application) || "{}"), $CKEditor; + var $application = $("#APPLICATION_MNEMONIC").val(), $sessionStorage = JSON.parse(sessionStorage.getItem($application) || "{}"); // ---------------------- // Initialize the Editor. // ---------------------- - ClassicEditor - .create(document.querySelector('#alert_message'), { - toolbar: { - items: [ - 'heading', - '|', - 'bold', - 'italic', - 'underline', - 'link', - 'bulletedList', - 'numberedList', - '|', - 'fontColor', - 'fontSize', - 'fontFamily', - '|', - 'indent', - 'outdent', - 'alignment', - '|', - 'horizontalLine', - 'insertTable', - '|', - 'undo', - 'redo', - '|' - ]}, - link: { - addTargetToExternalLinks: true, - defaultProtocol: "http://" - - } - }) - .then(editor => { - $CKEditor = editor; - }) - .catch(error => { - console.error('CK-Editor error...'); - console.error(error); - }); + HcrRichText.create(document.querySelector('#alert_message')); // ------------ @@ -210,7 +170,7 @@ $(document).ready(function () { e.preventDefault(); - $CKEditor.updateSourceElement(); + if (!HcrRichText.sync(document.querySelector('#alert_message'))) return; $.post("./", $(this).serialize()) diff --git a/js/addPopover.js b/js/addPopover.js index b216d21..9eea233 100644 --- a/js/addPopover.js +++ b/js/addPopover.js @@ -6,54 +6,13 @@ $(document).ready(function () { var $application = $("#APPLICATION_MNEMONIC").val(), - $sessionStorage = JSON.parse(sessionStorage.getItem($application) || "{}"), - $CKEditor; + $sessionStorage = JSON.parse(sessionStorage.getItem($application) || "{}"); // ---------------------- // Initialize the Editor. // ---------------------- - ClassicEditor - .create(document.querySelector('#popover_text'), { - toolbar: { - items: [ - 'heading', - '|', - 'bold', - 'italic', - 'underline', - 'link', - 'bulletedList', - 'numberedList', - '|', - 'fontColor', - 'fontSize', - 'fontFamily', - '|', - 'indent', - 'outdent', - 'alignment', - '|', - 'horizontalLine', - 'insertTable', - '|', - 'undo', - 'redo', - '|' - ]}, - link: { - addTargetToExternalLinks: true, - defaultProtocol: "http://" - - } - }) - .then(editor => { - $CKEditor = editor; - }) - .catch(error => { - console.error('CK-Editor error...'); - console.error(error); - }); + HcrRichText.create(document.querySelector('#popover_text')); // ----------- // Save Button @@ -114,7 +73,7 @@ $(document).ready(function () { e.preventDefault(); - $CKEditor.updateSourceElement(); + if (!HcrRichText.sync(document.querySelector('#popover_text'))) return; $.post("./", $(this).serialize()) diff --git a/js/ckeditor.js b/js/ckeditor.js deleted file mode 100644 index 9275436..0000000 --- a/js/ckeditor.js +++ /dev/null @@ -1,6 +0,0 @@ -/*! - * @license Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved. - * For licensing, see LICENSE.md. - */ -(function(t){const e=t["en"]=t["en"]||{};e.dictionary=Object.assign(e.dictionary||{},{"%0 of %1":"%0 of %1","Align center":"Align center","Align left":"Align left","Align right":"Align right",Aquamarine:"Aquamarine",Big:"Big",Black:"Black","Block quote":"Block quote",Blue:"Blue",Bold:"Bold","Bulleted List":"Bulleted List",Cancel:"Cancel","Cannot upload file:":"Cannot upload file:","Centered image":"Centered image","Change image text alternative":"Change image text alternative","Choose heading":"Choose heading",Column:"Column","Could not insert image at the current position.":"Could not insert image at the current position.","Could not obtain resized image URL.":"Could not obtain resized image URL.","Decrease indent":"Decrease indent",Default:"Default","Delete column":"Delete column","Delete row":"Delete row","Dim grey":"Dim grey","Document colors":"Document colors",Downloadable:"Downloadable","Dropdown toolbar":"Dropdown toolbar","Edit link":"Edit link","Editor toolbar":"Editor toolbar","Enter image caption":"Enter image caption","Font Color":"Font Color","Font Family":"Font Family","Font Size":"Font Size","Full size image":"Full size image",Green:"Green",Grey:"Grey","Header column":"Header column","Header row":"Header row",Heading:"Heading","Heading 1":"Heading 1","Heading 2":"Heading 2","Heading 3":"Heading 3","Heading 4":"Heading 4","Heading 5":"Heading 5","Heading 6":"Heading 6","Horizontal line":"Horizontal line",Huge:"Huge","Image resize list":"Image resize list","image widget":"image widget","Increase indent":"Increase indent","Insert column left":"Insert column left","Insert column right":"Insert column right","Insert image":"Insert image","Insert image or file":"Insert image or file","Insert media":"Insert media","Insert paragraph after block":"Insert paragraph after block","Insert paragraph before block":"Insert paragraph before block","Insert row above":"Insert row above","Insert row below":"Insert row below","Insert table":"Insert table","Inserting image failed":"Inserting image failed",Italic:"Italic",Justify:"Justify","Left aligned image":"Left aligned image","Light blue":"Light blue","Light green":"Light green","Light grey":"Light grey",Link:"Link","Link URL":"Link URL","Media URL":"Media URL","media widget":"media widget","Merge cell down":"Merge cell down","Merge cell left":"Merge cell left","Merge cell right":"Merge cell right","Merge cell up":"Merge cell up","Merge cells":"Merge cells",Next:"Next","Numbered List":"Numbered List","Open in a new tab":"Open in a new tab","Open link in new tab":"Open link in new tab",Orange:"Orange",Original:"Original",Paragraph:"Paragraph","Paste the media URL in the input.":"Paste the media URL in the input.",Previous:"Previous",Purple:"Purple",Red:"Red",Redo:"Redo","Remove color":"Remove color","Resize image":"Resize image","Resize image to %0":"Resize image to %0","Resize image to the original size":"Resize image to the original size","Rich Text Editor":"Rich Text Editor","Rich Text Editor, %0":"Rich Text Editor, %0","Right aligned image":"Right aligned image",Row:"Row",Save:"Save","Select all":"Select all","Select column":"Select column","Select row":"Select row","Selecting resized image failed":"Selecting resized image failed","Show more items":"Show more items","Side image":"Side image",Small:"Small","Split cell horizontally":"Split cell horizontally","Split cell vertically":"Split cell vertically","Table toolbar":"Table toolbar","Text alignment":"Text alignment","Text alignment toolbar":"Text alignment toolbar","Text alternative":"Text alternative","The URL must not be empty.":"The URL must not be empty.","This link has no URL":"This link has no URL","This media URL is not supported.":"This media URL is not supported.",Tiny:"Tiny","Tip: Paste the URL into the content to embed faster.":"Tip: Paste the URL into the content to embed faster.",Turquoise:"Turquoise",Underline:"Underline",Undo:"Undo",Unlink:"Unlink","Upload failed":"Upload failed","Upload in progress":"Upload in progress",White:"White","Widget toolbar":"Widget toolbar",Yellow:"Yellow"})})(window.CKEDITOR_TRANSLATIONS||(window.CKEDITOR_TRANSLATIONS={}));(function t(e,n){if(typeof exports==="object"&&typeof module==="object")module.exports=n();else if(typeof define==="function"&&define.amd)define([],n);else if(typeof exports==="object")exports["ClassicEditor"]=n();else e["ClassicEditor"]=n()})(window,(function(){return function(t){var e={};function n(o){if(e[o]){return e[o].exports}var i=e[o]={i:o,l:false,exports:{}};t[o].call(i.exports,i,i.exports,n);i.l=true;return i.exports}n.m=t;n.c=e;n.d=function(t,e,o){if(!n.o(t,e)){Object.defineProperty(t,e,{enumerable:true,get:o})}};n.r=function(t){if(typeof Symbol!=="undefined"&&Symbol.toStringTag){Object.defineProperty(t,Symbol.toStringTag,{value:"Module"})}Object.defineProperty(t,"__esModule",{value:true})};n.t=function(t,e){if(e&1)t=n(t);if(e&8)return t;if(e&4&&typeof t==="object"&&t&&t.__esModule)return t;var o=Object.create(null);n.r(o);Object.defineProperty(o,"default",{enumerable:true,value:t});if(e&2&&typeof t!="string")for(var i in t)n.d(o,i,function(e){return t[e]}.bind(null,i));return o};n.n=function(t){var e=t&&t.__esModule?function e(){return t["default"]}:function e(){return t};n.d(e,"a",e);return e};n.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)};n.p="";return n(n.s=63)}([function(t,e,n){"use strict";n.d(e,"a",(function(){return i}));n.d(e,"c",(function(){return r}));n.d(e,"b",(function(){return s}));const o="https://ckeditor.com/docs/ckeditor5/latest/framework/guides/support/error-codes.html";class i extends Error{constructor(t,e,n){const o=`${t}${n?` ${JSON.stringify(n)}`:""}${a(t)}`;super(o);this.name="CKEditorError";this.context=e;this.data=n}is(t){return t==="CKEditorError"}static rethrowUnexpectedError(t,e){if(t.is&&t.is("CKEditorError")){throw t}const n=new i(t.message,e);n.stack=t.stack;throw n}}function r(t,e){console.warn(...c(t,e))}function s(t,e){console.error(...c(t,e))}function a(t){return`\nRead more: ${o}#error-${t}`}function c(t,e){const n=a(t);return e?[t,e,n]:[t,n]}},function(t,e,n){"use strict";var o=function t(){var e;return function t(){if(typeof e==="undefined"){e=Boolean(window&&document&&document.all&&!window.atob)}return e}}();var i=function t(){var e={};return function t(n){if(typeof e[n]==="undefined"){var o=document.querySelector(n);if(window.HTMLIFrameElement&&o instanceof window.HTMLIFrameElement){try{o=o.contentDocument.head}catch(t){o=null}}e[n]=o}return e[n]}}();var r=[];function s(t){var e=-1;for(var n=0;nt.length)e=t.length;for(var n=0,o=new Array(e);n:first-child{margin-top:var(--ck-spacing-large)}.ck.ck-editor__editable_inline>:last-child{margin-bottom:var(--ck-spacing-large)}.ck.ck-editor__editable_inline.ck-blurred ::selection{background:var(--ck-color-editable-blur-selection)}.ck.ck-balloon-panel.ck-toolbar-container[class*=arrow_n]:after{border-bottom-color:var(--ck-color-base-foreground)}.ck.ck-balloon-panel.ck-toolbar-container[class*=arrow_s]:after{border-top-color:var(--ck-color-base-foreground)}","",{version:3,sources:["webpack://./node_modules/@ckeditor/ckeditor5-theme-lark/theme/ckeditor5-ui/components/editorui/editorui.css","webpack://./node_modules/@ckeditor/ckeditor5-theme-lark/theme/mixins/_rounded.css","webpack://./node_modules/@ckeditor/ckeditor5-theme-lark/theme/mixins/_focus.css","webpack://./node_modules/@ckeditor/ckeditor5-theme-lark/theme/mixins/_shadow.css"],names:[],mappings:"AAWA,MACC,0CACD,CAEA,yDCJC,eDWD,CAPA,yJCAE,qCDOF,CAJC,oEERA,YAAa,CACb,2BAA2B,CCF3B,qCHYA,CAGD,+BACC,aAAc,CACd,oCAAqC,CACrC,4BAwBD,CAtBC,wCACC,eACD,CAEA,wCACC,gBACD,CAGA,4CACC,kCACD,CAGA,2CACC,qCACD,CAGA,sDACC,kDACD,CAKA,gEACC,mDACD,CAIA,gEACC,gDACD",sourcesContent:['/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n@import "../../../mixins/_rounded.css";\n@import "../../../mixins/_disabled.css";\n@import "../../../mixins/_shadow.css";\n@import "../../../mixins/_focus.css";\n@import "../../mixins/_button.css";\n\n:root {\n\t--ck-color-editable-blur-selection: hsl(0, 0%, 85%);\n}\n\n.ck.ck-editor__editable:not(.ck-editor__nested-editable) {\n\t@mixin ck-rounded-corners;\n\n\t&.ck-focused {\n\t\t@mixin ck-focus-ring;\n\t\t@mixin ck-box-shadow var(--ck-inner-shadow);\n\t}\n}\n\n.ck.ck-editor__editable_inline {\n\toverflow: auto;\n\tpadding: 0 var(--ck-spacing-standard);\n\tborder: 1px solid transparent;\n\n\t&[dir="ltr"] {\n\t\ttext-align: left;\n\t}\n\n\t&[dir="rtl"] {\n\t\ttext-align: right;\n\t}\n\n\t/* https://github.com/ckeditor/ckeditor5-theme-lark/issues/116 */\n\t& > *:first-child {\n\t\tmargin-top: var(--ck-spacing-large);\n\t}\n\n\t/* https://github.com/ckeditor/ckeditor5/issues/847 */\n\t& > *:last-child {\n\t\tmargin-bottom: var(--ck-spacing-large);\n\t}\n\n\t/* https://github.com/ckeditor/ckeditor5/issues/6517 */\n\t&.ck-blurred ::selection {\n\t\tbackground: var(--ck-color-editable-blur-selection);\n\t}\n}\n\n/* https://github.com/ckeditor/ckeditor5-theme-lark/issues/111 */\n.ck.ck-balloon-panel.ck-toolbar-container[class*="arrow_n"] {\n\t&::after {\n\t\tborder-bottom-color: var(--ck-color-base-foreground);\n\t}\n}\n\n.ck.ck-balloon-panel.ck-toolbar-container[class*="arrow_s"] {\n\t&::after {\n\t\tborder-top-color: var(--ck-color-base-foreground);\n\t}\n}\n',"/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * Implements rounded corner interface for .ck-rounded-corners class.\n *\n * @see $ck-border-radius\n */\n@define-mixin ck-rounded-corners {\n\tborder-radius: 0;\n\n\t@nest .ck-rounded-corners &,\n\t&.ck-rounded-corners {\n\t\tborder-radius: var(--ck-border-radius);\n\t\t@mixin-content;\n\t}\n}\n","/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * A visual style of focused element's border.\n */\n@define-mixin ck-focus-ring {\n\t/* Disable native outline. */\n\toutline: none;\n\tborder: var(--ck-focus-ring)\n}\n","/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * A helper to combine multiple shadows.\n */\n@define-mixin ck-box-shadow $shadowA, $shadowB: 0 0 {\n\tbox-shadow: $shadowA, $shadowB;\n}\n\n/**\n * Gives an element a drop shadow so it looks like a floating panel.\n */\n@define-mixin ck-drop-shadow {\n\t@mixin ck-box-shadow var(--ck-drop-shadow);\n}\n"],sourceRoot:""}]);e["a"]=a},function(t,e,n){"use strict";var o=n(2);var i=n.n(o);var r=n(3);var s=n.n(r);var a=s()(i.a);a.push([t.i,".ck.ck-label{display:block}.ck.ck-voice-label{display:none}.ck.ck-label{font-weight:700}","",{version:3,sources:["webpack://./node_modules/@ckeditor/ckeditor5-ui/theme/components/label/label.css","webpack://./node_modules/@ckeditor/ckeditor5-theme-lark/theme/ckeditor5-ui/components/label/label.css"],names:[],mappings:"AAKA,aACC,aACD,CAEA,mBACC,YACD,CCNA,aACC,eACD",sourcesContent:["/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n.ck.ck-label {\n\tdisplay: block;\n}\n\n.ck.ck-voice-label {\n\tdisplay: none;\n}\n","/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n.ck.ck-label {\n\tfont-weight: bold;\n}\n"],sourceRoot:""}]);e["a"]=a},function(t,e,n){"use strict";var o=n(2);var i=n.n(o);var r=n(3);var s=n.n(r);var a=s()(i.a);a.push([t.i,".ck.ck-sticky-panel .ck-sticky-panel__content_sticky{z-index:var(--ck-z-modal);position:fixed;top:0}.ck.ck-sticky-panel .ck-sticky-panel__content_sticky_bottom-limit{top:auto;position:absolute}.ck.ck-sticky-panel .ck-sticky-panel__content_sticky{box-shadow:var(--ck-drop-shadow),0 0;border-width:0 1px 1px;border-top-left-radius:0;border-top-right-radius:0}","",{version:3,sources:["webpack://./node_modules/@ckeditor/ckeditor5-ui/theme/components/panel/stickypanel.css","webpack://./node_modules/@ckeditor/ckeditor5-theme-lark/theme/ckeditor5-ui/components/panel/stickypanel.css","webpack://./node_modules/@ckeditor/ckeditor5-theme-lark/theme/mixins/_shadow.css"],names:[],mappings:"AAMC,qDACC,yBAA0B,CAC1B,cAAe,CACf,KACD,CAEA,kEACC,QAAS,CACT,iBACD,CCPA,qDCCA,oCAA8B,CDE7B,sBAAuB,CACvB,wBAAyB,CACzB,yBACD",sourcesContent:["/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n.ck.ck-sticky-panel {\n\t& .ck-sticky-panel__content_sticky {\n\t\tz-index: var(--ck-z-modal); /* #315 */\n\t\tposition: fixed;\n\t\ttop: 0;\n\t}\n\n\t& .ck-sticky-panel__content_sticky_bottom-limit {\n\t\ttop: auto;\n\t\tposition: absolute;\n\t}\n}\n",'/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n@import "../../../mixins/_shadow.css";\n\n.ck.ck-sticky-panel {\n\t& .ck-sticky-panel__content_sticky {\n\t\t@mixin ck-drop-shadow;\n\n\t\tborder-width: 0 1px 1px;\n\t\tborder-top-left-radius: 0;\n\t\tborder-top-right-radius: 0;\n\t}\n}\n',"/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * A helper to combine multiple shadows.\n */\n@define-mixin ck-box-shadow $shadowA, $shadowB: 0 0 {\n\tbox-shadow: $shadowA, $shadowB;\n}\n\n/**\n * Gives an element a drop shadow so it looks like a floating panel.\n */\n@define-mixin ck-drop-shadow {\n\t@mixin ck-box-shadow var(--ck-drop-shadow);\n}\n"],sourceRoot:""}]);e["a"]=a},function(t,e,n){"use strict";var o=n(2);var i=n.n(o);var r=n(3);var s=n.n(r);var a=s()(i.a);a.push([t.i,".ck.ck-dropdown{display:inline-block;position:relative}.ck.ck-dropdown .ck-dropdown__arrow{pointer-events:none;z-index:var(--ck-z-default)}.ck.ck-dropdown .ck-button.ck-dropdown__button{width:100%}.ck.ck-dropdown .ck-button.ck-dropdown__button.ck-on .ck-tooltip{display:none}.ck.ck-dropdown .ck-dropdown__panel{-webkit-backface-visibility:hidden;display:none;z-index:var(--ck-z-modal);position:absolute}.ck.ck-dropdown .ck-dropdown__panel.ck-dropdown__panel-visible{display:inline-block}.ck.ck-dropdown .ck-dropdown__panel.ck-dropdown__panel_ne,.ck.ck-dropdown .ck-dropdown__panel.ck-dropdown__panel_nw{bottom:100%}.ck.ck-dropdown .ck-dropdown__panel.ck-dropdown__panel_se,.ck.ck-dropdown .ck-dropdown__panel.ck-dropdown__panel_sw{top:100%;bottom:auto}.ck.ck-dropdown .ck-dropdown__panel.ck-dropdown__panel_ne,.ck.ck-dropdown .ck-dropdown__panel.ck-dropdown__panel_se{left:0}.ck.ck-dropdown .ck-dropdown__panel.ck-dropdown__panel_nw,.ck.ck-dropdown .ck-dropdown__panel.ck-dropdown__panel_sw{right:0}.ck.ck-toolbar .ck-dropdown__panel{z-index:calc(var(--ck-z-modal) + 1)}:root{--ck-dropdown-arrow-size:calc(var(--ck-icon-size)*0.5)}.ck.ck-dropdown{font-size:inherit}.ck.ck-dropdown .ck-dropdown__arrow{width:var(--ck-dropdown-arrow-size)}[dir=ltr] .ck.ck-dropdown .ck-dropdown__arrow{right:var(--ck-spacing-standard);margin-left:var(--ck-spacing-standard)}[dir=rtl] .ck.ck-dropdown .ck-dropdown__arrow{left:var(--ck-spacing-standard);margin-right:var(--ck-spacing-small)}.ck.ck-dropdown.ck-disabled .ck-dropdown__arrow{opacity:var(--ck-disabled-opacity)}[dir=ltr] .ck.ck-dropdown .ck-button.ck-dropdown__button:not(.ck-button_with-text){padding-left:var(--ck-spacing-small)}[dir=rtl] .ck.ck-dropdown .ck-button.ck-dropdown__button:not(.ck-button_with-text){padding-right:var(--ck-spacing-small)}.ck.ck-dropdown .ck-button.ck-dropdown__button .ck-button__label{width:7em;overflow:hidden;text-overflow:ellipsis}.ck.ck-dropdown .ck-button.ck-dropdown__button.ck-disabled .ck-button__label{opacity:var(--ck-disabled-opacity)}.ck.ck-dropdown .ck-button.ck-dropdown__button.ck-on{border-bottom-left-radius:0;border-bottom-right-radius:0}.ck.ck-dropdown .ck-button.ck-dropdown__button.ck-dropdown__button_label-width_auto .ck-button__label{width:auto}.ck.ck-dropdown__panel{border-radius:0}.ck-rounded-corners .ck.ck-dropdown__panel,.ck.ck-dropdown__panel.ck-rounded-corners{border-radius:var(--ck-border-radius)}.ck.ck-dropdown__panel{box-shadow:var(--ck-drop-shadow),0 0;background:var(--ck-color-dropdown-panel-background);border:1px solid var(--ck-color-dropdown-panel-border);bottom:0;min-width:100%}.ck.ck-dropdown__panel.ck-dropdown__panel_se{border-top-left-radius:0}.ck.ck-dropdown__panel.ck-dropdown__panel_sw{border-top-right-radius:0}.ck.ck-dropdown__panel.ck-dropdown__panel_ne{border-bottom-left-radius:0}.ck.ck-dropdown__panel.ck-dropdown__panel_nw{border-bottom-right-radius:0}","",{version:3,sources:["webpack://./node_modules/@ckeditor/ckeditor5-ui/theme/components/dropdown/dropdown.css","webpack://./node_modules/@ckeditor/ckeditor5-ui/theme/components/tooltip/mixins/_tooltip.css","webpack://./node_modules/@ckeditor/ckeditor5-theme-lark/theme/ckeditor5-ui/components/dropdown/dropdown.css","webpack://./node_modules/@ckeditor/ckeditor5-theme-lark/theme/mixins/_disabled.css","webpack://./node_modules/@ckeditor/ckeditor5-theme-lark/theme/mixins/_rounded.css","webpack://./node_modules/@ckeditor/ckeditor5-theme-lark/theme/mixins/_shadow.css"],names:[],mappings:"AAOA,gBACC,oBAAqB,CACrB,iBAyDD,CAvDC,oCACC,mBAAoB,CACpB,2BACD,CAGA,+CACC,UAOD,CCcA,iEACC,YACD,CDdA,oCAGC,kCAAmC,CAEnC,YAAa,CACb,yBAA0B,CAE1B,iBA8BD,CA5BC,+DACC,oBACD,CAEA,oHAEC,WACD,CAEA,oHAMC,QAAS,CACT,WACD,CAEA,oHAEC,MACD,CAEA,oHAEC,OACD,CAQF,mCACC,mCACD,CEhEA,MACC,sDACD,CAEA,gBAEC,iBAiED,CA/DC,oCACC,mCACD,CAGC,8CACC,gCAAiC,CAGjC,sCACD,CAIA,8CACC,+BAAgC,CAGhC,oCACD,CAGD,gDC/BA,kCDiCA,CAIE,mFAEC,oCACD,CAIA,mFAEC,qCACD,CAID,iEACC,SAAU,CACV,eAAgB,CAChB,sBACD,CAGA,6EC1DD,kCD4DC,CAGA,qDACC,2BAA4B,CAC5B,4BACD,CAEA,sGACC,UACD,CAIF,uBExEC,eFoGD,CA5BA,qFEpEE,qCFgGF,CA5BA,uBG1EC,oCAA8B,CH8E9B,oDAAqD,CACrD,sDAAuD,CACvD,QAAS,CAGT,cAmBD,CAfC,6CACC,wBACD,CAEA,6CACC,yBACD,CAEA,6CACC,2BACD,CAEA,6CACC,4BACD",sourcesContent:["/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n@import \"../tooltip/mixins/_tooltip.css\";\n\n.ck.ck-dropdown {\n\tdisplay: inline-block;\n\tposition: relative;\n\n\t& .ck-dropdown__arrow {\n\t\tpointer-events: none;\n\t\tz-index: var(--ck-z-default);\n\t}\n\n\t/* Dropdown button should span horizontally, e.g. in vertical toolbars */\n\t& .ck-button.ck-dropdown__button {\n\t\twidth: 100%;\n\n\t\t/* Disable main button's tooltip when the dropdown is open. Otherwise the panel may\n\t\tpartially cover the tooltip */\n\t\t&.ck-on {\n\t\t\t@mixin ck-tooltip_disabled;\n\t\t}\n\t}\n\n\t& .ck-dropdown__panel {\n\t\t/* This is to get rid of flickering when the tooltip is shown under the panel,\n\t\twhich looks like the panel moves vertically a pixel down and up. */\n\t\t-webkit-backface-visibility: hidden;\n\n\t\tdisplay: none;\n\t\tz-index: var(--ck-z-modal);\n\n\t\tposition: absolute;\n\n\t\t&.ck-dropdown__panel-visible {\n\t\t\tdisplay: inline-block;\n\t\t}\n\n\t\t&.ck-dropdown__panel_ne,\n\t\t&.ck-dropdown__panel_nw {\n\t\t\tbottom: 100%;\n\t\t}\n\n\t\t&.ck-dropdown__panel_se,\n\t\t&.ck-dropdown__panel_sw {\n\t\t\t/*\n\t\t\t * Using transform: translate3d( 0, 100%, 0 ) causes blurry dropdown on Chrome 67-78+ on non-retina displays.\n\t\t\t * See https://github.com/ckeditor/ckeditor5/issues/1053.\n\t\t\t */\n\t\t\ttop: 100%;\n\t\t\tbottom: auto;\n\t\t}\n\n\t\t&.ck-dropdown__panel_ne,\n\t\t&.ck-dropdown__panel_se {\n\t\t\tleft: 0px;\n\t\t}\n\n\t\t&.ck-dropdown__panel_nw,\n\t\t&.ck-dropdown__panel_sw {\n\t\t\tright: 0px;\n\t\t}\n\t}\n}\n\n/*\n * Toolbar dropdown panels should be always above the UI (eg. other dropdown panels) from the editor's content.\n * See https://github.com/ckeditor/ckeditor5/issues/7874\n */\n.ck.ck-toolbar .ck-dropdown__panel {\n\tz-index: calc( var(--ck-z-modal) + 1 );\n}\n","/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * Enables the tooltip, which is the tooltip is in DOM but\n * not yet displayed.\n */\n@define-mixin ck-tooltip_enabled {\n\t& .ck-tooltip {\n\t\tdisplay: block;\n\n\t\t/*\n\t\t * Don't display tooltips in devices which don't support :hover.\n\t\t * In fact, it's all about iOS, which forces user to click UI elements twice to execute\n\t\t * the primary action, when tooltips are enabled.\n\t\t *\n\t\t * Q: OK, but why not the following query?\n\t\t *\n\t\t * @media (hover) {\n\t\t * display: block;\n\t\t * }\n\t\t *\n\t\t * A: Because FF does not support it and it would completely disable tooltips\n\t\t * in that browser.\n\t\t *\n\t\t * More in https://github.com/ckeditor/ckeditor5/issues/920.\n\t\t */\n\t\t@media (hover:none) {\n\t\t\tdisplay: none;\n\t\t}\n\t}\n}\n\n/**\n * Disables the tooltip making it disappear from DOM.\n */\n@define-mixin ck-tooltip_disabled {\n\t& .ck-tooltip {\n\t\tdisplay: none;\n\t}\n}\n\n/**\n * Shows the tooltip, which is already in DOM.\n * Requires `ck-tooltip_enabled` first.\n */\n@define-mixin ck-tooltip_visible {\n\t& .ck-tooltip {\n\t\tvisibility: visible;\n\t\topacity: 1;\n\t}\n}\n",'/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n@import "../../../mixins/_rounded.css";\n@import "../../../mixins/_disabled.css";\n@import "../../../mixins/_shadow.css";\n@import "@ckeditor/ckeditor5-ui/theme/mixins/_dir.css";\n\n:root {\n\t--ck-dropdown-arrow-size: calc(0.5 * var(--ck-icon-size));\n}\n\n.ck.ck-dropdown {\n\t/* Enable font size inheritance, which allows fluid UI scaling. */\n\tfont-size: inherit;\n\n\t& .ck-dropdown__arrow {\n\t\twidth: var(--ck-dropdown-arrow-size);\n\t}\n\n\t@mixin ck-dir ltr {\n\t\t& .ck-dropdown__arrow {\n\t\t\tright: var(--ck-spacing-standard);\n\n\t\t\t/* A space to accommodate the triangle. */\n\t\t\tmargin-left: var(--ck-spacing-standard);\n\t\t}\n\t}\n\n\t@mixin ck-dir rtl {\n\t\t& .ck-dropdown__arrow {\n\t\t\tleft: var(--ck-spacing-standard);\n\n\t\t\t/* A space to accommodate the triangle. */\n\t\t\tmargin-right: var(--ck-spacing-small);\n\t\t}\n\t}\n\n\t&.ck-disabled .ck-dropdown__arrow {\n\t\t@mixin ck-disabled;\n\t}\n\n\t& .ck-button.ck-dropdown__button {\n\t\t@mixin ck-dir ltr {\n\t\t\t&:not(.ck-button_with-text) {\n\t\t\t\t/* Make sure dropdowns with just an icon have the right inner spacing */\n\t\t\t\tpadding-left: var(--ck-spacing-small);\n\t\t\t}\n\t\t}\n\n\t\t@mixin ck-dir rtl {\n\t\t\t&:not(.ck-button_with-text) {\n\t\t\t\t/* Make sure dropdowns with just an icon have the right inner spacing */\n\t\t\t\tpadding-right: var(--ck-spacing-small);\n\t\t\t}\n\t\t}\n\n\t\t/* #23 */\n\t\t& .ck-button__label {\n\t\t\twidth: 7em;\n\t\t\toverflow: hidden;\n\t\t\ttext-overflow: ellipsis;\n\t\t}\n\n\t\t/* https://github.com/ckeditor/ckeditor5-theme-lark/issues/70 */\n\t\t&.ck-disabled .ck-button__label {\n\t\t\t@mixin ck-disabled;\n\t\t}\n\n\t\t/* https://github.com/ckeditor/ckeditor5/issues/816 */\n\t\t&.ck-on {\n\t\t\tborder-bottom-left-radius: 0;\n\t\t\tborder-bottom-right-radius: 0;\n\t\t}\n\n\t\t&.ck-dropdown__button_label-width_auto .ck-button__label {\n\t\t\twidth: auto;\n\t\t}\n\t}\n}\n\n.ck.ck-dropdown__panel {\n\t@mixin ck-rounded-corners;\n\t@mixin ck-drop-shadow;\n\n\tbackground: var(--ck-color-dropdown-panel-background);\n\tborder: 1px solid var(--ck-color-dropdown-panel-border);\n\tbottom: 0;\n\n\t/* Make sure the panel is at least as wide as the drop-down\'s button. */\n\tmin-width: 100%;\n\n\t/* Disabled corner border radius to be consistent with the .dropdown__button\n\thttps://github.com/ckeditor/ckeditor5/issues/816 */\n\t&.ck-dropdown__panel_se {\n\t\tborder-top-left-radius: 0;\n\t}\n\n\t&.ck-dropdown__panel_sw {\n\t\tborder-top-right-radius: 0;\n\t}\n\n\t&.ck-dropdown__panel_ne {\n\t\tborder-bottom-left-radius: 0;\n\t}\n\n\t&.ck-dropdown__panel_nw {\n\t\tborder-bottom-right-radius: 0;\n\t}\n}\n',"/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * A class which indicates that an element holding it is disabled.\n */\n@define-mixin ck-disabled {\n\topacity: var(--ck-disabled-opacity);\n}\n","/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * Implements rounded corner interface for .ck-rounded-corners class.\n *\n * @see $ck-border-radius\n */\n@define-mixin ck-rounded-corners {\n\tborder-radius: 0;\n\n\t@nest .ck-rounded-corners &,\n\t&.ck-rounded-corners {\n\t\tborder-radius: var(--ck-border-radius);\n\t\t@mixin-content;\n\t}\n}\n","/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * A helper to combine multiple shadows.\n */\n@define-mixin ck-box-shadow $shadowA, $shadowB: 0 0 {\n\tbox-shadow: $shadowA, $shadowB;\n}\n\n/**\n * Gives an element a drop shadow so it looks like a floating panel.\n */\n@define-mixin ck-drop-shadow {\n\t@mixin ck-box-shadow var(--ck-drop-shadow);\n}\n"],sourceRoot:""}]);e["a"]=a},function(t,e,n){"use strict";var o=n(2);var i=n.n(o);var r=n(3);var s=n.n(r);var a=s()(i.a);a.push([t.i,".ck.ck-icon{vertical-align:middle}:root{--ck-icon-size:calc(var(--ck-line-height-base)*var(--ck-font-size-normal))}.ck.ck-icon{width:var(--ck-icon-size);height:var(--ck-icon-size);font-size:.8333350694em;will-change:transform}.ck.ck-icon,.ck.ck-icon *{color:inherit;cursor:inherit}.ck.ck-icon :not([fill]){fill:currentColor}","",{version:3,sources:["webpack://./node_modules/@ckeditor/ckeditor5-ui/theme/components/icon/icon.css","webpack://./node_modules/@ckeditor/ckeditor5-theme-lark/theme/ckeditor5-ui/components/icon/icon.css"],names:[],mappings:"AAKA,YACC,qBACD,CCFA,MACC,0EACD,CAEA,YACC,yBAA0B,CAC1B,0BAA2B,CAG3B,uBAAwB,CAQxB,qBAcD,CAZC,0BARA,aAAc,CAGd,cAgBA,CAJC,yBAEC,iBACD",sourcesContent:["/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n.ck.ck-icon {\n\tvertical-align: middle;\n}\n",'/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n:root {\n\t--ck-icon-size: calc(var(--ck-line-height-base) * var(--ck-font-size-normal));\n}\n\n.ck.ck-icon {\n\twidth: var(--ck-icon-size);\n\theight: var(--ck-icon-size);\n\n\t/* Multiplied by the height of the line in "px" should give SVG "viewport" dimensions */\n\tfont-size: .8333350694em;\n\n\tcolor: inherit;\n\n\t/* Inherit cursor style (#5). */\n\tcursor: inherit;\n\n\t/* This will prevent blurry icons on Firefox. See #340. */\n\twill-change: transform;\n\n\t& * {\n\t\t/* Inherit cursor style (#5). */\n\t\tcursor: inherit;\n\n\t\t/* Allows dynamic coloring of the icons. */\n\t\tcolor: inherit;\n\n\t\t&:not([fill]) {\n\t\t\t/* Needed by FF. */\n\t\t\tfill: currentColor;\n\t\t}\n\t}\n}\n'],sourceRoot:""}]);e["a"]=a},function(t,e,n){"use strict";var o=n(2);var i=n.n(o);var r=n(3);var s=n.n(r);var a=s()(i.a);a.push([t.i,'.ck.ck-tooltip,.ck.ck-tooltip .ck-tooltip__text:after{position:absolute;pointer-events:none;-webkit-backface-visibility:hidden}.ck.ck-tooltip{visibility:hidden;opacity:0;display:none;z-index:var(--ck-z-modal)}.ck.ck-tooltip .ck-tooltip__text{display:inline-block}.ck.ck-tooltip .ck-tooltip__text:after{content:"";width:0;height:0}:root{--ck-tooltip-arrow-size:5px}.ck.ck-tooltip{left:50%;top:0;transition:opacity .2s ease-in-out .2s}.ck.ck-tooltip .ck-tooltip__text{border-radius:0}.ck-rounded-corners .ck.ck-tooltip .ck-tooltip__text,.ck.ck-tooltip .ck-tooltip__text.ck-rounded-corners{border-radius:var(--ck-border-radius)}.ck.ck-tooltip .ck-tooltip__text{font-size:.9em;line-height:1.5;color:var(--ck-color-tooltip-text);padding:var(--ck-spacing-small) var(--ck-spacing-medium);background:var(--ck-color-tooltip-background);position:relative;left:-50%}.ck.ck-tooltip .ck-tooltip__text:after{transition:opacity .2s ease-in-out .2s;border-style:solid;left:50%}.ck.ck-tooltip.ck-tooltip_s,.ck.ck-tooltip.ck-tooltip_se,.ck.ck-tooltip.ck-tooltip_sw{bottom:calc(var(--ck-tooltip-arrow-size)*-1);transform:translateY(100%)}.ck.ck-tooltip.ck-tooltip_s .ck-tooltip__text:after,.ck.ck-tooltip.ck-tooltip_se .ck-tooltip__text:after,.ck.ck-tooltip.ck-tooltip_sw .ck-tooltip__text:after{top:calc(var(--ck-tooltip-arrow-size)*-1 + 1px);transform:translateX(-50%);border-left-color:transparent;border-bottom-color:var(--ck-color-tooltip-background);border-right-color:transparent;border-top-color:transparent;border-left-width:var(--ck-tooltip-arrow-size);border-bottom-width:var(--ck-tooltip-arrow-size);border-right-width:var(--ck-tooltip-arrow-size);border-top-width:0}.ck.ck-tooltip.ck-tooltip_sw{right:50%;left:auto}.ck.ck-tooltip.ck-tooltip_sw .ck-tooltip__text{left:auto;right:calc(var(--ck-tooltip-arrow-size)*-2)}.ck.ck-tooltip.ck-tooltip_sw .ck-tooltip__text:after{left:auto;right:0}.ck.ck-tooltip.ck-tooltip_se{left:50%;right:auto}.ck.ck-tooltip.ck-tooltip_se .ck-tooltip__text{right:auto;left:calc(var(--ck-tooltip-arrow-size)*-2)}.ck.ck-tooltip.ck-tooltip_se .ck-tooltip__text:after{right:auto;left:0;transform:translateX(50%)}.ck.ck-tooltip.ck-tooltip_n{top:calc(var(--ck-tooltip-arrow-size)*-1);transform:translateY(-100%)}.ck.ck-tooltip.ck-tooltip_n .ck-tooltip__text:after{bottom:calc(var(--ck-tooltip-arrow-size)*-1);transform:translateX(-50%);border-left-color:transparent;border-bottom-color:transparent;border-right-color:transparent;border-top-color:var(--ck-color-tooltip-background);border-left-width:var(--ck-tooltip-arrow-size);border-bottom-width:0;border-right-width:var(--ck-tooltip-arrow-size);border-top-width:var(--ck-tooltip-arrow-size)}.ck.ck-tooltip.ck-tooltip_e{left:calc(100% + var(--ck-tooltip-arrow-size));top:50%}.ck.ck-tooltip.ck-tooltip_e .ck-tooltip__text{left:0;transform:translateY(-50%)}.ck.ck-tooltip.ck-tooltip_e .ck-tooltip__text:after{left:calc(var(--ck-tooltip-arrow-size)*-1);top:calc(50% - var(--ck-tooltip-arrow-size)*1);border-left-color:transparent;border-bottom-color:transparent;border-right-color:var(--ck-color-tooltip-background);border-top-color:transparent;border-left-width:0;border-bottom-width:var(--ck-tooltip-arrow-size);border-right-width:var(--ck-tooltip-arrow-size);border-top-width:var(--ck-tooltip-arrow-size)}.ck.ck-tooltip.ck-tooltip_w{right:calc(100% + var(--ck-tooltip-arrow-size));left:auto;top:50%}.ck.ck-tooltip.ck-tooltip_w .ck-tooltip__text{left:0;transform:translateY(-50%)}.ck.ck-tooltip.ck-tooltip_w .ck-tooltip__text:after{left:100%;top:calc(50% - var(--ck-tooltip-arrow-size)*1);border-left-color:var(--ck-color-tooltip-background);border-bottom-color:transparent;border-right-color:transparent;border-top-color:transparent;border-left-width:var(--ck-tooltip-arrow-size);border-bottom-width:var(--ck-tooltip-arrow-size);border-right-width:0;border-top-width:var(--ck-tooltip-arrow-size)}',"",{version:3,sources:["webpack://./node_modules/@ckeditor/ckeditor5-ui/theme/components/tooltip/tooltip.css","webpack://./node_modules/@ckeditor/ckeditor5-theme-lark/theme/ckeditor5-ui/components/tooltip/tooltip.css","webpack://./node_modules/@ckeditor/ckeditor5-theme-lark/theme/mixins/_rounded.css"],names:[],mappings:"AAKA,sDAEC,iBAAkB,CAGlB,mBAAoB,CAIpB,kCACD,CAEA,eAEC,iBAAkB,CAClB,SAAU,CACV,YAAa,CACb,yBAWD,CATC,iCACC,oBAOD,CALC,uCACC,UAAW,CACX,OAAQ,CACR,QACD,CCxBF,MACC,2BACD,CAEA,eACC,QAAS,CAMT,KAAM,CAON,sCAwKD,CAtKC,iCChBA,eDqCA,CArBA,yGCZC,qCDiCD,CArBA,iCAGC,cAAe,CACf,eAAgB,CAChB,kCAAmC,CACnC,wDAAyD,CACzD,6CAA8C,CAC9C,iBAAkB,CAClB,SAYD,CAVC,uCAMC,sCAAuC,CACvC,kBAAmB,CACnB,QACD,CAYD,sFAGC,4CAA+C,CAC/C,0BASD,CAPC,8JAEC,+CAAkD,CAClD,0BAA6B,CAC7B,6BAAoF,CAApF,sDAAoF,CAApF,8BAAoF,CAApF,4BAAoF,CACpF,8CAAsG,CAAtG,gDAAsG,CAAtG,+CAAsG,CAAtG,kBACD,CAaD,6BACC,SAAU,CACV,SAWD,CATC,+CACC,SAAU,CACV,2CACD,CAEA,qDACC,SAAU,CACV,OACD,CAYD,6BACC,QAAS,CACT,UAYD,CAVC,+CACC,UAAW,CACX,0CACD,CAEA,qDACC,UAAW,CACX,MAAO,CACP,yBACD,CAYD,4BACC,yCAA4C,CAC5C,2BAQD,CANC,oDACC,4CAA+C,CAC/C,0BAA6B,CAC7B,6BAAoF,CAApF,+BAAoF,CAApF,8BAAoF,CAApF,mDAAoF,CACpF,8CAAsG,CAAtG,qBAAsG,CAAtG,+CAAsG,CAAtG,6CACD,CAUD,4BACC,8CAA+C,CAC/C,OAaD,CAXC,8CACC,MAAO,CACP,0BAQD,CANC,oDACC,0CAA6C,CAC7C,8CAAiD,CACjD,6BAAoF,CAApF,+BAAoF,CAApF,qDAAoF,CAApF,4BAAoF,CACpF,mBAAsG,CAAtG,gDAAsG,CAAtG,+CAAsG,CAAtG,6CACD,CAWF,4BACC,+CAAgD,CAChD,SAAU,CACV,OAaD,CAXC,8CACC,MAAO,CACP,0BAQD,CANC,oDACC,SAAU,CACV,8CAAiD,CACjD,oDAAoF,CAApF,+BAAoF,CAApF,8BAAoF,CAApF,4BAAoF,CACpF,8CAAsG,CAAtG,gDAAsG,CAAtG,oBAAsG,CAAtG,6CACD",sourcesContent:['/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n.ck.ck-tooltip,\n.ck.ck-tooltip .ck-tooltip__text::after {\n\tposition: absolute;\n\n\t/* Without this, hovering the tooltip could keep it visible. */\n\tpointer-events: none;\n\n\t/* This is to get rid of flickering when transitioning opacity in Chrome.\n\tIt\'s weird but it works. */\n\t-webkit-backface-visibility: hidden;\n}\n\n.ck.ck-tooltip {\n\t/* Tooltip is hidden by default. */\n\tvisibility: hidden;\n\topacity: 0;\n\tdisplay: none;\n\tz-index: var(--ck-z-modal);\n\n\t& .ck-tooltip__text {\n\t\tdisplay: inline-block;\n\n\t\t&::after {\n\t\t\tcontent: "";\n\t\t\twidth: 0;\n\t\t\theight: 0;\n\t\t}\n\t}\n}\n','/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n@import "../../../mixins/_rounded.css";\n\n:root {\n\t--ck-tooltip-arrow-size: 5px;\n}\n\n.ck.ck-tooltip {\n\tleft: 50%;\n\n\t/*\n\t * Prevent blurry tooltips in LoDPI environments.\n\t * See https://github.com/ckeditor/ckeditor5/issues/1802.\n\t */\n\ttop: 0;\n\n\t/*\n\t * For the transition to work, the tooltip must be controlled\n\t * using visibility+opacity. A delay prevents a "tooltip avalanche"\n\t * i.e. when scanning the toolbar with mouse cursor.\n\t */\n\ttransition: opacity .2s ease-in-out .2s;\n\n\t& .ck-tooltip__text {\n\t\t@mixin ck-rounded-corners;\n\n\t\tfont-size: .9em;\n\t\tline-height: 1.5;\n\t\tcolor: var(--ck-color-tooltip-text);\n\t\tpadding: var(--ck-spacing-small) var(--ck-spacing-medium);\n\t\tbackground: var(--ck-color-tooltip-background);\n\t\tposition: relative;\n\t\tleft: -50%;\n\n\t\t&::after {\n\t\t\t/*\n\t\t\t * For the transition to work, the tooltip must be controlled\n\t\t\t * using visibility+opacity. A delay prevents a "tooltip avalanche"\n\t\t\t * i.e. when scanning the toolbar with mouse cursor.\n\t\t\t */\n\t\t\ttransition: opacity .2s ease-in-out .2s;\n\t\t\tborder-style: solid;\n\t\t\tleft: 50%;\n\t\t}\n\t}\n\n\t/**\n\t * A class that displays the tooltip south of the element.\n\t *\n\t * [element]\n\t * ^\n\t * +-----------+\n\t * | Tooltip |\n\t * +-----------+\n\t */\n\t&.ck-tooltip_s,\n\t&.ck-tooltip_sw,\n\t&.ck-tooltip_se {\n\t\tbottom: calc(-1 * var(--ck-tooltip-arrow-size));\n\t\ttransform: translateY( 100% );\n\n\t\t& .ck-tooltip__text::after {\n\t\t\t/* 1px addresses gliches in rendering causing gap between the triangle and the text */\n\t\t\ttop: calc(-1 * var(--ck-tooltip-arrow-size) + 1px);\n\t\t\ttransform: translateX( -50% );\n\t\t\tborder-color: transparent transparent var(--ck-color-tooltip-background) transparent;\n\t\t\tborder-width: 0 var(--ck-tooltip-arrow-size) var(--ck-tooltip-arrow-size) var(--ck-tooltip-arrow-size);\n\t\t}\n\t}\n\n\t/**\n\t * A class that displays the tooltip south-west of the element.\n\t *\n\t * [element]\n\t * ^\n\t * +-----------+\n\t * | Tooltip |\n\t * +-----------+\n\t */\n\n\t&.ck-tooltip_sw {\n\t\tright: 50%;\n\t\tleft: auto;\n\n\t\t& .ck-tooltip__text {\n\t\t\tleft: auto;\n\t\t\tright: calc( -2 * var(--ck-tooltip-arrow-size));\n\t\t}\n\n\t\t& .ck-tooltip__text::after {\n\t\t\tleft: auto;\n\t\t\tright: 0;\n\t\t}\n\t}\n\n\t/**\n\t * A class that displays the tooltip south-east of the element.\n\t *\n\t * [element]\n\t * ^\n\t * +-----------+\n\t * | Tooltip |\n\t * +-----------+\n\t */\n\t&.ck-tooltip_se {\n\t\tleft: 50%;\n\t\tright: auto;\n\n\t\t& .ck-tooltip__text {\n\t\t\tright: auto;\n\t\t\tleft: calc( -2 * var(--ck-tooltip-arrow-size));\n\t\t}\n\n\t\t& .ck-tooltip__text::after {\n\t\t\tright: auto;\n\t\t\tleft: 0;\n\t\t\ttransform: translateX( 50% );\n\t\t}\n\t}\n\n\t/**\n\t * A class that displays the tooltip north of the element.\n\t *\n\t * +-----------+\n\t * | Tooltip |\n\t * +-----------+\n\t * V\n\t * [element]\n\t */\n\t&.ck-tooltip_n {\n\t\ttop: calc(-1 * var(--ck-tooltip-arrow-size));\n\t\ttransform: translateY( -100% );\n\n\t\t& .ck-tooltip__text::after {\n\t\t\tbottom: calc(-1 * var(--ck-tooltip-arrow-size));\n\t\t\ttransform: translateX( -50% );\n\t\t\tborder-color: var(--ck-color-tooltip-background) transparent transparent transparent;\n\t\t\tborder-width: var(--ck-tooltip-arrow-size) var(--ck-tooltip-arrow-size) 0 var(--ck-tooltip-arrow-size);\n\t\t}\n\t}\n\n\t/**\n\t * A class that displays the tooltip east of the element.\n\t *\n\t * +----------+\n\t * [element] < | east |\n\t * +----------+\n\t */\n\t&.ck-tooltip_e {\n\t\tleft: calc(100% + var(--ck-tooltip-arrow-size));\n\t\ttop: 50%;\n\n\t\t& .ck-tooltip__text {\n\t\t\tleft: 0;\n\t\t\ttransform: translateY( -50% );\n\n\t\t\t&::after {\n\t\t\t\tleft: calc(-1 * var(--ck-tooltip-arrow-size));\n\t\t\t\ttop: calc(50% - 1 * var(--ck-tooltip-arrow-size));\n\t\t\t\tborder-color: transparent var(--ck-color-tooltip-background) transparent transparent;\n\t\t\t\tborder-width: var(--ck-tooltip-arrow-size) var(--ck-tooltip-arrow-size) var(--ck-tooltip-arrow-size) 0;\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * A class that displays the tooltip west of the element.\n\t *\n\t * +----------+\n\t * | west | > [element]\n\t * +----------+\n\t */\n\t&.ck-tooltip_w {\n\t\tright: calc(100% + var(--ck-tooltip-arrow-size));\n\t\tleft: auto;\n\t\ttop: 50%;\n\n\t\t& .ck-tooltip__text {\n\t\t\tleft: 0;\n\t\t\ttransform: translateY( -50% );\n\n\t\t\t&::after {\n\t\t\t\tleft: 100%;\n\t\t\t\ttop: calc(50% - 1 * var(--ck-tooltip-arrow-size));\n\t\t\t\tborder-color: transparent transparent transparent var(--ck-color-tooltip-background);\n\t\t\t\tborder-width: var(--ck-tooltip-arrow-size) 0 var(--ck-tooltip-arrow-size) var(--ck-tooltip-arrow-size);\n\t\t\t}\n\t\t}\n\t}\n}\n',"/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * Implements rounded corner interface for .ck-rounded-corners class.\n *\n * @see $ck-border-radius\n */\n@define-mixin ck-rounded-corners {\n\tborder-radius: 0;\n\n\t@nest .ck-rounded-corners &,\n\t&.ck-rounded-corners {\n\t\tborder-radius: var(--ck-border-radius);\n\t\t@mixin-content;\n\t}\n}\n"],sourceRoot:""}]);e["a"]=a},function(t,e,n){"use strict";var o=n(2);var i=n.n(o);var r=n(3);var s=n.n(r);var a=s()(i.a);a.push([t.i,".ck.ck-button,a.ck.ck-button{-moz-user-select:none;-webkit-user-select:none;-ms-user-select:none;user-select:none}.ck.ck-button .ck-tooltip,a.ck.ck-button .ck-tooltip{display:block}@media (hover:none){.ck.ck-button .ck-tooltip,a.ck.ck-button .ck-tooltip{display:none}}.ck.ck-button,a.ck.ck-button{position:relative;display:inline-flex;align-items:center;justify-content:left}.ck.ck-button .ck-button__label,a.ck.ck-button .ck-button__label{display:none}.ck.ck-button.ck-button_with-text .ck-button__label,a.ck.ck-button.ck-button_with-text .ck-button__label{display:inline-block}.ck.ck-button:not(.ck-button_with-text),a.ck.ck-button:not(.ck-button_with-text){justify-content:center}.ck.ck-button:hover .ck-tooltip,a.ck.ck-button:hover .ck-tooltip{visibility:visible;opacity:1}.ck.ck-button:focus:not(:hover) .ck-tooltip,a.ck.ck-button:focus:not(:hover) .ck-tooltip{display:none}.ck.ck-button,a.ck.ck-button{background:var(--ck-color-button-default-background)}.ck.ck-button:not(.ck-disabled):hover,a.ck.ck-button:not(.ck-disabled):hover{background:var(--ck-color-button-default-hover-background)}.ck.ck-button:not(.ck-disabled):active,a.ck.ck-button:not(.ck-disabled):active{background:var(--ck-color-button-default-active-background);box-shadow:inset 0 2px 2px var(--ck-color-button-default-active-shadow)}.ck.ck-button.ck-disabled,a.ck.ck-button.ck-disabled{background:var(--ck-color-button-default-disabled-background)}.ck.ck-button,a.ck.ck-button{border-radius:0}.ck-rounded-corners .ck.ck-button,.ck-rounded-corners a.ck.ck-button,.ck.ck-button.ck-rounded-corners,a.ck.ck-button.ck-rounded-corners{border-radius:var(--ck-border-radius)}.ck.ck-button,a.ck.ck-button{white-space:nowrap;cursor:default;vertical-align:middle;padding:var(--ck-spacing-tiny);text-align:center;min-width:var(--ck-ui-component-min-height);min-height:var(--ck-ui-component-min-height);line-height:1;font-size:inherit;border:1px solid transparent;transition:box-shadow .2s ease-in-out,border .2s ease-in-out;-webkit-appearance:none}.ck.ck-button:active,.ck.ck-button:focus,a.ck.ck-button:active,a.ck.ck-button:focus{outline:none;border:var(--ck-focus-ring);box-shadow:var(--ck-focus-outer-shadow),0 0}.ck.ck-button .ck-button__icon use,.ck.ck-button .ck-button__icon use *,a.ck.ck-button .ck-button__icon use,a.ck.ck-button .ck-button__icon use *{color:inherit}.ck.ck-button .ck-button__label,a.ck.ck-button .ck-button__label{font-size:inherit;font-weight:inherit;color:inherit;cursor:inherit;vertical-align:middle}[dir=ltr] .ck.ck-button .ck-button__label,[dir=ltr] a.ck.ck-button .ck-button__label{text-align:left}[dir=rtl] .ck.ck-button .ck-button__label,[dir=rtl] a.ck.ck-button .ck-button__label{text-align:right}.ck.ck-button .ck-button__keystroke,a.ck.ck-button .ck-button__keystroke{color:inherit}[dir=ltr] .ck.ck-button .ck-button__keystroke,[dir=ltr] a.ck.ck-button .ck-button__keystroke{margin-left:var(--ck-spacing-large)}[dir=rtl] .ck.ck-button .ck-button__keystroke,[dir=rtl] a.ck.ck-button .ck-button__keystroke{margin-right:var(--ck-spacing-large)}.ck.ck-button .ck-button__keystroke,a.ck.ck-button .ck-button__keystroke{font-weight:700;opacity:.7}.ck.ck-button.ck-disabled:active,.ck.ck-button.ck-disabled:focus,a.ck.ck-button.ck-disabled:active,a.ck.ck-button.ck-disabled:focus{box-shadow:var(--ck-focus-disabled-outer-shadow),0 0}.ck.ck-button.ck-disabled .ck-button__icon,a.ck.ck-button.ck-disabled .ck-button__icon{opacity:var(--ck-disabled-opacity)}.ck.ck-button.ck-disabled .ck-button__label,a.ck.ck-button.ck-disabled .ck-button__label{opacity:var(--ck-disabled-opacity)}.ck.ck-button.ck-disabled .ck-button__keystroke,a.ck.ck-button.ck-disabled .ck-button__keystroke{opacity:.3}.ck.ck-button.ck-button_with-text,a.ck.ck-button.ck-button_with-text{padding:var(--ck-spacing-tiny) var(--ck-spacing-standard)}[dir=ltr] .ck.ck-button.ck-button_with-text .ck-button__icon,[dir=ltr] a.ck.ck-button.ck-button_with-text .ck-button__icon{margin-left:calc(var(--ck-spacing-small)*-1);margin-right:var(--ck-spacing-small)}[dir=rtl] .ck.ck-button.ck-button_with-text .ck-button__icon,[dir=rtl] a.ck.ck-button.ck-button_with-text .ck-button__icon{margin-right:calc(var(--ck-spacing-small)*-1);margin-left:var(--ck-spacing-small)}.ck.ck-button.ck-button_with-keystroke .ck-button__label,a.ck.ck-button.ck-button_with-keystroke .ck-button__label{flex-grow:1}.ck.ck-button.ck-on,a.ck.ck-button.ck-on{background:var(--ck-color-button-on-background)}.ck.ck-button.ck-on:not(.ck-disabled):hover,a.ck.ck-button.ck-on:not(.ck-disabled):hover{background:var(--ck-color-button-on-hover-background)}.ck.ck-button.ck-on:not(.ck-disabled):active,a.ck.ck-button.ck-on:not(.ck-disabled):active{background:var(--ck-color-button-on-active-background);box-shadow:inset 0 2px 2px var(--ck-color-button-on-active-shadow)}.ck.ck-button.ck-on.ck-disabled,a.ck.ck-button.ck-on.ck-disabled{background:var(--ck-color-button-on-disabled-background)}.ck.ck-button.ck-button-save,a.ck.ck-button.ck-button-save{color:var(--ck-color-button-save)}.ck.ck-button.ck-button-cancel,a.ck.ck-button.ck-button-cancel{color:var(--ck-color-button-cancel)}.ck.ck-button-action,a.ck.ck-button-action{background:var(--ck-color-button-action-background)}.ck.ck-button-action:not(.ck-disabled):hover,a.ck.ck-button-action:not(.ck-disabled):hover{background:var(--ck-color-button-action-hover-background)}.ck.ck-button-action:not(.ck-disabled):active,a.ck.ck-button-action:not(.ck-disabled):active{background:var(--ck-color-button-action-active-background);box-shadow:inset 0 2px 2px var(--ck-color-button-action-active-shadow)}.ck.ck-button-action.ck-disabled,a.ck.ck-button-action.ck-disabled{background:var(--ck-color-button-action-disabled-background)}.ck.ck-button-action,a.ck.ck-button-action{color:var(--ck-color-button-action-text)}.ck.ck-button-bold,a.ck.ck-button-bold{font-weight:700}","",{version:3,sources:["webpack://./node_modules/@ckeditor/ckeditor5-ui/theme/components/button/button.css","webpack://./node_modules/@ckeditor/ckeditor5-ui/theme/mixins/_unselectable.css","webpack://./node_modules/@ckeditor/ckeditor5-ui/theme/components/tooltip/mixins/_tooltip.css","webpack://./node_modules/@ckeditor/ckeditor5-theme-lark/theme/ckeditor5-ui/components/button/button.css","webpack://./node_modules/@ckeditor/ckeditor5-theme-lark/theme/ckeditor5-ui/mixins/_button.css","webpack://./node_modules/@ckeditor/ckeditor5-theme-lark/theme/mixins/_rounded.css","webpack://./node_modules/@ckeditor/ckeditor5-theme-lark/theme/mixins/_focus.css","webpack://./node_modules/@ckeditor/ckeditor5-theme-lark/theme/mixins/_shadow.css","webpack://./node_modules/@ckeditor/ckeditor5-theme-lark/theme/mixins/_disabled.css"],names:[],mappings:"AAQA,6BCCC,qBAAsB,CACtB,wBAAyB,CACzB,oBAAqB,CACrB,gBD6BD,CE/BC,qDACC,aAqBD,CAHC,oBAnBD,qDAoBE,YAEF,CADC,CFvBF,6BAKC,iBAAkB,CAClB,mBAAoB,CACpB,kBAAmB,CACnB,oBAyBD,CAvBC,iEACC,YACD,CAGC,yGACC,oBACD,CAID,iFACC,sBACD,CEkBA,iEACC,kBAAmB,CACnB,SACD,CAbA,yFACC,YACD,CC7BD,6BCAC,oDD0ID,CCvIE,6EACC,0DACD,CAEA,+EACC,2DAA4C,CAC5C,uEACD,CAID,qDACC,6DACD,CDhBD,6BEDC,eF2ID,CA1IA,wIEGE,qCFuIF,CA1IA,6BAKC,kBAAmB,CACnB,cAAe,CACf,qBAAsB,CACtB,8BAA+B,CAC/B,iBAAkB,CAGlB,2CAA4C,CAC5C,4CAA6C,CAI7C,aAAc,CAGd,iBAAkB,CAGlB,4BAA6B,CAG7B,4DAA8D,CAG9D,uBA6GD,CA3GC,oFGjCA,YAAa,CACb,2BAA2B,CCF3B,2CJsCA,CAIC,kJAEC,aACD,CAGD,iEAEC,iBAAkB,CAClB,mBAAoB,CACpB,aAAc,CACd,cAAe,CAIf,qBASD,CAlBA,qFAYE,eAMF,CAlBA,qFAgBE,gBAEF,CAEA,yEACC,aAYD,CAbA,6FAIE,mCASF,CAbA,6FAQE,oCAKF,CAbA,yEAWC,eAAiB,CACjB,UACD,CAIC,oIIrFD,oDJyFC,CAEA,uFK3FD,kCL6FC,CAGA,yFKhGD,kCLkGC,CAEA,iGACC,UACD,CAGD,qEACC,yDAcD,CAXC,2HAEE,4CAA+C,CAC/C,oCAOF,CAVA,2HAOE,6CAAgD,CAChD,mCAEF,CAKA,mHACC,WACD,CAID,yCC/HA,+CDiIA,CC9HC,yFACC,qDACD,CAEA,2FACC,sDAA4C,CAC5C,kEACD,CAID,iEACC,wDACD,CDmHA,2DACC,iCACD,CAEA,+DACC,mCACD,CAID,2CC7IC,mDDkJD,CC/IE,2FACC,yDACD,CAEA,6FACC,0DAA4C,CAC5C,sEACD,CAID,mEACC,4DACD,CD6HD,2CAIC,wCACD,CAEA,uCAEC,eACD",sourcesContent:['/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n@import "../../mixins/_unselectable.css";\n@import "../tooltip/mixins/_tooltip.css";\n\n.ck.ck-button,\na.ck.ck-button {\n\t@mixin ck-unselectable;\n\t@mixin ck-tooltip_enabled;\n\n\tposition: relative;\n\tdisplay: inline-flex;\n\talign-items: center;\n\tjustify-content: left;\n\n\t& .ck-button__label {\n\t\tdisplay: none;\n\t}\n\n\t&.ck-button_with-text {\n\t\t& .ck-button__label {\n\t\t\tdisplay: inline-block;\n\t\t}\n\t}\n\n\t/* Center the icon horizontally in a button without text. */\n\t&:not(.ck-button_with-text) {\n\t\tjustify-content: center;\n\t}\n\n\t&:hover {\n\t\t@mixin ck-tooltip_visible;\n\t}\n\n\t/* Get rid of the native focus outline around the tooltip when focused (but not :hover). */\n\t&:focus:not(:hover) {\n\t\t@mixin ck-tooltip_disabled;\n\t}\n}\n',"/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * Makes element unselectable.\n */\n@define-mixin ck-unselectable {\n\t-moz-user-select: none;\n\t-webkit-user-select: none;\n\t-ms-user-select: none;\n\tuser-select: none\n}\n","/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * Enables the tooltip, which is the tooltip is in DOM but\n * not yet displayed.\n */\n@define-mixin ck-tooltip_enabled {\n\t& .ck-tooltip {\n\t\tdisplay: block;\n\n\t\t/*\n\t\t * Don't display tooltips in devices which don't support :hover.\n\t\t * In fact, it's all about iOS, which forces user to click UI elements twice to execute\n\t\t * the primary action, when tooltips are enabled.\n\t\t *\n\t\t * Q: OK, but why not the following query?\n\t\t *\n\t\t * @media (hover) {\n\t\t * display: block;\n\t\t * }\n\t\t *\n\t\t * A: Because FF does not support it and it would completely disable tooltips\n\t\t * in that browser.\n\t\t *\n\t\t * More in https://github.com/ckeditor/ckeditor5/issues/920.\n\t\t */\n\t\t@media (hover:none) {\n\t\t\tdisplay: none;\n\t\t}\n\t}\n}\n\n/**\n * Disables the tooltip making it disappear from DOM.\n */\n@define-mixin ck-tooltip_disabled {\n\t& .ck-tooltip {\n\t\tdisplay: none;\n\t}\n}\n\n/**\n * Shows the tooltip, which is already in DOM.\n * Requires `ck-tooltip_enabled` first.\n */\n@define-mixin ck-tooltip_visible {\n\t& .ck-tooltip {\n\t\tvisibility: visible;\n\t\topacity: 1;\n\t}\n}\n",'/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n@import "../../../mixins/_focus.css";\n@import "../../../mixins/_shadow.css";\n@import "../../../mixins/_disabled.css";\n@import "../../../mixins/_rounded.css";\n@import "../../mixins/_button.css";\n@import "@ckeditor/ckeditor5-ui/theme/mixins/_dir.css";\n\n.ck.ck-button,\na.ck.ck-button {\n\t@mixin ck-button-colors --ck-color-button-default;\n\t@mixin ck-rounded-corners;\n\n\twhite-space: nowrap;\n\tcursor: default;\n\tvertical-align: middle;\n\tpadding: var(--ck-spacing-tiny);\n\ttext-align: center;\n\n\t/* A very important piece of styling. Go to variable declaration to learn more. */\n\tmin-width: var(--ck-ui-component-min-height);\n\tmin-height: var(--ck-ui-component-min-height);\n\n\t/* Normalize the height of the line. Removing this will break consistent height\n\tamong text and text-less buttons (with icons). */\n\tline-height: 1;\n\n\t/* Enable font size inheritance, which allows fluid UI scaling. */\n\tfont-size: inherit;\n\n\t/* Avoid flickering when the foucs border shows up. */\n\tborder: 1px solid transparent;\n\n\t/* Apply some smooth transition to the box-shadow and border. */\n\ttransition: box-shadow .2s ease-in-out, border .2s ease-in-out;\n\n\t/* https://github.com/ckeditor/ckeditor5-theme-lark/issues/189 */\n\t-webkit-appearance: none;\n\n\t&:active,\n\t&:focus {\n\t\t@mixin ck-focus-ring;\n\t\t@mixin ck-box-shadow var(--ck-focus-outer-shadow);\n\t}\n\n\t/* Allow icon coloring using the text "color" property. */\n\t& .ck-button__icon {\n\t\t& use,\n\t\t& use * {\n\t\t\tcolor: inherit;\n\t\t}\n\t}\n\n\t& .ck-button__label {\n\t\t/* Enable font size inheritance, which allows fluid UI scaling. */\n\t\tfont-size: inherit;\n\t\tfont-weight: inherit;\n\t\tcolor: inherit;\n\t\tcursor: inherit;\n\n\t\t/* Must be consistent with .ck-icon\'s vertical align. Otherwise, buttons with and\n\t\twithout labels (but with icons) have different sizes in Chrome */\n\t\tvertical-align: middle;\n\n\t\t@mixin ck-dir ltr {\n\t\t\ttext-align: left;\n\t\t}\n\n\t\t@mixin ck-dir rtl {\n\t\t\ttext-align: right;\n\t\t}\n\t}\n\n\t& .ck-button__keystroke {\n\t\tcolor: inherit;\n\n\t\t@mixin ck-dir ltr {\n\t\t\tmargin-left: var(--ck-spacing-large);\n\t\t}\n\n\t\t@mixin ck-dir rtl {\n\t\t\tmargin-right: var(--ck-spacing-large);\n\t\t}\n\n\t\tfont-weight: bold;\n\t\topacity: .7;\n\t}\n\n\t/* https://github.com/ckeditor/ckeditor5-theme-lark/issues/70 */\n\t&.ck-disabled {\n\t\t&:active,\n\t\t&:focus {\n\t\t\t/* The disabled button should have a slightly less visible shadow when focused. */\n\t\t\t@mixin ck-box-shadow var(--ck-focus-disabled-outer-shadow);\n\t\t}\n\n\t\t& .ck-button__icon {\n\t\t\t@mixin ck-disabled;\n\t\t}\n\n\t\t/* https://github.com/ckeditor/ckeditor5-theme-lark/issues/98 */\n\t\t& .ck-button__label {\n\t\t\t@mixin ck-disabled;\n\t\t}\n\n\t\t& .ck-button__keystroke {\n\t\t\topacity: .3;\n\t\t}\n\t}\n\n\t&.ck-button_with-text {\n\t\tpadding: var(--ck-spacing-tiny) var(--ck-spacing-standard);\n\n\t\t/* stylelint-disable-next-line no-descending-specificity */\n\t\t& .ck-button__icon {\n\t\t\t@mixin ck-dir ltr {\n\t\t\t\tmargin-left: calc(-1 * var(--ck-spacing-small));\n\t\t\t\tmargin-right: var(--ck-spacing-small);\n\t\t\t}\n\n\t\t\t@mixin ck-dir rtl {\n\t\t\t\tmargin-right: calc(-1 * var(--ck-spacing-small));\n\t\t\t\tmargin-left: var(--ck-spacing-small);\n\t\t\t}\n\t\t}\n\t}\n\n\t&.ck-button_with-keystroke {\n\t\t/* stylelint-disable-next-line no-descending-specificity */\n\t\t& .ck-button__label {\n\t\t\tflex-grow: 1;\n\t\t}\n\t}\n\n\t/* A style of the button which is currently on, e.g. its feature is active. */\n\t&.ck-on {\n\t\t@mixin ck-button-colors --ck-color-button-on;\n\t}\n\n\t&.ck-button-save {\n\t\tcolor: var(--ck-color-button-save);\n\t}\n\n\t&.ck-button-cancel {\n\t\tcolor: var(--ck-color-button-cancel);\n\t}\n}\n\n/* A style of the button which handles the primary action. */\n.ck.ck-button-action,\na.ck.ck-button-action {\n\t@mixin ck-button-colors --ck-color-button-action;\n\n\tcolor: var(--ck-color-button-action-text);\n}\n\n.ck.ck-button-bold,\na.ck.ck-button-bold {\n\tfont-weight: bold;\n}\n',"/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * Implements a button of given background color.\n *\n * @param {String} $background - Background color of the button.\n * @param {String} $border - Border color of the button.\n */\n@define-mixin ck-button-colors $prefix {\n\tbackground: var($(prefix)-background);\n\n\t&:not(.ck-disabled) {\n\t\t&:hover {\n\t\t\tbackground: var($(prefix)-hover-background);\n\t\t}\n\n\t\t&:active {\n\t\t\tbackground: var($(prefix)-active-background);\n\t\t\tbox-shadow: inset 0 2px 2px var($(prefix)-active-shadow);\n\t\t}\n\t}\n\n\t/* https://github.com/ckeditor/ckeditor5-theme-lark/issues/98 */\n\t&.ck-disabled {\n\t\tbackground: var($(prefix)-disabled-background);\n\t}\n}\n","/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * Implements rounded corner interface for .ck-rounded-corners class.\n *\n * @see $ck-border-radius\n */\n@define-mixin ck-rounded-corners {\n\tborder-radius: 0;\n\n\t@nest .ck-rounded-corners &,\n\t&.ck-rounded-corners {\n\t\tborder-radius: var(--ck-border-radius);\n\t\t@mixin-content;\n\t}\n}\n","/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * A visual style of focused element's border.\n */\n@define-mixin ck-focus-ring {\n\t/* Disable native outline. */\n\toutline: none;\n\tborder: var(--ck-focus-ring)\n}\n","/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * A helper to combine multiple shadows.\n */\n@define-mixin ck-box-shadow $shadowA, $shadowB: 0 0 {\n\tbox-shadow: $shadowA, $shadowB;\n}\n\n/**\n * Gives an element a drop shadow so it looks like a floating panel.\n */\n@define-mixin ck-drop-shadow {\n\t@mixin ck-box-shadow var(--ck-drop-shadow);\n}\n","/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * A class which indicates that an element holding it is disabled.\n */\n@define-mixin ck-disabled {\n\topacity: var(--ck-disabled-opacity);\n}\n"],sourceRoot:""}]);e["a"]=a},function(t,e,n){"use strict";var o=n(2);var i=n.n(o);var r=n(3);var s=n.n(r);var a=s()(i.a);a.push([t.i,".ck.ck-list{-moz-user-select:none;-webkit-user-select:none;-ms-user-select:none;user-select:none;display:flex;flex-direction:column}.ck.ck-list .ck-list__item,.ck.ck-list .ck-list__separator{display:block}.ck.ck-list .ck-list__item>:focus{position:relative;z-index:var(--ck-z-default)}.ck.ck-list{border-radius:0}.ck-rounded-corners .ck.ck-list,.ck.ck-list.ck-rounded-corners{border-radius:var(--ck-border-radius)}.ck.ck-list{list-style-type:none;background:var(--ck-color-list-background)}.ck.ck-list__item{cursor:default;min-width:12em}.ck.ck-list__item .ck-button{min-height:unset;width:100%;text-align:left;border-radius:0;padding:calc(var(--ck-line-height-base)*0.2*var(--ck-font-size-base)) calc(var(--ck-line-height-base)*0.4*var(--ck-font-size-base))}.ck.ck-list__item .ck-button .ck-button__label{line-height:calc(var(--ck-line-height-base)*1.2*var(--ck-font-size-base))}.ck.ck-list__item .ck-button:active{box-shadow:none}.ck.ck-list__item .ck-button.ck-on{background:var(--ck-color-list-button-on-background);color:var(--ck-color-list-button-on-text)}.ck.ck-list__item .ck-button.ck-on:active{box-shadow:none}.ck.ck-list__item .ck-button.ck-on:hover:not(.ck-disabled){background:var(--ck-color-list-button-on-background-focus)}.ck.ck-list__item .ck-button.ck-on:focus:not(.ck-disabled){border-color:var(--ck-color-base-background)}.ck.ck-list__item .ck-button:hover:not(.ck-disabled){background:var(--ck-color-list-button-hover-background)}.ck.ck-list__item .ck-switchbutton.ck-on{background:var(--ck-color-list-background);color:inherit}.ck.ck-list__item .ck-switchbutton.ck-on:hover:not(.ck-disabled){background:var(--ck-color-list-button-hover-background);color:inherit}.ck.ck-list__separator{height:1px;width:100%;background:var(--ck-color-base-border)}","",{version:3,sources:["webpack://./node_modules/@ckeditor/ckeditor5-ui/theme/components/list/list.css","webpack://./node_modules/@ckeditor/ckeditor5-ui/theme/mixins/_unselectable.css","webpack://./node_modules/@ckeditor/ckeditor5-theme-lark/theme/ckeditor5-ui/components/list/list.css","webpack://./node_modules/@ckeditor/ckeditor5-theme-lark/theme/mixins/_rounded.css"],names:[],mappings:"AAOA,YCEC,qBAAsB,CACtB,wBAAyB,CACzB,oBAAqB,CACrB,gBAAgB,CDFhB,YAAa,CACb,qBAcD,CAZC,2DAEC,aACD,CAKA,kCACC,iBAAkB,CAClB,2BACD,CEfD,YCEC,eDGD,CALA,+DCME,qCDDF,CALA,YAGC,oBAAqB,CACrB,0CACD,CAEA,kBACC,cAAe,CACf,cA2DD,CAzDC,6BACC,gBAAiB,CACjB,UAAW,CACX,eAAgB,CAChB,eAAgB,CAKhB,mIAiCD,CA7BC,+CAEC,yEACD,CAEA,oCACC,eACD,CAEA,mCACC,oDAAqD,CACrD,yCAaD,CAXC,0CACC,eACD,CAEA,2DACC,0DACD,CAEA,2DACC,4CACD,CAGD,qDACC,uDACD,CAMA,yCACC,0CAA2C,CAC3C,aAMD,CAJC,iEACC,uDAAwD,CACxD,aACD,CAKH,uBACC,UAAW,CACX,UAAW,CACX,sCACD",sourcesContent:['/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n@import "../../mixins/_unselectable.css";\n\n.ck.ck-list {\n\t@mixin ck-unselectable;\n\n\tdisplay: flex;\n\tflex-direction: column;\n\n\t& .ck-list__item,\n\t& .ck-list__separator {\n\t\tdisplay: block;\n\t}\n\n\t/* Make sure that whatever child of the list item gets focus, it remains on the\n\ttop. Thanks to that, styles like box-shadow, outline, etc. are not masked by\n\tadjacent list items. */\n\t& .ck-list__item > *:focus {\n\t\tposition: relative;\n\t\tz-index: var(--ck-z-default);\n\t}\n}\n',"/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * Makes element unselectable.\n */\n@define-mixin ck-unselectable {\n\t-moz-user-select: none;\n\t-webkit-user-select: none;\n\t-ms-user-select: none;\n\tuser-select: none\n}\n",'/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n@import "../../../mixins/_disabled.css";\n@import "../../../mixins/_rounded.css";\n@import "../../../mixins/_shadow.css";\n\n.ck.ck-list {\n\t@mixin ck-rounded-corners;\n\n\tlist-style-type: none;\n\tbackground: var(--ck-color-list-background);\n}\n\n.ck.ck-list__item {\n\tcursor: default;\n\tmin-width: 12em;\n\n\t& .ck-button {\n\t\tmin-height: unset;\n\t\twidth: 100%;\n\t\ttext-align: left;\n\t\tborder-radius: 0;\n\n\t\t/* List items should have the same height. Use absolute units to make sure it is so\n\t\t because e.g. different heading styles may have different height\n\t\t https://github.com/ckeditor/ckeditor5-heading/issues/63 */\n\t\tpadding:\n\t\t\tcalc(.2 * var(--ck-line-height-base) * var(--ck-font-size-base))\n\t\t\tcalc(.4 * var(--ck-line-height-base) * var(--ck-font-size-base));\n\n\t\t& .ck-button__label {\n\t\t\t/* https://github.com/ckeditor/ckeditor5-heading/issues/63 */\n\t\t\tline-height: calc(1.2 * var(--ck-line-height-base) * var(--ck-font-size-base));\n\t\t}\n\n\t\t&:active {\n\t\t\tbox-shadow: none;\n\t\t}\n\n\t\t&.ck-on {\n\t\t\tbackground: var(--ck-color-list-button-on-background);\n\t\t\tcolor: var(--ck-color-list-button-on-text);\n\n\t\t\t&:active {\n\t\t\t\tbox-shadow: none;\n\t\t\t}\n\n\t\t\t&:hover:not(.ck-disabled) {\n\t\t\t\tbackground: var(--ck-color-list-button-on-background-focus);\n\t\t\t}\n\n\t\t\t&:focus:not(.ck-disabled) {\n\t\t\t\tborder-color: var(--ck-color-base-background);\n\t\t\t}\n\t\t}\n\n\t\t&:hover:not(.ck-disabled) {\n\t\t\tbackground: var(--ck-color-list-button-hover-background);\n\t\t}\n\t}\n\n\t/* It\'s unnecessary to change the background/text of a switch toggle; it has different ways\n\tof conveying its state (like the switcher) */\n\t& .ck-switchbutton {\n\t\t&.ck-on {\n\t\t\tbackground: var(--ck-color-list-background);\n\t\t\tcolor: inherit;\n\n\t\t\t&:hover:not(.ck-disabled) {\n\t\t\t\tbackground: var(--ck-color-list-button-hover-background);\n\t\t\t\tcolor: inherit;\n\t\t\t}\n\t\t}\n\t}\n}\n\n.ck.ck-list__separator {\n\theight: 1px;\n\twidth: 100%;\n\tbackground: var(--ck-color-base-border);\n}\n',"/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * Implements rounded corner interface for .ck-rounded-corners class.\n *\n * @see $ck-border-radius\n */\n@define-mixin ck-rounded-corners {\n\tborder-radius: 0;\n\n\t@nest .ck-rounded-corners &,\n\t&.ck-rounded-corners {\n\t\tborder-radius: var(--ck-border-radius);\n\t\t@mixin-content;\n\t}\n}\n"],sourceRoot:""}]);e["a"]=a},function(t,e,n){"use strict";var o=n(2);var i=n.n(o);var r=n(3);var s=n.n(r);var a=s()(i.a);a.push([t.i,".ck.ck-button.ck-switchbutton .ck-button__toggle,.ck.ck-button.ck-switchbutton .ck-button__toggle .ck-button__toggle__inner{display:block}:root{--ck-switch-button-toggle-width:2.6153846154em;--ck-switch-button-toggle-inner-size:1.0769230769em;--ck-switch-button-toggle-spacing:1px;--ck-switch-button-translation:calc(var(--ck-switch-button-toggle-width) - var(--ck-switch-button-toggle-inner-size) - var(--ck-switch-button-toggle-spacing)*2)}[dir=ltr] .ck.ck-button.ck-switchbutton .ck-button__label{margin-right:calc(var(--ck-spacing-large)*2)}[dir=rtl] .ck.ck-button.ck-switchbutton .ck-button__label{margin-left:calc(var(--ck-spacing-large)*2)}.ck.ck-button.ck-switchbutton .ck-button__toggle{border-radius:0}.ck-rounded-corners .ck.ck-button.ck-switchbutton .ck-button__toggle,.ck.ck-button.ck-switchbutton .ck-button__toggle.ck-rounded-corners{border-radius:var(--ck-border-radius)}[dir=ltr] .ck.ck-button.ck-switchbutton .ck-button__toggle{margin-left:auto}[dir=rtl] .ck.ck-button.ck-switchbutton .ck-button__toggle{margin-right:auto}.ck.ck-button.ck-switchbutton .ck-button__toggle{transition:background .4s ease;width:var(--ck-switch-button-toggle-width);background:var(--ck-color-switch-button-off-background)}.ck.ck-button.ck-switchbutton .ck-button__toggle .ck-button__toggle__inner{border-radius:0}.ck-rounded-corners .ck.ck-button.ck-switchbutton .ck-button__toggle .ck-button__toggle__inner,.ck.ck-button.ck-switchbutton .ck-button__toggle .ck-button__toggle__inner.ck-rounded-corners{border-radius:var(--ck-border-radius);border-radius:calc(var(--ck-border-radius)*0.5)}.ck.ck-button.ck-switchbutton .ck-button__toggle .ck-button__toggle__inner{margin:var(--ck-switch-button-toggle-spacing);width:var(--ck-switch-button-toggle-inner-size);height:var(--ck-switch-button-toggle-inner-size);background:var(--ck-color-switch-button-inner-background);transition:all .3s ease}.ck.ck-button.ck-switchbutton .ck-button__toggle:hover{background:var(--ck-color-switch-button-off-hover-background)}.ck.ck-button.ck-switchbutton .ck-button__toggle:hover .ck-button__toggle__inner{box-shadow:0 0 0 5px var(--ck-color-switch-button-inner-shadow)}.ck.ck-button.ck-switchbutton.ck-disabled .ck-button__toggle{opacity:var(--ck-disabled-opacity)}.ck.ck-button.ck-switchbutton.ck-on .ck-button__toggle{background:var(--ck-color-switch-button-on-background)}.ck.ck-button.ck-switchbutton.ck-on .ck-button__toggle:hover{background:var(--ck-color-switch-button-on-hover-background)}[dir=ltr] .ck.ck-button.ck-switchbutton.ck-on .ck-button__toggle .ck-button__toggle__inner{transform:translateX(var(--ck-switch-button-translation))}[dir=rtl] .ck.ck-button.ck-switchbutton.ck-on .ck-button__toggle .ck-button__toggle__inner{transform:translateX(calc(var(--ck-switch-button-translation)*-1))}","",{version:3,sources:["webpack://./node_modules/@ckeditor/ckeditor5-ui/theme/components/button/switchbutton.css","webpack://./node_modules/@ckeditor/ckeditor5-theme-lark/theme/ckeditor5-ui/components/button/switchbutton.css","webpack://./node_modules/@ckeditor/ckeditor5-theme-lark/theme/mixins/_rounded.css","webpack://./node_modules/@ckeditor/ckeditor5-theme-lark/theme/mixins/_disabled.css"],names:[],mappings:"AASE,4HACC,aACD,CCCF,MAEC,8CAA+C,CAE/C,mDAAoD,CACpD,qCAAsC,CACtC,gKAKD,CAGC,0DAGE,4CAOF,CAVA,0DAQE,2CAEF,CAEA,iDC3BA,eDoEA,CAzCA,yICvBC,qCDgED,CAzCA,2DAKE,gBAoCF,CAzCA,2DAUE,iBA+BF,CAzCA,iDAcC,8BAAiC,CAEjC,0CAA2C,CAC3C,uDAwBD,CAtBC,2EC9CD,eD2DC,CAbA,6LC1CA,qCAAsC,CD4CpC,+CAWF,CAbA,2EAMC,6CAA8C,CAC9C,+CAAgD,CAChD,gDAAiD,CACjD,yDAA0D,CAG1D,uBACD,CAEA,uDACC,6DAKD,CAHC,iFACC,+DACD,CAIF,6DExEA,kCF0EA,CAEA,uDACC,sDAkBD,CAhBC,6DACC,4DACD,CAEA,2FAKE,yDAMF,CAXA,2FASE,kEAEF",sourcesContent:["/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n.ck.ck-button.ck-switchbutton {\n\t& .ck-button__toggle {\n\t\tdisplay: block;\n\n\t\t& .ck-button__toggle__inner {\n\t\t\tdisplay: block;\n\t\t}\n\t}\n}\n",'/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n@import "../../../mixins/_rounded.css";\n@import "../../../mixins/_disabled.css";\n@import "@ckeditor/ckeditor5-ui/theme/mixins/_dir.css";\n\n/* Note: To avoid rendering issues (aliasing) but to preserve the responsive nature\nof the component, floating–point numbers have been used which, for the default font size\n(see: --ck-font-size-base), will generate simple integers. */\n:root {\n\t/* 34px at 13px font-size */\n\t--ck-switch-button-toggle-width: 2.6153846154em;\n\t/* 14px at 13px font-size */\n\t--ck-switch-button-toggle-inner-size: 1.0769230769em;\n\t--ck-switch-button-toggle-spacing: 1px;\n\t--ck-switch-button-translation: calc(\n\t\tvar(--ck-switch-button-toggle-width) -\n\t\tvar(--ck-switch-button-toggle-inner-size) -\n\t\t2 * var(--ck-switch-button-toggle-spacing)\n\t);\n}\n\n.ck.ck-button.ck-switchbutton {\n\t& .ck-button__label {\n\t\t@mixin ck-dir ltr {\n\t\t\t/* Separate the label from the switch */\n\t\t\tmargin-right: calc(2 * var(--ck-spacing-large));\n\t\t}\n\n\t\t@mixin ck-dir rtl {\n\t\t\t/* Separate the label from the switch */\n\t\t\tmargin-left: calc(2 * var(--ck-spacing-large));\n\t\t}\n\t}\n\n\t& .ck-button__toggle {\n\t\t@mixin ck-rounded-corners;\n\n\t\t@mixin ck-dir ltr {\n\t\t\t/* Make sure the toggle is always to the right as far as possible. */\n\t\t\tmargin-left: auto;\n\t\t}\n\n\t\t@mixin ck-dir rtl {\n\t\t\t/* Make sure the toggle is always to the left as far as possible. */\n\t\t\tmargin-right: auto;\n\t\t}\n\n\t\t/* Gently animate the background color of the toggle switch */\n\t\ttransition: background 400ms ease;\n\n\t\twidth: var(--ck-switch-button-toggle-width);\n\t\tbackground: var(--ck-color-switch-button-off-background);\n\n\t\t& .ck-button__toggle__inner {\n\t\t\t@mixin ck-rounded-corners {\n\t\t\t\tborder-radius: calc(.5 * var(--ck-border-radius));\n\t\t\t}\n\n\t\t\t/* Leave some tiny bit of space around the inner part of the switch */\n\t\t\tmargin: var(--ck-switch-button-toggle-spacing);\n\t\t\twidth: var(--ck-switch-button-toggle-inner-size);\n\t\t\theight: var(--ck-switch-button-toggle-inner-size);\n\t\t\tbackground: var(--ck-color-switch-button-inner-background);\n\n\t\t\t/* Gently animate the inner part of the toggle switch */\n\t\t\ttransition: all 300ms ease;\n\t\t}\n\n\t\t&:hover {\n\t\t\tbackground: var(--ck-color-switch-button-off-hover-background);\n\n\t\t\t& .ck-button__toggle__inner {\n\t\t\t\tbox-shadow: 0 0 0 5px var(--ck-color-switch-button-inner-shadow);\n\t\t\t}\n\t\t}\n\t}\n\n\t&.ck-disabled .ck-button__toggle {\n\t\t@mixin ck-disabled;\n\t}\n\n\t&.ck-on .ck-button__toggle {\n\t\tbackground: var(--ck-color-switch-button-on-background);\n\n\t\t&:hover {\n\t\t\tbackground: var(--ck-color-switch-button-on-hover-background);\n\t\t}\n\n\t\t& .ck-button__toggle__inner {\n\t\t\t/*\n\t\t\t * Move the toggle switch to the right. It will be animated.\n\t\t\t */\n\t\t\t@mixin ck-dir ltr {\n\t\t\t\ttransform: translateX( var( --ck-switch-button-translation ) );\n\t\t\t}\n\n\t\t\t@mixin ck-dir rtl {\n\t\t\t\ttransform: translateX( calc( -1 * var( --ck-switch-button-translation ) ) );\n\t\t\t}\n\t\t}\n\t}\n}\n',"/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * Implements rounded corner interface for .ck-rounded-corners class.\n *\n * @see $ck-border-radius\n */\n@define-mixin ck-rounded-corners {\n\tborder-radius: 0;\n\n\t@nest .ck-rounded-corners &,\n\t&.ck-rounded-corners {\n\t\tborder-radius: var(--ck-border-radius);\n\t\t@mixin-content;\n\t}\n}\n","/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * A class which indicates that an element holding it is disabled.\n */\n@define-mixin ck-disabled {\n\topacity: var(--ck-disabled-opacity);\n}\n"],sourceRoot:""}]);e["a"]=a},function(t,e,n){"use strict";var o=n(2);var i=n.n(o);var r=n(3);var s=n.n(r);var a=s()(i.a);a.push([t.i,":root{--ck-toolbar-dropdown-max-width:60vw}.ck.ck-toolbar-dropdown .ck-dropdown__panel{width:max-content;max-width:var(--ck-toolbar-dropdown-max-width)}.ck.ck-toolbar-dropdown .ck-dropdown__panel .ck-button:focus{z-index:calc(var(--ck-z-default) + 1)}.ck.ck-toolbar-dropdown .ck-toolbar{border:0}","",{version:3,sources:["webpack://./node_modules/@ckeditor/ckeditor5-ui/theme/components/dropdown/toolbardropdown.css","webpack://./node_modules/@ckeditor/ckeditor5-theme-lark/theme/ckeditor5-ui/components/dropdown/toolbardropdown.css"],names:[],mappings:"AAKA,MACC,oCACD,CAGC,4CAEC,iBAAkB,CAClB,8CAOD,CAJE,6DACC,qCACD,CCbH,oCACC,QACD",sourcesContent:["/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n:root {\n\t--ck-toolbar-dropdown-max-width: 60vw;\n}\n\n.ck.ck-toolbar-dropdown {\n\t& .ck-dropdown__panel {\n\t\t/* https://github.com/ckeditor/ckeditor5/issues/5586 */\n\t\twidth: max-content;\n\t\tmax-width: var(--ck-toolbar-dropdown-max-width);\n\n\t\t& .ck-button {\n\t\t\t&:focus {\n\t\t\t\tz-index: calc(var(--ck-z-default) + 1);\n\t\t\t}\n\t\t}\n\t}\n}\n","/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n.ck.ck-toolbar-dropdown .ck-toolbar {\n\tborder: 0;\n}\n"],sourceRoot:""}]);e["a"]=a},function(t,e,n){"use strict";var o=n(2);var i=n.n(o);var r=n(3);var s=n.n(r);var a=s()(i.a);a.push([t.i,".ck.ck-dropdown .ck-dropdown__panel .ck-list{border-radius:0}.ck-rounded-corners .ck.ck-dropdown .ck-dropdown__panel .ck-list,.ck.ck-dropdown .ck-dropdown__panel .ck-list.ck-rounded-corners{border-radius:var(--ck-border-radius);border-top-left-radius:0}.ck.ck-dropdown .ck-dropdown__panel .ck-list .ck-list__item:first-child .ck-button{border-radius:0}.ck-rounded-corners .ck.ck-dropdown .ck-dropdown__panel .ck-list .ck-list__item:first-child .ck-button,.ck.ck-dropdown .ck-dropdown__panel .ck-list .ck-list__item:first-child .ck-button.ck-rounded-corners{border-radius:var(--ck-border-radius);border-top-left-radius:0;border-bottom-left-radius:0;border-bottom-right-radius:0}.ck.ck-dropdown .ck-dropdown__panel .ck-list .ck-list__item:last-child .ck-button{border-radius:0}.ck-rounded-corners .ck.ck-dropdown .ck-dropdown__panel .ck-list .ck-list__item:last-child .ck-button,.ck.ck-dropdown .ck-dropdown__panel .ck-list .ck-list__item:last-child .ck-button.ck-rounded-corners{border-radius:var(--ck-border-radius);border-top-left-radius:0;border-top-right-radius:0}","",{version:3,sources:["webpack://./node_modules/@ckeditor/ckeditor5-theme-lark/theme/ckeditor5-ui/components/dropdown/listdropdown.css","webpack://./node_modules/@ckeditor/ckeditor5-theme-lark/theme/mixins/_rounded.css"],names:[],mappings:"AAOA,6CCIC,eDqBD,CAzBA,iICQE,qCAAsC,CDJtC,wBAqBF,CAfE,mFCND,eDYC,CANA,6MCFA,qCAAsC,CDIpC,wBAAyB,CACzB,2BAA4B,CAC5B,4BAEF,CAEA,kFCdD,eDmBC,CALA,2MCVA,qCAAsC,CDYpC,wBAAyB,CACzB,yBAEF",sourcesContent:['/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n@import "../../../mixins/_rounded.css";\n\n.ck.ck-dropdown .ck-dropdown__panel .ck-list {\n\t/* Disabled radius of top-left border to be consistent with .dropdown__button\n\thttps://github.com/ckeditor/ckeditor5/issues/816 */\n\t@mixin ck-rounded-corners {\n\t\tborder-top-left-radius: 0;\n\t}\n\n\t/* Make sure the button belonging to the first/last child of the list goes well with the\n\tborder radius of the entire panel. */\n\t& .ck-list__item {\n\t\t&:first-child .ck-button {\n\t\t\t@mixin ck-rounded-corners {\n\t\t\t\tborder-top-left-radius: 0;\n\t\t\t\tborder-bottom-left-radius: 0;\n\t\t\t\tborder-bottom-right-radius: 0;\n\t\t\t}\n\t\t}\n\n\t\t&:last-child .ck-button {\n\t\t\t@mixin ck-rounded-corners {\n\t\t\t\tborder-top-left-radius: 0;\n\t\t\t\tborder-top-right-radius: 0;\n\t\t\t}\n\t\t}\n\t}\n}\n',"/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * Implements rounded corner interface for .ck-rounded-corners class.\n *\n * @see $ck-border-radius\n */\n@define-mixin ck-rounded-corners {\n\tborder-radius: 0;\n\n\t@nest .ck-rounded-corners &,\n\t&.ck-rounded-corners {\n\t\tborder-radius: var(--ck-border-radius);\n\t\t@mixin-content;\n\t}\n}\n"],sourceRoot:""}]);e["a"]=a},function(t,e,n){"use strict";var o=n(2);var i=n.n(o);var r=n(3);var s=n.n(r);var a=s()(i.a);a.push([t.i,".ck.ck-toolbar{-moz-user-select:none;-webkit-user-select:none;-ms-user-select:none;user-select:none;display:flex;flex-flow:row nowrap;align-items:center}.ck.ck-toolbar>.ck-toolbar__items{display:flex;flex-flow:row wrap;align-items:center;flex-grow:1}.ck.ck-toolbar .ck.ck-toolbar__separator{display:inline-block}.ck.ck-toolbar .ck.ck-toolbar__separator:first-child,.ck.ck-toolbar .ck.ck-toolbar__separator:last-child{display:none}.ck.ck-toolbar .ck-toolbar__line-break{flex-basis:100%}.ck.ck-toolbar.ck-toolbar_grouping>.ck-toolbar__items{flex-wrap:nowrap}.ck.ck-toolbar.ck-toolbar_vertical>.ck-toolbar__items{flex-direction:column}.ck.ck-toolbar.ck-toolbar_floating>.ck-toolbar__items{flex-wrap:nowrap}.ck.ck-toolbar>.ck.ck-toolbar__grouped-dropdown>.ck-dropdown__button .ck-dropdown__arrow{display:none}.ck.ck-toolbar{border-radius:0}.ck-rounded-corners .ck.ck-toolbar,.ck.ck-toolbar.ck-rounded-corners{border-radius:var(--ck-border-radius)}.ck.ck-toolbar{background:var(--ck-color-toolbar-background);padding:0 var(--ck-spacing-small);border:1px solid var(--ck-color-toolbar-border)}.ck.ck-toolbar .ck.ck-toolbar__separator{align-self:stretch;width:1px;min-width:1px;background:var(--ck-color-toolbar-border);margin-top:var(--ck-spacing-small);margin-bottom:var(--ck-spacing-small)}.ck.ck-toolbar .ck-toolbar__line-break{height:0}.ck.ck-toolbar>.ck-toolbar__items>:not(.ck-toolbar__line-break){margin-right:var(--ck-spacing-small)}.ck.ck-toolbar>.ck-toolbar__items:empty+.ck.ck-toolbar__separator{display:none}.ck.ck-toolbar>.ck-toolbar__items>:not(.ck-toolbar__line-break),.ck.ck-toolbar>.ck.ck-toolbar__grouped-dropdown{margin-top:var(--ck-spacing-small);margin-bottom:var(--ck-spacing-small)}.ck.ck-toolbar.ck-toolbar_vertical{padding:0}.ck.ck-toolbar.ck-toolbar_vertical>.ck-toolbar__items>.ck{width:100%;margin:0;border-radius:0;border:0}.ck.ck-toolbar.ck-toolbar_compact{padding:0}.ck.ck-toolbar.ck-toolbar_compact>.ck-toolbar__items>*{margin:0}.ck.ck-toolbar.ck-toolbar_compact>.ck-toolbar__items>:not(:first-child):not(:last-child){border-radius:0}.ck.ck-toolbar>.ck.ck-toolbar__grouped-dropdown>.ck.ck-button.ck-dropdown__button{padding-left:var(--ck-spacing-tiny)}.ck-toolbar-container .ck.ck-toolbar{border:0}.ck.ck-toolbar[dir=rtl]>.ck-toolbar__items>.ck,[dir=rtl] .ck.ck-toolbar>.ck-toolbar__items>.ck{margin-right:0}.ck.ck-toolbar[dir=rtl]:not(.ck-toolbar_compact)>.ck-toolbar__items>.ck,[dir=rtl] .ck.ck-toolbar:not(.ck-toolbar_compact)>.ck-toolbar__items>.ck{margin-left:var(--ck-spacing-small)}.ck.ck-toolbar[dir=rtl]>.ck-toolbar__items>.ck:last-child,[dir=rtl] .ck.ck-toolbar>.ck-toolbar__items>.ck:last-child{margin-left:0}.ck.ck-toolbar[dir=rtl].ck-toolbar_compact>.ck-toolbar__items>.ck:first-child,[dir=rtl] .ck.ck-toolbar.ck-toolbar_compact>.ck-toolbar__items>.ck:first-child{border-top-left-radius:0;border-bottom-left-radius:0}.ck.ck-toolbar[dir=rtl].ck-toolbar_compact>.ck-toolbar__items>.ck:last-child,[dir=rtl] .ck.ck-toolbar.ck-toolbar_compact>.ck-toolbar__items>.ck:last-child{border-top-right-radius:0;border-bottom-right-radius:0}.ck.ck-toolbar[dir=rtl]>.ck.ck-toolbar__separator,[dir=rtl] .ck.ck-toolbar>.ck.ck-toolbar__separator{margin-left:var(--ck-spacing-small)}.ck.ck-toolbar[dir=rtl].ck-toolbar_grouping>.ck-toolbar__items:not(:empty):not(:only-child),[dir=rtl] .ck.ck-toolbar.ck-toolbar_grouping>.ck-toolbar__items:not(:empty):not(:only-child){margin-left:var(--ck-spacing-small)}.ck.ck-toolbar[dir=ltr]>.ck-toolbar__items>.ck:last-child,[dir=ltr] .ck.ck-toolbar>.ck-toolbar__items>.ck:last-child{margin-right:0}.ck.ck-toolbar[dir=ltr].ck-toolbar_compact>.ck-toolbar__items>.ck:first-child,[dir=ltr] .ck.ck-toolbar.ck-toolbar_compact>.ck-toolbar__items>.ck:first-child{border-top-right-radius:0;border-bottom-right-radius:0}.ck.ck-toolbar[dir=ltr].ck-toolbar_compact>.ck-toolbar__items>.ck:last-child,[dir=ltr] .ck.ck-toolbar.ck-toolbar_compact>.ck-toolbar__items>.ck:last-child{border-top-left-radius:0;border-bottom-left-radius:0}.ck.ck-toolbar[dir=ltr]>.ck.ck-toolbar__separator,[dir=ltr] .ck.ck-toolbar>.ck.ck-toolbar__separator{margin-right:var(--ck-spacing-small)}.ck.ck-toolbar[dir=ltr].ck-toolbar_grouping>.ck-toolbar__items:not(:empty):not(:only-child),[dir=ltr] .ck.ck-toolbar.ck-toolbar_grouping>.ck-toolbar__items:not(:empty):not(:only-child){margin-right:var(--ck-spacing-small)}","",{version:3,sources:["webpack://./node_modules/@ckeditor/ckeditor5-ui/theme/components/toolbar/toolbar.css","webpack://./node_modules/@ckeditor/ckeditor5-ui/theme/mixins/_unselectable.css","webpack://./node_modules/@ckeditor/ckeditor5-theme-lark/theme/ckeditor5-ui/components/toolbar/toolbar.css","webpack://./node_modules/@ckeditor/ckeditor5-theme-lark/theme/mixins/_rounded.css"],names:[],mappings:"AAOA,eCEC,qBAAsB,CACtB,wBAAyB,CACzB,oBAAqB,CACrB,gBAAgB,CDFhB,YAAa,CACb,oBAAqB,CACrB,kBA6CD,CA3CC,kCACC,YAAa,CACb,kBAAmB,CACnB,kBAAmB,CACnB,WAED,CAEA,yCACC,oBAWD,CAJC,yGAEC,YACD,CAGD,uCACC,eACD,CAEA,sDACC,gBACD,CAEA,sDACC,qBACD,CAEA,sDACC,gBACD,CAGC,yFACC,YACD,CE/CF,eCGC,eD0FD,CA7FA,qECOE,qCDsFF,CA7FA,eAGC,6CAA8C,CAC9C,iCAAkC,CAClC,+CAwFD,CAtFC,yCACC,kBAAmB,CACnB,SAAU,CACV,aAAc,CACd,yCAA0C,CAM1C,kCAAmC,CACnC,qCACD,CAEA,uCACC,QACD,CAGC,gEAEC,oCACD,CAIA,kEACC,YACD,CAGD,gHAGC,kCAAmC,CACnC,qCACD,CAEA,mCAEC,SAgBD,CAbC,0DAEC,UAAW,CAGX,QAAS,CAGT,eAAgB,CAGhB,QACD,CAGD,kCAEC,SAWD,CATC,uDAEC,QAMD,CAHC,yFACC,eACD,CASD,kFACC,mCACD,CAvFF,qCA2FE,QAEF,CAYC,+FACC,cACD,CAEA,iJAEC,mCACD,CAEA,qHACC,aACD,CAIC,6JACC,wBAAyB,CACzB,2BACD,CAGA,2JACC,yBAA0B,CAC1B,4BACD,CAID,qGACC,mCACD,CAGA,yLACC,mCACD,CAWA,qHACC,cACD,CAIC,6JACC,yBAA0B,CAC1B,4BACD,CAGA,2JACC,wBAAyB,CACzB,2BACD,CAID,qGACC,oCACD,CAGA,yLACC,oCACD",sourcesContent:['/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n@import "../../mixins/_unselectable.css";\n\n.ck.ck-toolbar {\n\t@mixin ck-unselectable;\n\n\tdisplay: flex;\n\tflex-flow: row nowrap;\n\talign-items: center;\n\n\t& > .ck-toolbar__items {\n\t\tdisplay: flex;\n\t\tflex-flow: row wrap;\n\t\talign-items: center;\n\t\tflex-grow: 1;\n\n\t}\n\n\t& .ck.ck-toolbar__separator {\n\t\tdisplay: inline-block;\n\n\t\t/*\n\t\t * A leading or trailing separator makes no sense (separates from nothing on one side).\n\t\t * For instance, it can happen when toolbar items (also separators) are getting grouped one by one and\n\t\t * moved to another toolbar in the dropdown.\n\t\t */\n\t\t&:first-child,\n\t\t&:last-child {\n\t\t\tdisplay: none;\n\t\t}\n\t}\n\n\t& .ck-toolbar__line-break {\n\t\tflex-basis: 100%;\n\t}\n\n\t&.ck-toolbar_grouping > .ck-toolbar__items {\n\t\tflex-wrap: nowrap;\n\t}\n\n\t&.ck-toolbar_vertical > .ck-toolbar__items {\n\t\tflex-direction: column;\n\t}\n\n\t&.ck-toolbar_floating > .ck-toolbar__items {\n\t\tflex-wrap: nowrap;\n\t}\n\n\t& > .ck.ck-toolbar__grouped-dropdown {\n\t\t& > .ck-dropdown__button .ck-dropdown__arrow {\n\t\t\tdisplay: none;\n\t\t}\n\t}\n}\n',"/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * Makes element unselectable.\n */\n@define-mixin ck-unselectable {\n\t-moz-user-select: none;\n\t-webkit-user-select: none;\n\t-ms-user-select: none;\n\tuser-select: none\n}\n",'/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n@import "../../../mixins/_rounded.css";\n@import "@ckeditor/ckeditor5-ui/theme/mixins/_dir.css";\n\n.ck.ck-toolbar {\n\t@mixin ck-rounded-corners;\n\n\tbackground: var(--ck-color-toolbar-background);\n\tpadding: 0 var(--ck-spacing-small);\n\tborder: 1px solid var(--ck-color-toolbar-border);\n\n\t& .ck.ck-toolbar__separator {\n\t\talign-self: stretch;\n\t\twidth: 1px;\n\t\tmin-width: 1px;\n\t\tbackground: var(--ck-color-toolbar-border);\n\n\t\t/*\n\t\t * These margins make the separators look better in balloon toolbars (when aligned with the "tip").\n\t\t * See https://github.com/ckeditor/ckeditor5/issues/7493.\n\t\t */\n\t\tmargin-top: var(--ck-spacing-small);\n\t\tmargin-bottom: var(--ck-spacing-small);\n\t}\n\n\t& .ck-toolbar__line-break {\n\t\theight: 0;\n\t}\n\n\t& > .ck-toolbar__items {\n\t\t& > *:not(.ck-toolbar__line-break) {\n\t\t\t/* (#11) Separate toolbar items. */\n\t\t\tmargin-right: var(--ck-spacing-small);\n\t\t}\n\n\t\t/* Don\'t display a separator after an empty items container, for instance,\n\t\twhen all items were grouped */\n\t\t&:empty + .ck.ck-toolbar__separator {\n\t\t\tdisplay: none;\n\t\t}\n\t}\n\n\t& > .ck-toolbar__items > *:not(.ck-toolbar__line-break),\n\t& > .ck.ck-toolbar__grouped-dropdown {\n\t\t/* Make sure items wrapped to the next line have v-spacing */\n\t\tmargin-top: var(--ck-spacing-small);\n\t\tmargin-bottom: var(--ck-spacing-small);\n\t}\n\n\t&.ck-toolbar_vertical {\n\t\t/* Items in a vertical toolbar span the entire width. */\n\t\tpadding: 0;\n\n\t\t/* Specificity matters here. See https://github.com/ckeditor/ckeditor5-theme-lark/issues/168. */\n\t\t& > .ck-toolbar__items > .ck {\n\t\t\t/* Items in a vertical toolbar should span the horizontal space. */\n\t\t\twidth: 100%;\n\n\t\t\t/* Items in a vertical toolbar should have no margin. */\n\t\t\tmargin: 0;\n\n\t\t\t/* Items in a vertical toolbar span the entire width so rounded corners are pointless. */\n\t\t\tborder-radius: 0;\n\n\t\t\t/* Items in a vertical toolbar span the entire width so any border is pointless. */\n\t\t\tborder: 0;\n\t\t}\n\t}\n\n\t&.ck-toolbar_compact {\n\t\t/* No spacing around items. */\n\t\tpadding: 0;\n\n\t\t& > .ck-toolbar__items > * {\n\t\t\t/* Compact toolbar items have no spacing between them. */\n\t\t\tmargin: 0;\n\n\t\t\t/* "Middle" children should have no rounded corners. */\n\t\t\t&:not(:first-child):not(:last-child) {\n\t\t\t\tborder-radius: 0;\n\t\t\t}\n\t\t}\n\t}\n\n\t& > .ck.ck-toolbar__grouped-dropdown {\n\t\t/*\n\t\t * Dropdown button has asymmetric padding to fit the arrow.\n\t\t * This button has no arrow so let\'s revert that padding back to normal.\n\t\t */\n\t\t& > .ck.ck-button.ck-dropdown__button {\n\t\t\tpadding-left: var(--ck-spacing-tiny);\n\t\t}\n\t}\n\n\t@nest .ck-toolbar-container & {\n\t\tborder: 0;\n\t}\n}\n\n/* stylelint-disable */\n\n/*\n * Styles for RTL toolbars.\n *\n * Note: In some cases (e.g. a decoupled editor), the toolbar has its own "dir"\n * because its parent is not controlled by the editor framework.\n */\n[dir="rtl"] .ck.ck-toolbar,\n.ck.ck-toolbar[dir="rtl"] {\n\t& > .ck-toolbar__items > .ck {\n\t\tmargin-right: 0;\n\t}\n\n\t&:not(.ck-toolbar_compact) > .ck-toolbar__items > .ck {\n\t\t/* (#11) Separate toolbar items. */\n\t\tmargin-left: var(--ck-spacing-small);\n\t}\n\n\t& > .ck-toolbar__items > .ck:last-child {\n\t\tmargin-left: 0;\n\t}\n\n\t&.ck-toolbar_compact > .ck-toolbar__items > .ck {\n\t\t/* No rounded corners on the right side of the first child. */\n\t\t&:first-child {\n\t\t\tborder-top-left-radius: 0;\n\t\t\tborder-bottom-left-radius: 0;\n\t\t}\n\n\t\t/* No rounded corners on the left side of the last child. */\n\t\t&:last-child {\n\t\t\tborder-top-right-radius: 0;\n\t\t\tborder-bottom-right-radius: 0;\n\t\t}\n\t}\n\n\t/* Separate the the separator form the grouping dropdown when some items are grouped. */\n\t& > .ck.ck-toolbar__separator {\n\t\tmargin-left: var(--ck-spacing-small);\n\t}\n\n\t/* Some spacing between the items and the separator before the grouped items dropdown. */\n\t&.ck-toolbar_grouping > .ck-toolbar__items:not(:empty):not(:only-child) {\n\t\tmargin-left: var(--ck-spacing-small);\n\t}\n}\n\n/*\n * Styles for LTR toolbars.\n *\n * Note: In some cases (e.g. a decoupled editor), the toolbar has its own "dir"\n * because its parent is not controlled by the editor framework.\n */\n[dir="ltr"] .ck.ck-toolbar,\n.ck.ck-toolbar[dir="ltr"] {\n\t& > .ck-toolbar__items > .ck:last-child {\n\t\tmargin-right: 0;\n\t}\n\n\t&.ck-toolbar_compact > .ck-toolbar__items > .ck {\n\t\t/* No rounded corners on the right side of the first child. */\n\t\t&:first-child {\n\t\t\tborder-top-right-radius: 0;\n\t\t\tborder-bottom-right-radius: 0;\n\t\t}\n\n\t\t/* No rounded corners on the left side of the last child. */\n\t\t&:last-child {\n\t\t\tborder-top-left-radius: 0;\n\t\t\tborder-bottom-left-radius: 0;\n\t\t}\n\t}\n\n\t/* Separate the the separator form the grouping dropdown when some items are grouped. */\n\t& > .ck.ck-toolbar__separator {\n\t\tmargin-right: var(--ck-spacing-small);\n\t}\n\n\t/* Some spacing between the items and the separator before the grouped items dropdown. */\n\t&.ck-toolbar_grouping > .ck-toolbar__items:not(:empty):not(:only-child) {\n\t\tmargin-right: var(--ck-spacing-small);\n\t}\n}\n\n/* stylelint-enable */\n',"/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * Implements rounded corner interface for .ck-rounded-corners class.\n *\n * @see $ck-border-radius\n */\n@define-mixin ck-rounded-corners {\n\tborder-radius: 0;\n\n\t@nest .ck-rounded-corners &,\n\t&.ck-rounded-corners {\n\t\tborder-radius: var(--ck-border-radius);\n\t\t@mixin-content;\n\t}\n}\n"],sourceRoot:""}]);e["a"]=a},function(t,e,n){"use strict";var o=n(2);var i=n.n(o);var r=n(3);var s=n.n(r);var a=s()(i.a);a.push([t.i,".ck.ck-editor{position:relative}.ck.ck-editor .ck-editor__top .ck-sticky-panel .ck-toolbar{z-index:var(--ck-z-modal)}.ck.ck-editor__top .ck-sticky-panel .ck-toolbar{border-radius:0}.ck-rounded-corners .ck.ck-editor__top .ck-sticky-panel .ck-toolbar,.ck.ck-editor__top .ck-sticky-panel .ck-toolbar.ck-rounded-corners{border-radius:var(--ck-border-radius);border-bottom-left-radius:0;border-bottom-right-radius:0}.ck.ck-editor__top .ck-sticky-panel .ck-toolbar{border-bottom-width:0}.ck.ck-editor__top .ck-sticky-panel .ck-sticky-panel__content_sticky .ck-toolbar{border-bottom-width:1px;border-radius:0}.ck-rounded-corners .ck.ck-editor__top .ck-sticky-panel .ck-sticky-panel__content_sticky .ck-toolbar,.ck.ck-editor__top .ck-sticky-panel .ck-sticky-panel__content_sticky .ck-toolbar.ck-rounded-corners{border-radius:var(--ck-border-radius);border-radius:0}.ck.ck-editor__main>.ck-editor__editable{background:var(--ck-color-base-background);border-radius:0}.ck-rounded-corners .ck.ck-editor__main>.ck-editor__editable,.ck.ck-editor__main>.ck-editor__editable.ck-rounded-corners{border-radius:var(--ck-border-radius);border-top-left-radius:0;border-top-right-radius:0}.ck.ck-editor__main>.ck-editor__editable:not(.ck-focused){border-color:var(--ck-color-base-border)}","",{version:3,sources:["webpack://./node_modules/@ckeditor/ckeditor5-editor-classic/theme/classiceditor.css","webpack://./node_modules/@ckeditor/ckeditor5-theme-lark/theme/ckeditor5-editor-classic/classiceditor.css","webpack://./node_modules/@ckeditor/ckeditor5-theme-lark/theme/mixins/_rounded.css"],names:[],mappings:"AAKA,cAIC,iBAMD,CAJC,2DAEC,yBACD,CCLC,gDCED,eDKC,CAPA,uICMA,qCAAsC,CDJpC,2BAA4B,CAC5B,4BAIF,CAPA,gDAMC,qBACD,CAEA,iFACC,uBAAwB,CCR1B,eDaC,CANA,yMCHA,qCAAsC,CDOpC,eAEF,CAKF,yCAEC,0CAA2C,CCpB3C,eD8BD,CAZA,yHCdE,qCAAsC,CDmBtC,wBAAyB,CACzB,yBAMF,CAHC,0DACC,wCACD",sourcesContent:["/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n.ck.ck-editor {\n\t/* All the elements within `.ck-editor` are positioned relatively to it.\n\t If any element needs to be positioned with respect to the , etc.,\n\t it must land outside of the `.ck-editor` in DOM. */\n\tposition: relative;\n\n\t& .ck-editor__top .ck-sticky-panel .ck-toolbar {\n\t\t/* https://github.com/ckeditor/ckeditor5-editor-classic/issues/62 */\n\t\tz-index: var(--ck-z-modal);\n\t}\n}\n",'/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n@import "../mixins/_rounded.css";\n\n.ck.ck-editor__top {\n\t& .ck-sticky-panel {\n\t\t& .ck-toolbar {\n\t\t\t@mixin ck-rounded-corners {\n\t\t\t\tborder-bottom-left-radius: 0;\n\t\t\t\tborder-bottom-right-radius: 0;\n\t\t\t}\n\n\t\t\tborder-bottom-width: 0;\n\t\t}\n\n\t\t& .ck-sticky-panel__content_sticky .ck-toolbar {\n\t\t\tborder-bottom-width: 1px;\n\n\t\t\t@mixin ck-rounded-corners {\n\t\t\t\tborder-radius: 0;\n\t\t\t}\n\t\t}\n\t}\n}\n\n/* Note: Use ck-editor__main to make sure these styles don\'t apply to other editor types */\n.ck.ck-editor__main > .ck-editor__editable {\n\t/* https://github.com/ckeditor/ckeditor5-theme-lark/issues/113 */\n\tbackground: var(--ck-color-base-background);\n\n\t@mixin ck-rounded-corners {\n\t\tborder-top-left-radius: 0;\n\t\tborder-top-right-radius: 0;\n\t}\n\n\t&:not(.ck-focused) {\n\t\tborder-color: var(--ck-color-base-border);\n\t}\n}\n',"/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * Implements rounded corner interface for .ck-rounded-corners class.\n *\n * @see $ck-border-radius\n */\n@define-mixin ck-rounded-corners {\n\tborder-radius: 0;\n\n\t@nest .ck-rounded-corners &,\n\t&.ck-rounded-corners {\n\t\tborder-radius: var(--ck-border-radius);\n\t\t@mixin-content;\n\t}\n}\n"],sourceRoot:""}]);e["a"]=a},function(t,e,n){"use strict";var o=n(2);var i=n.n(o);var r=n(3);var s=n.n(r);var a=s()(i.a);a.push([t.i,".ck-content blockquote{overflow:hidden;padding-right:1.5em;padding-left:1.5em;margin-left:0;margin-right:0;font-style:italic;border-left:5px solid #ccc}.ck-content[dir=rtl] blockquote{border-left:0;border-right:5px solid #ccc}","",{version:3,sources:["webpack://./node_modules/@ckeditor/ckeditor5-block-quote/theme/blockquote.css"],names:[],mappings:"AAKA,uBAEC,eAAgB,CAGhB,mBAAoB,CACpB,kBAAmB,CAEnB,aAAc,CACd,cAAe,CACf,iBAAkB,CAClB,0BACD,CAEA,gCACC,aAAc,CACd,2BACD",sourcesContent:['/**\n * @license Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n.ck-content blockquote {\n\t/* See #12 */\n\toverflow: hidden;\n\n\t/* https://github.com/ckeditor/ckeditor5-block-quote/issues/15 */\n\tpadding-right: 1.5em;\n\tpadding-left: 1.5em;\n\n\tmargin-left: 0;\n\tmargin-right: 0;\n\tfont-style: italic;\n\tborder-left: solid 5px hsl(0, 0%, 80%);\n}\n\n.ck-content[dir="rtl"] blockquote {\n\tborder-left: 0;\n\tborder-right: solid 5px hsl(0, 0%, 80%);\n}\n'],sourceRoot:""}]);e["a"]=a},function(t,e,n){"use strict";var o=n(2);var i=n.n(o);var r=n(3);var s=n.n(r);var a=s()(i.a);a.push([t.i,':root{--ck-balloon-panel-arrow-z-index:calc(var(--ck-z-default) - 3)}.ck.ck-balloon-panel{display:none;position:absolute;z-index:var(--ck-z-modal)}.ck.ck-balloon-panel.ck-balloon-panel_with-arrow:after,.ck.ck-balloon-panel.ck-balloon-panel_with-arrow:before{content:"";position:absolute}.ck.ck-balloon-panel.ck-balloon-panel_with-arrow:before{z-index:var(--ck-balloon-panel-arrow-z-index)}.ck.ck-balloon-panel.ck-balloon-panel_with-arrow:after{z-index:calc(var(--ck-balloon-panel-arrow-z-index) + 1)}.ck.ck-balloon-panel[class*=arrow_n]:before{z-index:var(--ck-balloon-panel-arrow-z-index)}.ck.ck-balloon-panel[class*=arrow_n]:after{z-index:calc(var(--ck-balloon-panel-arrow-z-index) + 1)}.ck.ck-balloon-panel[class*=arrow_s]:before{z-index:var(--ck-balloon-panel-arrow-z-index)}.ck.ck-balloon-panel[class*=arrow_s]:after{z-index:calc(var(--ck-balloon-panel-arrow-z-index) + 1)}.ck.ck-balloon-panel.ck-balloon-panel_visible{display:block}:root{--ck-balloon-arrow-offset:2px;--ck-balloon-arrow-height:10px;--ck-balloon-arrow-half-width:8px;--ck-balloon-arrow-drop-shadow:0 2px 2px var(--ck-color-shadow-drop)}.ck.ck-balloon-panel{border-radius:0}.ck-rounded-corners .ck.ck-balloon-panel,.ck.ck-balloon-panel.ck-rounded-corners{border-radius:var(--ck-border-radius)}.ck.ck-balloon-panel{box-shadow:var(--ck-drop-shadow),0 0;min-height:15px;background:var(--ck-color-panel-background);border:1px solid var(--ck-color-panel-border)}.ck.ck-balloon-panel.ck-balloon-panel_with-arrow:after,.ck.ck-balloon-panel.ck-balloon-panel_with-arrow:before{width:0;height:0;border-style:solid}.ck.ck-balloon-panel[class*=arrow_n]:after,.ck.ck-balloon-panel[class*=arrow_n]:before{border-left-width:var(--ck-balloon-arrow-half-width);border-bottom-width:var(--ck-balloon-arrow-height);border-right-width:var(--ck-balloon-arrow-half-width);border-top-width:0}.ck.ck-balloon-panel[class*=arrow_n]:before{border-bottom-color:var(--ck-color-panel-border)}.ck.ck-balloon-panel[class*=arrow_n]:after,.ck.ck-balloon-panel[class*=arrow_n]:before{border-left-color:transparent;border-right-color:transparent;border-top-color:transparent}.ck.ck-balloon-panel[class*=arrow_n]:after{border-bottom-color:var(--ck-color-panel-background);margin-top:var(--ck-balloon-arrow-offset)}.ck.ck-balloon-panel[class*=arrow_s]:after,.ck.ck-balloon-panel[class*=arrow_s]:before{border-left-width:var(--ck-balloon-arrow-half-width);border-bottom-width:0;border-right-width:var(--ck-balloon-arrow-half-width);border-top-width:var(--ck-balloon-arrow-height)}.ck.ck-balloon-panel[class*=arrow_s]:before{border-top-color:var(--ck-color-panel-border);filter:drop-shadow(var(--ck-balloon-arrow-drop-shadow))}.ck.ck-balloon-panel[class*=arrow_s]:after,.ck.ck-balloon-panel[class*=arrow_s]:before{border-left-color:transparent;border-bottom-color:transparent;border-right-color:transparent}.ck.ck-balloon-panel[class*=arrow_s]:after{border-top-color:var(--ck-color-panel-background);margin-bottom:var(--ck-balloon-arrow-offset)}.ck.ck-balloon-panel.ck-balloon-panel_arrow_n:after,.ck.ck-balloon-panel.ck-balloon-panel_arrow_n:before{left:50%;margin-left:calc(var(--ck-balloon-arrow-half-width)*-1);top:calc(var(--ck-balloon-arrow-height)*-1)}.ck.ck-balloon-panel.ck-balloon-panel_arrow_nw:after,.ck.ck-balloon-panel.ck-balloon-panel_arrow_nw:before{left:calc(var(--ck-balloon-arrow-half-width)*2);top:calc(var(--ck-balloon-arrow-height)*-1)}.ck.ck-balloon-panel.ck-balloon-panel_arrow_ne:after,.ck.ck-balloon-panel.ck-balloon-panel_arrow_ne:before{right:calc(var(--ck-balloon-arrow-half-width)*2);top:calc(var(--ck-balloon-arrow-height)*-1)}.ck.ck-balloon-panel.ck-balloon-panel_arrow_s:after,.ck.ck-balloon-panel.ck-balloon-panel_arrow_s:before{left:50%;margin-left:calc(var(--ck-balloon-arrow-half-width)*-1);bottom:calc(var(--ck-balloon-arrow-height)*-1)}.ck.ck-balloon-panel.ck-balloon-panel_arrow_sw:after,.ck.ck-balloon-panel.ck-balloon-panel_arrow_sw:before{left:calc(var(--ck-balloon-arrow-half-width)*2);bottom:calc(var(--ck-balloon-arrow-height)*-1)}.ck.ck-balloon-panel.ck-balloon-panel_arrow_se:after,.ck.ck-balloon-panel.ck-balloon-panel_arrow_se:before{right:calc(var(--ck-balloon-arrow-half-width)*2);bottom:calc(var(--ck-balloon-arrow-height)*-1)}.ck.ck-balloon-panel.ck-balloon-panel_arrow_sme:after,.ck.ck-balloon-panel.ck-balloon-panel_arrow_sme:before{right:25%;margin-right:calc(var(--ck-balloon-arrow-half-width)*2);bottom:calc(var(--ck-balloon-arrow-height)*-1)}.ck.ck-balloon-panel.ck-balloon-panel_arrow_smw:after,.ck.ck-balloon-panel.ck-balloon-panel_arrow_smw:before{left:25%;margin-left:calc(var(--ck-balloon-arrow-half-width)*2);bottom:calc(var(--ck-balloon-arrow-height)*-1)}.ck.ck-balloon-panel.ck-balloon-panel_arrow_nme:after,.ck.ck-balloon-panel.ck-balloon-panel_arrow_nme:before{right:25%;margin-right:calc(var(--ck-balloon-arrow-half-width)*2);top:calc(var(--ck-balloon-arrow-height)*-1)}.ck.ck-balloon-panel.ck-balloon-panel_arrow_nmw:after,.ck.ck-balloon-panel.ck-balloon-panel_arrow_nmw:before{left:25%;margin-left:calc(var(--ck-balloon-arrow-half-width)*2);top:calc(var(--ck-balloon-arrow-height)*-1)}',"",{version:3,sources:["webpack://./node_modules/@ckeditor/ckeditor5-ui/theme/components/panel/balloonpanel.css","webpack://./node_modules/@ckeditor/ckeditor5-theme-lark/theme/ckeditor5-ui/components/panel/balloonpanel.css","webpack://./node_modules/@ckeditor/ckeditor5-theme-lark/theme/mixins/_rounded.css","webpack://./node_modules/@ckeditor/ckeditor5-theme-lark/theme/mixins/_shadow.css"],names:[],mappings:"AAKA,MAEC,8DACD,CAEA,qBACC,YAAa,CACb,iBAAkB,CAElB,yBAyCD,CAtCE,+GAEC,UAAW,CACX,iBACD,CAEA,wDACC,6CACD,CAEA,uDACC,uDACD,CAIA,4CACC,6CACD,CAEA,2CACC,uDACD,CAIA,4CACC,6CACD,CAEA,2CACC,uDACD,CAGD,8CACC,aACD,CC9CD,MACC,6BAA8B,CAC9B,8BAA+B,CAC/B,iCAAkC,CAClC,oEACD,CAEA,qBCJC,eD4ID,CAxIA,iFCAE,qCDwIF,CAxIA,qBENC,oCAA8B,CFU9B,eAAgB,CAEhB,2CAA4C,CAC5C,6CAiID,CA9HE,+GAEC,OAAQ,CACR,QAAS,CACT,kBACD,CAIA,uFAEC,oDAAoH,CAApH,kDAAoH,CAApH,qDAAoH,CAApH,kBACD,CAEA,4CACC,gDACD,CAEA,uFAHC,6BAA8E,CAA9E,8BAA8E,CAA9E,4BAMD,CAHA,2CACC,oDAAkF,CAClF,yCACD,CAIA,uFAEC,oDAAoH,CAApH,qBAAoH,CAApH,qDAAoH,CAApH,+CACD,CAEA,4CACC,6CAAkE,CAClE,uDACD,CAEA,uFAJC,6BAAkE,CAAlE,+BAAkE,CAAlE,8BAOD,CAHA,2CACC,iDAAkF,CAClF,4CACD,CAIA,yGAEC,QAAS,CACT,uDAA0D,CAC1D,2CACD,CAIA,2GAEC,+CAAkD,CAClD,2CACD,CAIA,2GAEC,gDAAmD,CACnD,2CACD,CAIA,yGAEC,QAAS,CACT,uDAA0D,CAC1D,8CACD,CAIA,2GAEC,+CAAkD,CAClD,8CACD,CAIA,2GAEC,gDAAmD,CACnD,8CACD,CAIA,6GAEC,SAAU,CACV,uDAA0D,CAC1D,8CACD,CAIA,6GAEC,QAAS,CACT,sDAAyD,CACzD,8CACD,CAIA,6GAEC,SAAU,CACV,uDAA0D,CAC1D,2CACD,CAIA,6GAEC,QAAS,CACT,sDAAyD,CACzD,2CACD",sourcesContent:['/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n:root {\n\t/* Make sure the balloon arrow does not float over its children. */\n\t--ck-balloon-panel-arrow-z-index: calc(var(--ck-z-default) - 3);\n}\n\n.ck.ck-balloon-panel {\n\tdisplay: none;\n\tposition: absolute;\n\n\tz-index: var(--ck-z-modal);\n\n\t&.ck-balloon-panel_with-arrow {\n\t\t&::before,\n\t\t&::after {\n\t\t\tcontent: "";\n\t\t\tposition: absolute;\n\t\t}\n\n\t\t&::before {\n\t\t\tz-index: var(--ck-balloon-panel-arrow-z-index);\n\t\t}\n\n\t\t&::after {\n\t\t\tz-index: calc(var(--ck-balloon-panel-arrow-z-index) + 1);\n\t\t}\n\t}\n\n\t&[class*="arrow_n"] {\n\t\t&::before {\n\t\t\tz-index: var(--ck-balloon-panel-arrow-z-index);\n\t\t}\n\n\t\t&::after {\n\t\t\tz-index: calc(var(--ck-balloon-panel-arrow-z-index) + 1);\n\t\t}\n\t}\n\n\t&[class*="arrow_s"] {\n\t\t&::before {\n\t\t\tz-index: var(--ck-balloon-panel-arrow-z-index);\n\t\t}\n\n\t\t&::after {\n\t\t\tz-index: calc(var(--ck-balloon-panel-arrow-z-index) + 1);\n\t\t}\n\t}\n\n\t&.ck-balloon-panel_visible {\n\t\tdisplay: block;\n\t}\n}\n','/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n@import "../../../mixins/_rounded.css";\n@import "../../../mixins/_shadow.css";\n\n:root {\n\t--ck-balloon-arrow-offset: 2px;\n\t--ck-balloon-arrow-height: 10px;\n\t--ck-balloon-arrow-half-width: 8px;\n\t--ck-balloon-arrow-drop-shadow: 0 2px 2px var(--ck-color-shadow-drop);\n}\n\n.ck.ck-balloon-panel {\n\t@mixin ck-rounded-corners;\n\t@mixin ck-drop-shadow;\n\n\tmin-height: 15px;\n\n\tbackground: var(--ck-color-panel-background);\n\tborder: 1px solid var(--ck-color-panel-border);\n\n\t&.ck-balloon-panel_with-arrow {\n\t\t&::before,\n\t\t&::after {\n\t\t\twidth: 0;\n\t\t\theight: 0;\n\t\t\tborder-style: solid;\n\t\t}\n\t}\n\n\t&[class*="arrow_n"] {\n\t\t&::before,\n\t\t&::after {\n\t\t\tborder-width: 0 var(--ck-balloon-arrow-half-width) var(--ck-balloon-arrow-height) var(--ck-balloon-arrow-half-width);\n\t\t}\n\n\t\t&::before {\n\t\t\tborder-color: transparent transparent var(--ck-color-panel-border) transparent;\n\t\t}\n\n\t\t&::after {\n\t\t\tborder-color: transparent transparent var(--ck-color-panel-background) transparent;\n\t\t\tmargin-top: var(--ck-balloon-arrow-offset);\n\t\t}\n\t}\n\n\t&[class*="arrow_s"] {\n\t\t&::before,\n\t\t&::after {\n\t\t\tborder-width: var(--ck-balloon-arrow-height) var(--ck-balloon-arrow-half-width) 0 var(--ck-balloon-arrow-half-width);\n\t\t}\n\n\t\t&::before {\n\t\t\tborder-color: var(--ck-color-panel-border) transparent transparent;\n\t\t\tfilter: drop-shadow(var(--ck-balloon-arrow-drop-shadow));\n\t\t}\n\n\t\t&::after {\n\t\t\tborder-color: var(--ck-color-panel-background) transparent transparent transparent;\n\t\t\tmargin-bottom: var(--ck-balloon-arrow-offset);\n\t\t}\n\t}\n\n\t&.ck-balloon-panel_arrow_n {\n\t\t&::before,\n\t\t&::after {\n\t\t\tleft: 50%;\n\t\t\tmargin-left: calc(-1 * var(--ck-balloon-arrow-half-width));\n\t\t\ttop: calc(-1 * var(--ck-balloon-arrow-height));\n\t\t}\n\t}\n\n\t&.ck-balloon-panel_arrow_nw {\n\t\t&::before,\n\t\t&::after {\n\t\t\tleft: calc(2 * var(--ck-balloon-arrow-half-width));\n\t\t\ttop: calc(-1 * var(--ck-balloon-arrow-height));\n\t\t}\n\t}\n\n\t&.ck-balloon-panel_arrow_ne {\n\t\t&::before,\n\t\t&::after {\n\t\t\tright: calc(2 * var(--ck-balloon-arrow-half-width));\n\t\t\ttop: calc(-1 * var(--ck-balloon-arrow-height));\n\t\t}\n\t}\n\n\t&.ck-balloon-panel_arrow_s {\n\t\t&::before,\n\t\t&::after {\n\t\t\tleft: 50%;\n\t\t\tmargin-left: calc(-1 * var(--ck-balloon-arrow-half-width));\n\t\t\tbottom: calc(-1 * var(--ck-balloon-arrow-height));\n\t\t}\n\t}\n\n\t&.ck-balloon-panel_arrow_sw {\n\t\t&::before,\n\t\t&::after {\n\t\t\tleft: calc(2 * var(--ck-balloon-arrow-half-width));\n\t\t\tbottom: calc(-1 * var(--ck-balloon-arrow-height));\n\t\t}\n\t}\n\n\t&.ck-balloon-panel_arrow_se {\n\t\t&::before,\n\t\t&::after {\n\t\t\tright: calc(2 * var(--ck-balloon-arrow-half-width));\n\t\t\tbottom: calc(-1 * var(--ck-balloon-arrow-height));\n\t\t}\n\t}\n\n\t&.ck-balloon-panel_arrow_sme {\n\t\t&::before,\n\t\t&::after {\n\t\t\tright: 25%;\n\t\t\tmargin-right: calc(2 * var(--ck-balloon-arrow-half-width));\n\t\t\tbottom: calc(-1 * var(--ck-balloon-arrow-height));\n\t\t}\n\t}\n\n\t&.ck-balloon-panel_arrow_smw {\n\t\t&::before,\n\t\t&::after {\n\t\t\tleft: 25%;\n\t\t\tmargin-left: calc(2 * var(--ck-balloon-arrow-half-width));\n\t\t\tbottom: calc(-1 * var(--ck-balloon-arrow-height));\n\t\t}\n\t}\n\n\t&.ck-balloon-panel_arrow_nme {\n\t\t&::before,\n\t\t&::after {\n\t\t\tright: 25%;\n\t\t\tmargin-right: calc(2 * var(--ck-balloon-arrow-half-width));\n\t\t\ttop: calc(-1 * var(--ck-balloon-arrow-height));\n\t\t}\n\t}\n\n\t&.ck-balloon-panel_arrow_nmw {\n\t\t&::before,\n\t\t&::after {\n\t\t\tleft: 25%;\n\t\t\tmargin-left: calc(2 * var(--ck-balloon-arrow-half-width));\n\t\t\ttop: calc(-1 * var(--ck-balloon-arrow-height));\n\t\t}\n\t}\n}\n',"/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * Implements rounded corner interface for .ck-rounded-corners class.\n *\n * @see $ck-border-radius\n */\n@define-mixin ck-rounded-corners {\n\tborder-radius: 0;\n\n\t@nest .ck-rounded-corners &,\n\t&.ck-rounded-corners {\n\t\tborder-radius: var(--ck-border-radius);\n\t\t@mixin-content;\n\t}\n}\n","/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * A helper to combine multiple shadows.\n */\n@define-mixin ck-box-shadow $shadowA, $shadowB: 0 0 {\n\tbox-shadow: $shadowA, $shadowB;\n}\n\n/**\n * Gives an element a drop shadow so it looks like a floating panel.\n */\n@define-mixin ck-drop-shadow {\n\t@mixin ck-box-shadow var(--ck-drop-shadow);\n}\n"],sourceRoot:""}]);e["a"]=a},function(t,e,n){"use strict";var o=n(2);var i=n.n(o);var r=n(3);var s=n.n(r);var a=s()(i.a);a.push([t.i,".ck .ck-link_selected{background:var(--ck-color-link-selected-background)}.ck .ck-fake-link-selection{background:var(--ck-color-link-fake-selection)}.ck .ck-fake-link-selection_collapsed{height:100%;border-right:1px solid var(--ck-color-base-text);margin-right:-1px;outline:1px solid hsla(0,0%,100%,.5)}","",{version:3,sources:["webpack://./node_modules/@ckeditor/ckeditor5-theme-lark/theme/ckeditor5-link/link.css"],names:[],mappings:"AAMA,sBACC,mDACD,CAMA,4BACC,8CACD,CAGA,sCACC,WAAY,CACZ,gDAAiD,CACjD,iBAAkB,CAClB,oCACD",sourcesContent:['/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/* Class added to span element surrounding currently selected link. */\n.ck .ck-link_selected {\n\tbackground: var(--ck-color-link-selected-background);\n}\n\n/*\n * Classes used by the "fake visual selection" displayed in the content when an input\n * in the link UI has focus (the browser does not render the native selection in this state).\n */\n.ck .ck-fake-link-selection {\n\tbackground: var(--ck-color-link-fake-selection);\n}\n\n/* A collapsed fake visual selection. */\n.ck .ck-fake-link-selection_collapsed {\n\theight: 100%;\n\tborder-right: 1px solid var(--ck-color-base-text);\n\tmargin-right: -1px;\n\toutline: solid 1px hsla(0, 0%, 100%, .5);\n}\n'],sourceRoot:""}]);e["a"]=a},function(t,e,n){"use strict";var o=n(2);var i=n.n(o);var r=n(3);var s=n.n(r);var a=s()(i.a);a.push([t.i,".ck.ck-color-grid{display:grid}:root{--ck-color-grid-tile-size:24px;--ck-color-color-grid-check-icon:#000}.ck.ck-color-grid{grid-gap:5px;padding:8px}.ck.ck-color-grid__tile{width:var(--ck-color-grid-tile-size);height:var(--ck-color-grid-tile-size);min-width:var(--ck-color-grid-tile-size);min-height:var(--ck-color-grid-tile-size);padding:0;transition:box-shadow .2s ease;border:0}.ck.ck-color-grid__tile.ck-disabled{cursor:unset;transition:unset}.ck.ck-color-grid__tile.ck-color-table__color-tile_bordered{box-shadow:0 0 0 1px var(--ck-color-base-border)}.ck.ck-color-grid__tile .ck.ck-icon{display:none;color:var(--ck-color-color-grid-check-icon)}.ck.ck-color-grid__tile.ck-on{box-shadow:inset 0 0 0 1px var(--ck-color-base-background),0 0 0 2px var(--ck-color-base-text)}.ck.ck-color-grid__tile.ck-on .ck.ck-icon{display:block}.ck.ck-color-grid__tile.ck-on,.ck.ck-color-grid__tile:focus:not(.ck-disabled),.ck.ck-color-grid__tile:hover:not(.ck-disabled){border:0}.ck.ck-color-grid__tile:focus:not(.ck-disabled),.ck.ck-color-grid__tile:hover:not(.ck-disabled){box-shadow:inset 0 0 0 1px var(--ck-color-base-background),0 0 0 2px var(--ck-color-focus-border)}.ck.ck-color-grid__label{padding:0 var(--ck-spacing-standard)}","",{version:3,sources:["webpack://./node_modules/@ckeditor/ckeditor5-ui/theme/components/colorgrid/colorgrid.css","webpack://./node_modules/@ckeditor/ckeditor5-theme-lark/theme/ckeditor5-ui/components/colorgrid/colorgrid.css"],names:[],mappings:"AAKA,kBACC,YACD,CCAA,MACC,8BAA+B,CAK/B,qCACD,CAEA,kBACC,YAAa,CACb,WACD,CAEA,wBACC,oCAAqC,CACrC,qCAAsC,CACtC,wCAAyC,CACzC,yCAA0C,CAC1C,SAAU,CACV,8BAA+B,CAC/B,QAmCD,CAjCC,oCACC,YAAa,CACb,gBACD,CAEA,4DACC,gDACD,CAEA,oCACC,YAAa,CACb,2CACD,CAEA,8BACC,8FAKD,CAHC,0CACC,aACD,CAGD,8HAIC,QACD,CAEA,gGAEC,iGACD,CAGD,yBACC,oCACD",sourcesContent:["/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n.ck.ck-color-grid {\n\tdisplay: grid;\n}\n",'/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n@import "../../../mixins/_rounded.css";\n\n:root {\n\t--ck-color-grid-tile-size: 24px;\n\n\t/* Not using global colors here because these may change but some colors in a pallette\n\t * require special treatment. For instance, this ensures no matter what the UI text color is,\n\t * the check icon will look good on the black color tile. */\n\t--ck-color-color-grid-check-icon: hsl(0, 0%, 0%);\n}\n\n.ck.ck-color-grid {\n\tgrid-gap: 5px;\n\tpadding: 8px;\n}\n\n.ck.ck-color-grid__tile {\n\twidth: var(--ck-color-grid-tile-size);\n\theight: var(--ck-color-grid-tile-size);\n\tmin-width: var(--ck-color-grid-tile-size);\n\tmin-height: var(--ck-color-grid-tile-size);\n\tpadding: 0;\n\ttransition: .2s ease box-shadow;\n\tborder: 0;\n\n\t&.ck-disabled {\n\t\tcursor: unset;\n\t\ttransition: unset;\n\t}\n\n\t&.ck-color-table__color-tile_bordered {\n\t\tbox-shadow: 0 0 0 1px var(--ck-color-base-border);\n\t}\n\n\t& .ck.ck-icon {\n\t\tdisplay: none;\n\t\tcolor: var(--ck-color-color-grid-check-icon);\n\t}\n\n\t&.ck-on {\n\t\tbox-shadow: inset 0 0 0 1px var(--ck-color-base-background), 0 0 0 2px var(--ck-color-base-text);\n\n\t\t& .ck.ck-icon {\n\t\t\tdisplay: block;\n\t\t}\n\t}\n\n\t&.ck-on,\n\t&:focus:not( .ck-disabled ),\n\t&:hover:not( .ck-disabled ) {\n\t\t/* Disable the default .ck-button\'s border ring. */\n\t\tborder: 0;\n\t}\n\n\t&:focus:not( .ck-disabled ),\n\t&:hover:not( .ck-disabled ) {\n\t\tbox-shadow: inset 0 0 0 1px var(--ck-color-base-background), 0 0 0 2px var(--ck-color-focus-border);\n\t}\n}\n\n.ck.ck-color-grid__label {\n\tpadding: 0 var(--ck-spacing-standard);\n}\n'],sourceRoot:""}]);e["a"]=a},function(t,e,n){"use strict";var o=n(2);var i=n.n(o);var r=n(3);var s=n.n(r);var a=s()(i.a);a.push([t.i,".ck .ck-button.ck-color-table__remove-color{display:flex;align-items:center;width:100%}label.ck.ck-color-grid__label{font-weight:unset}.ck .ck-button.ck-color-table__remove-color{padding:calc(var(--ck-spacing-standard)/2) var(--ck-spacing-standard);border-bottom-left-radius:0;border-bottom-right-radius:0}.ck .ck-button.ck-color-table__remove-color:not(:focus){border-bottom:1px solid var(--ck-color-base-border)}[dir=ltr] .ck .ck-button.ck-color-table__remove-color .ck.ck-icon{margin-right:var(--ck-spacing-standard)}[dir=rtl] .ck .ck-button.ck-color-table__remove-color .ck.ck-icon{margin-left:var(--ck-spacing-standard)}","",{version:3,sources:["webpack://./node_modules/@ckeditor/ckeditor5-font/theme/fontcolor.css","webpack://./node_modules/@ckeditor/ckeditor5-theme-lark/theme/ckeditor5-font/fontcolor.css"],names:[],mappings:"AAKA,4CACC,YAAa,CACb,kBAAmB,CACnB,UACD,CAEA,8BACC,iBACD,CCNA,4CACC,qEAAyE,CACzE,2BAA4B,CAC5B,4BAeD,CAbC,wDACC,mDACD,CAEA,kEAEE,uCAMF,CARA,kEAME,sCAEF",sourcesContent:["/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n.ck .ck-button.ck-color-table__remove-color {\n\tdisplay: flex;\n\talign-items: center;\n\twidth: 100%;\n}\n\nlabel.ck.ck-color-grid__label {\n\tfont-weight: unset;\n}\n",'/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n@import "@ckeditor/ckeditor5-ui/theme/mixins/_dir.css";\n\n.ck .ck-button.ck-color-table__remove-color {\n\tpadding: calc(var(--ck-spacing-standard) / 2 ) var(--ck-spacing-standard);\n\tborder-bottom-left-radius: 0;\n\tborder-bottom-right-radius: 0;\n\n\t&:not(:focus) {\n\t\tborder-bottom: 1px solid var(--ck-color-base-border);\n\t}\n\n\t& .ck.ck-icon {\n\t\t@mixin ck-dir ltr {\n\t\t\tmargin-right: var(--ck-spacing-standard);\n\t\t}\n\n\t\t@mixin ck-dir rtl {\n\t\t\tmargin-left: var(--ck-spacing-standard);\n\t\t}\n\t}\n}\n\n'],sourceRoot:""}]);e["a"]=a},function(t,e,n){"use strict";var o=n(2);var i=n.n(o);var r=n(3);var s=n.n(r);var a=s()(i.a);a.push([t.i,".ck-content .text-tiny{font-size:.7em}.ck-content .text-small{font-size:.85em}.ck-content .text-big{font-size:1.4em}.ck-content .text-huge{font-size:1.8em}","",{version:3,sources:["webpack://./node_modules/@ckeditor/ckeditor5-font/theme/fontsize.css"],names:[],mappings:"AAUC,uBACC,cACD,CAEA,wBACC,eACD,CAEA,sBACC,eACD,CAEA,uBACC,eACD",sourcesContent:['/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/* The values should be synchronized with the "FONT_SIZE_PRESET_UNITS" object in the "/src/fontsize/utils.js" file. */\n\n/* Styles should be prefixed with the `.ck-content` class.\nSee https://github.com/ckeditor/ckeditor5/issues/6636 */\n.ck-content {\n\t& .text-tiny {\n\t\tfont-size: .7em;\n\t}\n\n\t& .text-small {\n\t\tfont-size: .85em;\n\t}\n\n\t& .text-big {\n\t\tfont-size: 1.4em;\n\t}\n\n\t& .text-huge {\n\t\tfont-size: 1.8em;\n\t}\n}\n'],sourceRoot:""}]);e["a"]=a},function(t,e,n){"use strict";var o=n(2);var i=n.n(o);var r=n(3);var s=n.n(r);var a=s()(i.a);a.push([t.i,".ck.ck-heading_heading1{font-size:20px}.ck.ck-heading_heading2{font-size:17px}.ck.ck-heading_heading3{font-size:14px}.ck[class*=ck-heading_heading]{font-weight:700}.ck.ck-dropdown.ck-heading-dropdown .ck-dropdown__button .ck-button__label{width:8em}.ck.ck-dropdown.ck-heading-dropdown .ck-dropdown__panel .ck-list__item{min-width:18em}","",{version:3,sources:["webpack://./node_modules/@ckeditor/ckeditor5-heading/theme/heading.css","webpack://./node_modules/@ckeditor/ckeditor5-theme-lark/theme/ckeditor5-heading/heading.css"],names:[],mappings:"AAKA,wBACC,cACD,CAEA,wBACC,cACD,CAEA,wBACC,cACD,CAEA,+BACC,eACD,CCZC,2EACC,SACD,CAEA,uEACC,cACD",sourcesContent:['/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n.ck.ck-heading_heading1 {\n\tfont-size: 20px;\n}\n\n.ck.ck-heading_heading2 {\n\tfont-size: 17px;\n}\n\n.ck.ck-heading_heading3 {\n\tfont-size: 14px;\n}\n\n.ck[class*="ck-heading_heading"] {\n\tfont-weight: bold;\n}\n',"/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/* Resize dropdown's button label. */\n.ck.ck-dropdown.ck-heading-dropdown {\n\t& .ck-dropdown__button .ck-button__label {\n\t\twidth: 8em;\n\t}\n\n\t& .ck-dropdown__panel .ck-list__item {\n\t\tmin-width: 18em;\n\t}\n}\n"],sourceRoot:""}]);e["a"]=a},function(t,e,n){"use strict";var o=n(2);var i=n.n(o);var r=n(3);var s=n.n(r);var a=s()(i.a);a.push([t.i,".ck-editor__editable .ck-horizontal-line{display:flow-root}.ck-content hr{margin:15px 0;height:4px;background:#dedede;border:0}","",{version:3,sources:["webpack://./node_modules/@ckeditor/ckeditor5-horizontal-line/theme/horizontalline.css"],names:[],mappings:"AAMA,yCAEC,iBACD,CAEA,eACC,aAAc,CACd,UAAW,CACX,kBAA2B,CAC3B,QACD",sourcesContent:["/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n\n.ck-editor__editable .ck-horizontal-line {\n\t/* Necessary to render properly next to floated objects, e.g. side image case. */\n\tdisplay: flow-root;\n}\n\n.ck-content hr {\n\tmargin: 15px 0;\n\theight: 4px;\n\tbackground: hsl(0, 0%, 87%);\n\tborder: 0;\n}\n"],sourceRoot:""}]);e["a"]=a},function(t,e,n){"use strict";var o=n(2);var i=n.n(o);var r=n(3);var s=n.n(r);var a=s()(i.a);a.push([t.i,'.ck .ck-widget .ck-widget__type-around__button{display:block;position:absolute;overflow:hidden;z-index:var(--ck-z-default)}.ck .ck-widget .ck-widget__type-around__button svg{position:absolute;top:50%;left:50%;z-index:calc(var(--ck-z-default) + 2)}.ck .ck-widget .ck-widget__type-around__button.ck-widget__type-around__button_before{top:calc(var(--ck-widget-outline-thickness)*-0.5);left:min(10%,30px);transform:translateY(-50%)}.ck .ck-widget .ck-widget__type-around__button.ck-widget__type-around__button_after{bottom:calc(var(--ck-widget-outline-thickness)*-0.5);right:min(10%,30px);transform:translateY(50%)}.ck .ck-widget.ck-widget_selected>.ck-widget__type-around>.ck-widget__type-around__button:after,.ck .ck-widget>.ck-widget__type-around>.ck-widget__type-around__button:hover:after{content:"";display:block;position:absolute;top:1px;left:1px;z-index:calc(var(--ck-z-default) + 1)}.ck .ck-widget>.ck-widget__type-around>.ck-widget__type-around__fake-caret{display:none;position:absolute;left:0;right:0}.ck .ck-widget:hover>.ck-widget__type-around>.ck-widget__type-around__fake-caret{left:calc(var(--ck-widget-outline-thickness)*-1);right:calc(var(--ck-widget-outline-thickness)*-1)}.ck .ck-widget.ck-widget_type-around_show-fake-caret_before>.ck-widget__type-around>.ck-widget__type-around__fake-caret{top:calc(var(--ck-widget-outline-thickness)*-1 - 1px);display:block}.ck .ck-widget.ck-widget_type-around_show-fake-caret_after>.ck-widget__type-around>.ck-widget__type-around__fake-caret{bottom:calc(var(--ck-widget-outline-thickness)*-1 - 1px);display:block}.ck.ck-editor__editable.ck-read-only .ck-widget__type-around,.ck.ck-editor__editable.ck-restricted-editing_mode_restricted .ck-widget__type-around,.ck.ck-editor__editable.ck-widget__type-around_disabled .ck-widget__type-around{display:none}:root{--ck-widget-type-around-button-size:20px;--ck-color-widget-type-around-button-active:var(--ck-color-focus-border);--ck-color-widget-type-around-button-hover:var(--ck-color-widget-hover-border);--ck-color-widget-type-around-button-blurred-editable:var(--ck-color-widget-blurred-border);--ck-color-widget-type-around-button-radar-start-alpha:0;--ck-color-widget-type-around-button-radar-end-alpha:.3;--ck-color-widget-type-around-button-icon:var(--ck-color-base-background)}.ck .ck-widget .ck-widget__type-around__button{width:var(--ck-widget-type-around-button-size);height:var(--ck-widget-type-around-button-size);background:var(--ck-color-widget-type-around-button);border-radius:100px;transition:opacity var(--ck-widget-handler-animation-duration) var(--ck-widget-handler-animation-curve),background var(--ck-widget-handler-animation-duration) var(--ck-widget-handler-animation-curve);opacity:0;pointer-events:none}.ck .ck-widget .ck-widget__type-around__button svg{width:10px;height:8px;transform:translate(-50%,-50%);transition:transform .5s ease;margin-top:1px}.ck .ck-widget .ck-widget__type-around__button svg *{stroke-dasharray:10;stroke-dashoffset:0;fill:none;stroke:var(--ck-color-widget-type-around-button-icon);stroke-width:1.5px;stroke-linecap:round;stroke-linejoin:round}.ck .ck-widget .ck-widget__type-around__button svg line{stroke-dasharray:7}.ck .ck-widget .ck-widget__type-around__button:hover{animation:ck-widget-type-around-button-sonar 1s ease infinite}.ck .ck-widget .ck-widget__type-around__button:hover svg polyline{animation:ck-widget-type-around-arrow-dash 2s linear}.ck .ck-widget .ck-widget__type-around__button:hover svg line{animation:ck-widget-type-around-arrow-tip-dash 2s linear}.ck .ck-widget.ck-widget_selected>.ck-widget__type-around>.ck-widget__type-around__button,.ck .ck-widget:hover>.ck-widget__type-around>.ck-widget__type-around__button{opacity:1;pointer-events:auto}.ck .ck-widget:not(.ck-widget_selected)>.ck-widget__type-around>.ck-widget__type-around__button{background:var(--ck-color-widget-type-around-button-hover)}.ck .ck-widget.ck-widget_selected>.ck-widget__type-around>.ck-widget__type-around__button,.ck .ck-widget>.ck-widget__type-around>.ck-widget__type-around__button:hover{background:var(--ck-color-widget-type-around-button-active)}.ck .ck-widget.ck-widget_selected>.ck-widget__type-around>.ck-widget__type-around__button:after,.ck .ck-widget>.ck-widget__type-around>.ck-widget__type-around__button:hover:after{width:calc(var(--ck-widget-type-around-button-size) - 2px);height:calc(var(--ck-widget-type-around-button-size) - 2px);border-radius:100px;background:linear-gradient(135deg,hsla(0,0%,100%,0),hsla(0,0%,100%,.3))}.ck .ck-widget.ck-widget_with-selection-handle>.ck-widget__type-around>.ck-widget__type-around__button_before{margin-left:20px}.ck .ck-widget .ck-widget__type-around__fake-caret{pointer-events:none;height:1px;animation:ck-widget-type-around-fake-caret-pulse 1s linear infinite normal forwards;outline:1px solid hsla(0,0%,100%,.5);background:var(--ck-color-base-text)}.ck .ck-widget.ck-widget_selected.ck-widget_type-around_show-fake-caret_after,.ck .ck-widget.ck-widget_selected.ck-widget_type-around_show-fake-caret_before{outline-color:transparent}.ck .ck-widget.ck-widget_type-around_show-fake-caret_after.ck-widget_selected:hover,.ck .ck-widget.ck-widget_type-around_show-fake-caret_before.ck-widget_selected:hover{outline-color:var(--ck-color-widget-hover-border)}.ck .ck-widget.ck-widget_type-around_show-fake-caret_after>.ck-widget__type-around>.ck-widget__type-around__button,.ck .ck-widget.ck-widget_type-around_show-fake-caret_before>.ck-widget__type-around>.ck-widget__type-around__button{opacity:0;pointer-events:none}.ck .ck-widget.ck-widget_type-around_show-fake-caret_after.ck-widget_with-selection-handle.ck-widget_selected:hover>.ck-widget__selection-handle,.ck .ck-widget.ck-widget_type-around_show-fake-caret_after.ck-widget_with-selection-handle.ck-widget_selected>.ck-widget__selection-handle,.ck .ck-widget.ck-widget_type-around_show-fake-caret_before.ck-widget_with-selection-handle.ck-widget_selected:hover>.ck-widget__selection-handle,.ck .ck-widget.ck-widget_type-around_show-fake-caret_before.ck-widget_with-selection-handle.ck-widget_selected>.ck-widget__selection-handle{opacity:0}.ck .ck-widget.ck-widget_type-around_show-fake-caret_after.ck-widget_selected.ck-widget_with-resizer>.ck-widget__resizer,.ck .ck-widget.ck-widget_type-around_show-fake-caret_before.ck-widget_selected.ck-widget_with-resizer>.ck-widget__resizer{opacity:0}.ck[dir=rtl] .ck-widget.ck-widget_with-selection-handle .ck-widget__type-around>.ck-widget__type-around__button_before{margin-left:0;margin-right:20px}.ck-editor__nested-editable.ck-editor__editable_selected .ck-widget.ck-widget_selected>.ck-widget__type-around>.ck-widget__type-around__button,.ck-editor__nested-editable.ck-editor__editable_selected .ck-widget:hover>.ck-widget__type-around>.ck-widget__type-around__button{opacity:0;pointer-events:none}.ck-editor__editable.ck-blurred .ck-widget.ck-widget_selected>.ck-widget__type-around>.ck-widget__type-around__button:not(:hover){background:var(--ck-color-widget-type-around-button-blurred-editable)}.ck-editor__editable.ck-blurred .ck-widget.ck-widget_selected>.ck-widget__type-around>.ck-widget__type-around__button:not(:hover) svg *{stroke:#999}@keyframes ck-widget-type-around-arrow-dash{0%{stroke-dashoffset:10}20%,to{stroke-dashoffset:0}}@keyframes ck-widget-type-around-arrow-tip-dash{0%,20%{stroke-dashoffset:7}40%,to{stroke-dashoffset:0}}@keyframes ck-widget-type-around-button-sonar{0%{box-shadow:0 0 0 0 hsla(var(--ck-color-focus-border-coordinates),var(--ck-color-widget-type-around-button-radar-start-alpha))}50%{box-shadow:0 0 0 5px hsla(var(--ck-color-focus-border-coordinates),var(--ck-color-widget-type-around-button-radar-end-alpha))}to{box-shadow:0 0 0 5px hsla(var(--ck-color-focus-border-coordinates),var(--ck-color-widget-type-around-button-radar-start-alpha))}}@keyframes ck-widget-type-around-fake-caret-pulse{0%{opacity:1}49%{opacity:1}50%{opacity:0}99%{opacity:0}to{opacity:1}}',"",{version:3,sources:["webpack://./node_modules/@ckeditor/ckeditor5-widget/theme/widgettypearound.css","webpack://./node_modules/@ckeditor/ckeditor5-theme-lark/theme/ckeditor5-widget/widgettypearound.css"],names:[],mappings:"AASC,+CACC,aAAc,CACd,iBAAkB,CAClB,eAAgB,CAChB,2BAwBD,CAtBC,mDACC,iBAAkB,CAClB,OAAQ,CACR,QAAS,CACT,qCACD,CAEA,qFAEC,iDAAoD,CACpD,kBAAoB,CAEpB,0BACD,CAEA,oFAEC,oDAAuD,CACvD,mBAAqB,CAErB,yBACD,CAUA,mLACC,UAAW,CACX,aAAc,CACd,iBAAkB,CAClB,OAAQ,CACR,QAAS,CACT,qCACD,CAMD,2EACC,YAAa,CACb,iBAAkB,CAClB,MAAO,CACP,OACD,CAOA,iFACC,gDAAqD,CACrD,iDACD,CAKA,wHACC,qDAA0D,CAC1D,aACD,CAKA,uHACC,wDAA6D,CAC7D,aACD,CAoBD,mOACC,YACD,CC3GA,MACC,wCAAyC,CACzC,wEAAyE,CACzE,8EAA+E,CAC/E,2FAA4F,CAC5F,wDAAyD,CACzD,uDAAwD,CACxD,yEACD,CAgBC,+CACC,8CAA+C,CAC/C,+CAAgD,CAChD,oDAAqD,CACrD,mBAAoB,CACpB,uMAAyM,CAb1M,SAAU,CACV,mBA0DA,CA1CC,mDACC,UAAW,CACX,UAAW,CACX,8BAA+B,CAC/B,6BAA8B,CAC9B,cAgBD,CAdC,qDACC,mBAAoB,CACpB,mBAAoB,CAEpB,SAAU,CACV,qDAAsD,CACtD,kBAAmB,CACnB,oBAAqB,CACrB,qBACD,CAEA,wDACC,kBACD,CAGD,qDAIC,6DAcD,CARE,kEACC,oDACD,CAEA,8DACC,wDACD,CAUF,uKAvED,SAAU,CACV,mBAwEC,CAOD,gGACC,0DACD,CAOA,uKAEC,2DAQD,CANC,mLACC,0DAA2D,CAC3D,2DAA4D,CAC5D,mBAAoB,CACpB,uEACD,CAOD,8GACC,gBACD,CAKA,mDACC,mBAAoB,CACpB,UAAW,CACX,mFAAoF,CAMpF,oCAAwC,CACxC,oCACD,CAOC,6JAEC,yBACD,CAUA,yKACC,iDACD,CAMA,uOAlJD,SAAU,CACV,mBAmJC,CASE,0jBACC,SACD,CASF,mPACC,SACD,CASF,uHACC,aAAc,CACd,iBACD,CAYG,iRAlMF,SAAU,CACV,mBAmME,CAQH,kIACC,qEAKD,CAHC,wIACC,WACD,CAGD,4CACC,GACC,oBACD,CACA,OACC,mBACD,CACD,CAEA,gDACC,OACC,mBACD,CACA,OACC,mBACD,CACD,CAEA,8CACC,GACC,6HACD,CACA,IACC,6HACD,CACA,GACC,+HACD,CACD,CAEA,kDACC,GACC,SACD,CACA,IACC,SACD,CACA,IACC,SACD,CACA,IACC,SACD,CACA,GACC,SACD,CACD",sourcesContent:['/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n.ck .ck-widget {\n\t/*\n\t * Styles of the type around buttons\n\t */\n\t& .ck-widget__type-around__button {\n\t\tdisplay: block;\n\t\tposition: absolute;\n\t\toverflow: hidden;\n\t\tz-index: var(--ck-z-default);\n\n\t\t& svg {\n\t\t\tposition: absolute;\n\t\t\ttop: 50%;\n\t\t\tleft: 50%;\n\t\t\tz-index: calc(var(--ck-z-default) + 2);\n\t\t}\n\n\t\t&.ck-widget__type-around__button_before {\n\t\t\t/* Place it in the middle of the outline */\n\t\t\ttop: calc(-0.5 * var(--ck-widget-outline-thickness));\n\t\t\tleft: min(10%, 30px);\n\n\t\t\ttransform: translateY(-50%);\n\t\t}\n\n\t\t&.ck-widget__type-around__button_after {\n\t\t\t/* Place it in the middle of the outline */\n\t\t\tbottom: calc(-0.5 * var(--ck-widget-outline-thickness));\n\t\t\tright: min(10%, 30px);\n\n\t\t\ttransform: translateY(50%);\n\t\t}\n\t}\n\n\t/*\n\t * Styles for the buttons when:\n\t * - the widget is selected,\n\t * - or the button is being hovered (regardless of the widget state).\n\t */\n\t&.ck-widget_selected > .ck-widget__type-around > .ck-widget__type-around__button,\n\t& > .ck-widget__type-around > .ck-widget__type-around__button:hover {\n\t\t&::after {\n\t\t\tcontent: "";\n\t\t\tdisplay: block;\n\t\t\tposition: absolute;\n\t\t\ttop: 1px;\n\t\t\tleft: 1px;\n\t\t\tz-index: calc(var(--ck-z-default) + 1);\n\t\t}\n\t}\n\n\t/*\n\t * Styles for the horizontal "fake caret" which is displayed when the user navigates using the keyboard.\n\t */\n\t& > .ck-widget__type-around > .ck-widget__type-around__fake-caret {\n\t\tdisplay: none;\n\t\tposition: absolute;\n\t\tleft: 0;\n\t\tright: 0;\n\t}\n\n\t/*\n\t * When the widget is hovered the "fake caret" would normally be narrower than the\n\t * extra outline displayed around the widget. Let\'s extend the "fake caret" to match\n\t * the full width of the widget.\n\t */\n\t&:hover > .ck-widget__type-around > .ck-widget__type-around__fake-caret {\n\t\tleft: calc( -1 * var(--ck-widget-outline-thickness) );\n\t\tright: calc( -1 * var(--ck-widget-outline-thickness) );\n\t}\n\n\t/*\n\t * Styles for the horizontal "fake caret" when it should be displayed before the widget (backward keyboard navigation).\n\t */\n\t&.ck-widget_type-around_show-fake-caret_before > .ck-widget__type-around > .ck-widget__type-around__fake-caret {\n\t\ttop: calc( -1 * var(--ck-widget-outline-thickness) - 1px );\n\t\tdisplay: block;\n\t}\n\n\t/*\n\t * Styles for the horizontal "fake caret" when it should be displayed after the widget (forward keyboard navigation).\n\t */\n\t&.ck-widget_type-around_show-fake-caret_after > .ck-widget__type-around > .ck-widget__type-around__fake-caret {\n\t\tbottom: calc( -1 * var(--ck-widget-outline-thickness) - 1px );\n\t\tdisplay: block;\n\t}\n}\n\n/*\n * Integration with the read-only mode of the editor.\n */\n.ck.ck-editor__editable.ck-read-only .ck-widget__type-around {\n\tdisplay: none;\n}\n\n/*\n * Integration with the restricted editing mode (feature) of the editor.\n */\n.ck.ck-editor__editable.ck-restricted-editing_mode_restricted .ck-widget__type-around {\n\tdisplay: none;\n}\n\n/*\n * Integration with the #isEnabled property of the WidgetTypeAround plugin.\n */\n.ck.ck-editor__editable.ck-widget__type-around_disabled .ck-widget__type-around {\n\tdisplay: none;\n}\n','/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n:root {\n\t--ck-widget-type-around-button-size: 20px;\n\t--ck-color-widget-type-around-button-active: var(--ck-color-focus-border);\n\t--ck-color-widget-type-around-button-hover: var(--ck-color-widget-hover-border);\n\t--ck-color-widget-type-around-button-blurred-editable: var(--ck-color-widget-blurred-border);\n\t--ck-color-widget-type-around-button-radar-start-alpha: 0;\n\t--ck-color-widget-type-around-button-radar-end-alpha: .3;\n\t--ck-color-widget-type-around-button-icon: var(--ck-color-base-background);\n}\n\n@define-mixin ck-widget-type-around-button-visible {\n\topacity: 1;\n\tpointer-events: auto;\n}\n\n@define-mixin ck-widget-type-around-button-hidden {\n\topacity: 0;\n\tpointer-events: none;\n}\n\n.ck .ck-widget {\n\t/*\n\t * Styles of the type around buttons\n\t */\n\t& .ck-widget__type-around__button {\n\t\twidth: var(--ck-widget-type-around-button-size);\n\t\theight: var(--ck-widget-type-around-button-size);\n\t\tbackground: var(--ck-color-widget-type-around-button);\n\t\tborder-radius: 100px;\n\t\ttransition: opacity var(--ck-widget-handler-animation-duration) var(--ck-widget-handler-animation-curve), background var(--ck-widget-handler-animation-duration) var(--ck-widget-handler-animation-curve);\n\n\t\t@mixin ck-widget-type-around-button-hidden;\n\n\t\t& svg {\n\t\t\twidth: 10px;\n\t\t\theight: 8px;\n\t\t\ttransform: translate(-50%,-50%);\n\t\t\ttransition: transform .5s ease;\n\t\t\tmargin-top: 1px;\n\n\t\t\t& * {\n\t\t\t\tstroke-dasharray: 10;\n\t\t\t\tstroke-dashoffset: 0;\n\n\t\t\t\tfill: none;\n\t\t\t\tstroke: var(--ck-color-widget-type-around-button-icon);\n\t\t\t\tstroke-width: 1.5px;\n\t\t\t\tstroke-linecap: round;\n\t\t\t\tstroke-linejoin: round;\n\t\t\t}\n\n\t\t\t& line {\n\t\t\t\tstroke-dasharray: 7;\n\t\t\t}\n\t\t}\n\n\t\t&:hover {\n\t\t\t/*\n\t\t\t * Display the "sonar" around the button when hovered.\n\t\t\t */\n\t\t\tanimation: ck-widget-type-around-button-sonar 1s ease infinite;\n\n\t\t\t/*\n\t\t\t * Animate active button\'s icon.\n\t\t\t */\n\t\t\t& svg {\n\t\t\t\t& polyline {\n\t\t\t\t\tanimation: ck-widget-type-around-arrow-dash 2s linear;\n\t\t\t\t}\n\n\t\t\t\t& line {\n\t\t\t\t\tanimation: ck-widget-type-around-arrow-tip-dash 2s linear;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t * Show type around buttons when the widget gets selected or being hovered.\n\t */\n\t&.ck-widget_selected,\n\t&:hover {\n\t\t& > .ck-widget__type-around > .ck-widget__type-around__button {\n\t\t\t@mixin ck-widget-type-around-button-visible;\n\t\t}\n\t}\n\n\t/*\n\t * Styles for the buttons when the widget is NOT selected (but the buttons are visible\n\t * and still can be hovered).\n\t */\n\t&:not(.ck-widget_selected) > .ck-widget__type-around > .ck-widget__type-around__button {\n\t\tbackground: var(--ck-color-widget-type-around-button-hover);\n\t}\n\n\t/*\n\t * Styles for the buttons when:\n\t * - the widget is selected,\n\t * - or the button is being hovered (regardless of the widget state).\n\t */\n\t&.ck-widget_selected > .ck-widget__type-around > .ck-widget__type-around__button,\n\t& > .ck-widget__type-around > .ck-widget__type-around__button:hover {\n\t\tbackground: var(--ck-color-widget-type-around-button-active);\n\n\t\t&::after {\n\t\t\twidth: calc(var(--ck-widget-type-around-button-size) - 2px);\n\t\t\theight: calc(var(--ck-widget-type-around-button-size) - 2px);\n\t\t\tborder-radius: 100px;\n\t\t\tbackground: linear-gradient(135deg, hsla(0,0%,100%,0) 0%, hsla(0,0%,100%,.3) 100%);\n\t\t}\n\t}\n\n\t/*\n\t * Styles for the "before" button when the widget has a selection handle. Because some space\n\t * is consumed by the handle, the button must be moved slightly to the right to let it breathe.\n\t */\n\t&.ck-widget_with-selection-handle > .ck-widget__type-around > .ck-widget__type-around__button_before {\n\t\tmargin-left: 20px;\n\t}\n\n\t/*\n\t * Styles for the horizontal "fake caret" which is displayed when the user navigates using the keyboard.\n\t */\n\t& .ck-widget__type-around__fake-caret {\n\t\tpointer-events: none;\n\t\theight: 1px;\n\t\tanimation: ck-widget-type-around-fake-caret-pulse linear 1s infinite normal forwards;\n\n\t\t/*\n\t\t * The semi-transparent-outline+background combo improves the contrast\n\t\t * when the background underneath the fake caret is dark.\n\t\t */\n\t\toutline: solid 1px hsla(0, 0%, 100%, .5);\n\t\tbackground: var(--ck-color-base-text);\n\t}\n\n\t/*\n\t * Styles of the widget when the "fake caret" is blinking (e.g. upon keyboard navigation).\n\t * Despite the widget being physically selected in the model, its outline should disappear.\n\t */\n\t&.ck-widget_selected {\n\t\t&.ck-widget_type-around_show-fake-caret_before,\n\t\t&.ck-widget_type-around_show-fake-caret_after {\n\t\t\toutline-color: transparent;\n\t\t}\n\t}\n\n\t&.ck-widget_type-around_show-fake-caret_before,\n\t&.ck-widget_type-around_show-fake-caret_after {\n\t\t/*\n\t\t * When the "fake caret" is visible we simulate that the widget is not selected\n\t\t * (despite being physically selected), so the outline color should be for the\n\t\t * unselected widget.\n\t\t */\n\t\t&.ck-widget_selected:hover {\n\t\t\toutline-color: var(--ck-color-widget-hover-border);\n\t\t}\n\n\t\t/*\n\t\t * Styles of the type around buttons when the "fake caret" is blinking (e.g. upon keyboard navigation).\n\t\t * In this state, the type around buttons would collide with the fake carets so they should disappear.\n\t\t */\n\t\t& > .ck-widget__type-around > .ck-widget__type-around__button {\n\t\t\t@mixin ck-widget-type-around-button-hidden;\n\t\t}\n\n\t\t/*\n\t\t * Fake horizontal caret integration with the selection handle. When the caret is visible, simply\n\t\t * hide the handle because it intersects with the caret (and does not make much sense anyway).\n\t\t */\n\t\t&.ck-widget_with-selection-handle {\n\t\t\t&.ck-widget_selected,\n\t\t\t&.ck-widget_selected:hover {\n\t\t\t\t& > .ck-widget__selection-handle {\n\t\t\t\t\topacity: 0\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t * Fake horizontal caret integration with the resize UI. When the caret is visible, simply\n\t\t * hide the resize UI because it creates too much noise. It can be visible when the user\n\t\t * hovers the widget, though.\n\t\t */\n\t\t&.ck-widget_selected.ck-widget_with-resizer > .ck-widget__resizer {\n\t\t\topacity: 0\n\t\t}\n\t}\n}\n\n/*\n * Styles for the "before" button when the widget has a selection handle in an RTL environment.\n * The selection handler is aligned to the right side of the widget so there is no need to create\n * additional space for it next to the "before" button.\n */\n.ck[dir="rtl"] .ck-widget.ck-widget_with-selection-handle .ck-widget__type-around > .ck-widget__type-around__button_before {\n\tmargin-left: 0;\n\tmargin-right: 20px;\n}\n\n/*\n * Hide type around buttons when the widget is selected as a child of a selected\n * nested editable (e.g. mulit-cell table selection).\n *\n * See https://github.com/ckeditor/ckeditor5/issues/7263.\n */\n.ck-editor__nested-editable.ck-editor__editable_selected {\n\t& .ck-widget {\n\t\t&.ck-widget_selected,\n\t\t&:hover {\n\t\t\t& > .ck-widget__type-around > .ck-widget__type-around__button {\n\t\t\t\t@mixin ck-widget-type-around-button-hidden;\n\t\t\t}\n\t\t}\n\t}\n}\n\n/*\n * Styles for the buttons when the widget is selected but the user clicked outside of the editor (blurred the editor).\n */\n.ck-editor__editable.ck-blurred .ck-widget.ck-widget_selected > .ck-widget__type-around > .ck-widget__type-around__button:not(:hover) {\n\tbackground: var(--ck-color-widget-type-around-button-blurred-editable);\n\n\t& svg * {\n\t\tstroke: hsl(0,0%,60%);\n\t}\n}\n\n@keyframes ck-widget-type-around-arrow-dash {\n\t0% {\n\t\tstroke-dashoffset: 10;\n\t}\n\t20%, 100% {\n\t\tstroke-dashoffset: 0;\n\t}\n}\n\n@keyframes ck-widget-type-around-arrow-tip-dash {\n\t0%, 20% {\n\t\tstroke-dashoffset: 7;\n\t}\n\t40%, 100% {\n\t\tstroke-dashoffset: 0;\n\t}\n}\n\n@keyframes ck-widget-type-around-button-sonar {\n\t0% {\n\t\tbox-shadow: 0 0 0 0 hsla(var(--ck-color-focus-border-coordinates), var(--ck-color-widget-type-around-button-radar-start-alpha));\n\t}\n\t50% {\n\t\tbox-shadow: 0 0 0 5px hsla(var(--ck-color-focus-border-coordinates), var(--ck-color-widget-type-around-button-radar-end-alpha));\n\t}\n\t100% {\n\t\tbox-shadow: 0 0 0 5px hsla(var(--ck-color-focus-border-coordinates), var(--ck-color-widget-type-around-button-radar-start-alpha));\n\t}\n}\n\n@keyframes ck-widget-type-around-fake-caret-pulse {\n\t0% {\n\t\topacity: 1;\n\t}\n\t49% {\n\t\topacity: 1;\n\t}\n\t50% {\n\t\topacity: 0;\n\t}\n\t99% {\n\t\topacity: 0;\n\t}\n\t100% {\n\t\topacity: 1;\n\t}\n}\n'],sourceRoot:""}]);e["a"]=a},function(t,e,n){"use strict";var o=n(2);var i=n.n(o);var r=n(3);var s=n.n(r);var a=s()(i.a);a.push([t.i,":root{--ck-color-resizer:var(--ck-color-focus-border);--ck-resizer-size:10px;--ck-resizer-border-width:1px;--ck-resizer-border-radius:2px;--ck-resizer-offset:calc(var(--ck-resizer-size)/-2 - 2px);--ck-resizer-tooltip-offset:10px;--ck-color-resizer-tooltip-background:#262626;--ck-color-resizer-tooltip-text:#f2f2f2}.ck .ck-widget,.ck .ck-widget.ck-widget_with-selection-handle{position:relative}.ck .ck-widget.ck-widget_with-selection-handle .ck-widget__selection-handle{position:absolute}.ck .ck-widget.ck-widget_with-selection-handle .ck-widget__selection-handle .ck-icon{display:block}.ck .ck-widget.ck-widget_with-selection-handle.ck-widget_selected .ck-widget__selection-handle,.ck .ck-widget.ck-widget_with-selection-handle:hover .ck-widget__selection-handle{visibility:visible}.ck .ck-size-view{background:var(--ck-color-resizer-tooltip-background);color:var(--ck-color-resizer-tooltip-text);border:1px solid var(--ck-color-resizer-tooltip-text);border-radius:var(--ck-resizer-border-radius);font-size:var(--ck-font-size-tiny);display:block;padding:var(--ck-spacing-small)}.ck .ck-size-view.ck-orientation-bottom-left,.ck .ck-size-view.ck-orientation-bottom-right,.ck .ck-size-view.ck-orientation-top-left,.ck .ck-size-view.ck-orientation-top-right{position:absolute}.ck .ck-size-view.ck-orientation-top-left{top:var(--ck-resizer-tooltip-offset);left:var(--ck-resizer-tooltip-offset)}.ck .ck-size-view.ck-orientation-top-right{top:var(--ck-resizer-tooltip-offset);right:var(--ck-resizer-tooltip-offset)}.ck .ck-size-view.ck-orientation-bottom-right{bottom:var(--ck-resizer-tooltip-offset);right:var(--ck-resizer-tooltip-offset)}.ck .ck-size-view.ck-orientation-bottom-left{bottom:var(--ck-resizer-tooltip-offset);left:var(--ck-resizer-tooltip-offset)}:root{--ck-widget-outline-thickness:3px;--ck-widget-handler-icon-size:16px;--ck-widget-handler-animation-duration:200ms;--ck-widget-handler-animation-curve:ease;--ck-color-widget-blurred-border:#dedede;--ck-color-widget-hover-border:#ffc83d;--ck-color-widget-editable-focus-background:var(--ck-color-base-background);--ck-color-widget-drag-handler-icon-color:var(--ck-color-base-background)}.ck .ck-widget{outline-width:var(--ck-widget-outline-thickness);outline-style:solid;outline-color:transparent;transition:outline-color var(--ck-widget-handler-animation-duration) var(--ck-widget-handler-animation-curve)}.ck .ck-widget.ck-widget_selected,.ck .ck-widget.ck-widget_selected:hover{outline:var(--ck-widget-outline-thickness) solid var(--ck-color-focus-border)}.ck .ck-widget:hover{outline-color:var(--ck-color-widget-hover-border)}.ck .ck-editor__nested-editable{border:1px solid transparent}.ck .ck-editor__nested-editable.ck-editor__nested-editable_focused,.ck .ck-editor__nested-editable:focus{outline:none;border:var(--ck-focus-ring);box-shadow:var(--ck-inner-shadow),0 0;background-color:var(--ck-color-widget-editable-focus-background)}.ck .ck-widget.ck-widget_with-selection-handle .ck-widget__selection-handle{padding:4px;box-sizing:border-box;background-color:transparent;opacity:0;transition:background-color var(--ck-widget-handler-animation-duration) var(--ck-widget-handler-animation-curve),visibility var(--ck-widget-handler-animation-duration) var(--ck-widget-handler-animation-curve),opacity var(--ck-widget-handler-animation-duration) var(--ck-widget-handler-animation-curve);border-radius:var(--ck-border-radius) var(--ck-border-radius) 0 0;transform:translateY(-100%);left:calc(0px - var(--ck-widget-outline-thickness))}.ck .ck-widget.ck-widget_with-selection-handle .ck-widget__selection-handle .ck-icon{width:var(--ck-widget-handler-icon-size);height:var(--ck-widget-handler-icon-size);color:var(--ck-color-widget-drag-handler-icon-color)}.ck .ck-widget.ck-widget_with-selection-handle .ck-widget__selection-handle .ck-icon .ck-icon__selected-indicator{opacity:0;transition:opacity .3s var(--ck-widget-handler-animation-curve)}.ck .ck-widget.ck-widget_with-selection-handle .ck-widget__selection-handle:hover .ck-icon .ck-icon__selected-indicator{opacity:1}.ck .ck-widget.ck-widget_with-selection-handle:hover .ck-widget__selection-handle{opacity:1;background-color:var(--ck-color-widget-hover-border)}.ck .ck-widget.ck-widget_with-selection-handle.ck-widget_selected .ck-widget__selection-handle,.ck .ck-widget.ck-widget_with-selection-handle.ck-widget_selected:hover .ck-widget__selection-handle{opacity:1;background-color:var(--ck-color-focus-border)}.ck .ck-widget.ck-widget_with-selection-handle.ck-widget_selected .ck-widget__selection-handle .ck-icon .ck-icon__selected-indicator,.ck .ck-widget.ck-widget_with-selection-handle.ck-widget_selected:hover .ck-widget__selection-handle .ck-icon .ck-icon__selected-indicator{opacity:1}.ck[dir=rtl] .ck-widget.ck-widget_with-selection-handle .ck-widget__selection-handle{left:auto;right:calc(0px - var(--ck-widget-outline-thickness))}.ck.ck-editor__editable.ck-read-only .ck-widget{transition:none}.ck.ck-editor__editable.ck-read-only .ck-widget:not(.ck-widget_selected){--ck-widget-outline-thickness:0px}.ck.ck-editor__editable.ck-read-only .ck-widget.ck-widget_with-selection-handle .ck-widget__selection-handle,.ck.ck-editor__editable.ck-read-only .ck-widget.ck-widget_with-selection-handle .ck-widget__selection-handle:hover{background:var(--ck-color-widget-blurred-border)}.ck.ck-editor__editable.ck-blurred .ck-widget.ck-widget_selected,.ck.ck-editor__editable.ck-blurred .ck-widget.ck-widget_selected:hover{outline-color:var(--ck-color-widget-blurred-border)}.ck.ck-editor__editable.ck-blurred .ck-widget.ck-widget_selected.ck-widget_with-selection-handle .ck-widget__selection-handle,.ck.ck-editor__editable.ck-blurred .ck-widget.ck-widget_selected.ck-widget_with-selection-handle .ck-widget__selection-handle:hover,.ck.ck-editor__editable.ck-blurred .ck-widget.ck-widget_selected:hover.ck-widget_with-selection-handle .ck-widget__selection-handle,.ck.ck-editor__editable.ck-blurred .ck-widget.ck-widget_selected:hover.ck-widget_with-selection-handle .ck-widget__selection-handle:hover{background:var(--ck-color-widget-blurred-border)}.ck.ck-editor__editable>.ck-widget.ck-widget_with-selection-handle:first-child,.ck.ck-editor__editable blockquote>.ck-widget.ck-widget_with-selection-handle:first-child{margin-top:calc(1em + var(--ck-widget-handler-icon-size))}","",{version:3,sources:["webpack://./node_modules/@ckeditor/ckeditor5-widget/theme/widget.css","webpack://./node_modules/@ckeditor/ckeditor5-theme-lark/theme/ckeditor5-widget/widget.css","webpack://./node_modules/@ckeditor/ckeditor5-theme-lark/theme/mixins/_focus.css","webpack://./node_modules/@ckeditor/ckeditor5-theme-lark/theme/mixins/_shadow.css"],names:[],mappings:"AAKA,MACC,+CAAgD,CAChD,sBAAuB,CACvB,6BAA8B,CAC9B,8BAA+B,CAG/B,yDAAiE,CAEjE,gCAAiC,CACjC,6CAAsD,CACtD,uCACD,CAOA,8DAEC,iBAuBD,CArBC,4EACC,iBAOD,CALC,qFAGC,aACD,CAWD,iLACC,kBACD,CAGD,kBACC,qDAAsD,CACtD,0CAA2C,CAC3C,qDAAsD,CACtD,6CAA8C,CAC9C,kCAAmC,CACnC,aAAc,CACd,+BA4BD,CA1BC,gLAIC,iBACD,CAEA,0CACC,oCAAuC,CACvC,qCACD,CAEA,2CACC,oCAAuC,CACvC,sCACD,CAEA,8CACC,uCAA0C,CAC1C,sCACD,CAEA,6CACC,uCAA0C,CAC1C,qCACD,CC7ED,MACC,iCAAkC,CAClC,kCAAmC,CACnC,4CAA6C,CAC7C,wCAAyC,CAEzC,wCAAiD,CACjD,sCAAkD,CAClD,2EAA4E,CAC5E,yEACD,CAEA,eACC,gDAAiD,CACjD,mBAAoB,CACpB,yBAA0B,CAC1B,6GAUD,CARC,0EAEC,6EACD,CAEA,qBACC,iDACD,CAGD,gCACC,4BAWD,CAPC,yGC/BA,YAAa,CACb,2BAA2B,CCF3B,qCAA8B,CFqC7B,iEACD,CAIA,4EACC,WAAY,CACZ,qBAAsB,CAGtB,4BAA6B,CAC7B,SAAU,CAMV,6SAG6F,CAG7F,iEAAkE,CAGlE,2BAA4B,CAC5B,mDAqBD,CAnBC,qFAEC,wCAAyC,CACzC,yCAA0C,CAC1C,oDASD,CANC,kHACC,SAAU,CAGV,+DACD,CAID,wHACC,SACD,CAID,kFACC,SAAU,CACV,oDACD,CAKC,oMACC,SAAU,CACV,6CAMD,CAHC,gRACC,SACD,CAOH,qFACC,SAAU,CACV,oDACD,CAGA,gDAEC,eAkBD,CAhBC,yEAOC,iCACD,CAGC,gOAEC,gDACD,CAOD,wIAEC,mDAQD,CALE,ghBAEC,gDACD,CAKH,yKAOC,yDACD",sourcesContent:["/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n:root {\n\t--ck-color-resizer: var(--ck-color-focus-border);\n\t--ck-resizer-size: 10px;\n\t--ck-resizer-border-width: 1px;\n\t--ck-resizer-border-radius: 2px;\n\n\t/* Set the resizer with a 50% offset. */\n\t--ck-resizer-offset: calc( ( var(--ck-resizer-size) / -2 ) - 2px);\n\n\t--ck-resizer-tooltip-offset: 10px;\n\t--ck-color-resizer-tooltip-background: hsl(0, 0%, 15%);\n\t--ck-color-resizer-tooltip-text: hsl(0, 0%, 95%);\n}\n\n.ck .ck-widget {\n\t/* This is neccessary for type around UI to be positioned properly. */\n\tposition: relative;\n}\n\n.ck .ck-widget.ck-widget_with-selection-handle {\n\t/* Make the widget wrapper a relative positioning container for the drag handle. */\n\tposition: relative;\n\n\t& .ck-widget__selection-handle {\n\t\tposition: absolute;\n\n\t\t& .ck-icon {\n\t\t\t/* Make sure the icon in not a subject to font-size or line-height to avoid\n\t\t\tunnecessary spacing around it. */\n\t\t\tdisplay: block;\n\t\t}\n\t}\n\n\t/* Show the selection handle on mouse hover over the widget. */\n\t&:hover {\n\t\t& .ck-widget__selection-handle {\n\t\t\tvisibility: visible;\n\t\t}\n\t}\n\n\t/* Show the selection handle when the widget is selected. */\n\t&.ck-widget_selected .ck-widget__selection-handle {\n\t\tvisibility: visible;\n\t}\n}\n\n.ck .ck-size-view {\n\tbackground: var(--ck-color-resizer-tooltip-background);\n\tcolor: var(--ck-color-resizer-tooltip-text);\n\tborder: 1px solid var(--ck-color-resizer-tooltip-text);\n\tborder-radius: var(--ck-resizer-border-radius);\n\tfont-size: var(--ck-font-size-tiny);\n\tdisplay: block;\n\tpadding: var(--ck-spacing-small);\n\n\t&.ck-orientation-top-left,\n\t&.ck-orientation-top-right,\n\t&.ck-orientation-bottom-right,\n\t&.ck-orientation-bottom-left {\n\t\tposition: absolute;\n\t}\n\n\t&.ck-orientation-top-left {\n\t\ttop: var( --ck-resizer-tooltip-offset );\n\t\tleft: var( --ck-resizer-tooltip-offset );\n\t}\n\n\t&.ck-orientation-top-right {\n\t\ttop: var( --ck-resizer-tooltip-offset );\n\t\tright: var( --ck-resizer-tooltip-offset );\n\t}\n\n\t&.ck-orientation-bottom-right {\n\t\tbottom: var( --ck-resizer-tooltip-offset );\n\t\tright: var( --ck-resizer-tooltip-offset );\n\t}\n\n\t&.ck-orientation-bottom-left {\n\t\tbottom: var( --ck-resizer-tooltip-offset );\n\t\tleft: var( --ck-resizer-tooltip-offset );\n\t}\n}\n",'/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n@import "../mixins/_focus.css";\n@import "../mixins/_shadow.css";\n\n:root {\n\t--ck-widget-outline-thickness: 3px;\n\t--ck-widget-handler-icon-size: 16px;\n\t--ck-widget-handler-animation-duration: 200ms;\n\t--ck-widget-handler-animation-curve: ease;\n\n\t--ck-color-widget-blurred-border: hsl(0, 0%, 87%);\n\t--ck-color-widget-hover-border: hsl(43, 100%, 62%);\n\t--ck-color-widget-editable-focus-background: var(--ck-color-base-background);\n\t--ck-color-widget-drag-handler-icon-color: var(--ck-color-base-background);\n}\n\n.ck .ck-widget {\n\toutline-width: var(--ck-widget-outline-thickness);\n\toutline-style: solid;\n\toutline-color: transparent;\n\ttransition: outline-color var(--ck-widget-handler-animation-duration) var(--ck-widget-handler-animation-curve);\n\n\t&.ck-widget_selected,\n\t&.ck-widget_selected:hover {\n\t\toutline: var(--ck-widget-outline-thickness) solid var(--ck-color-focus-border);\n\t}\n\n\t&:hover {\n\t\toutline-color: var(--ck-color-widget-hover-border);\n\t}\n}\n\n.ck .ck-editor__nested-editable {\n\tborder: 1px solid transparent;\n\n\t/* The :focus style is applied before .ck-editor__nested-editable_focused class is rendered in the view.\n\tThese styles show a different border for a blink of an eye, so `:focus` need to have same styles applied. */\n\t&.ck-editor__nested-editable_focused,\n\t&:focus {\n\t\t@mixin ck-focus-ring;\n\t\t@mixin ck-box-shadow var(--ck-inner-shadow);\n\n\t\tbackground-color: var(--ck-color-widget-editable-focus-background);\n\t}\n}\n\n.ck .ck-widget.ck-widget_with-selection-handle {\n\t& .ck-widget__selection-handle {\n\t\tpadding: 4px;\n\t\tbox-sizing: border-box;\n\n\t\t/* Background and opacity will be animated as the handler shows up or the widget gets selected. */\n\t\tbackground-color: transparent;\n\t\topacity: 0;\n\n\t\t/* Transition:\n\t\t * background-color for the .ck-widget_selected state change,\n\t\t * visibility for hiding the handler,\n\t\t * opacity for the proper look of the icon when the handler disappears. */\n\t\ttransition:\n\t\t\tbackground-color var(--ck-widget-handler-animation-duration) var(--ck-widget-handler-animation-curve),\n\t\t\tvisibility var(--ck-widget-handler-animation-duration) var(--ck-widget-handler-animation-curve),\n\t\t\topacity var(--ck-widget-handler-animation-duration) var(--ck-widget-handler-animation-curve);\n\n\t\t/* Make only top corners round. */\n\t\tborder-radius: var(--ck-border-radius) var(--ck-border-radius) 0 0;\n\n\t\t/* Place the drag handler outside the widget wrapper. */\n\t\ttransform: translateY(-100%);\n\t\tleft: calc(0px - var(--ck-widget-outline-thickness));\n\n\t\t& .ck-icon {\n\t\t\t/* Make sure the dimensions of the icon are independent of the fon-size of the content. */\n\t\t\twidth: var(--ck-widget-handler-icon-size);\n\t\t\theight: var(--ck-widget-handler-icon-size);\n\t\t\tcolor: var(--ck-color-widget-drag-handler-icon-color);\n\n\t\t\t/* The "selected" part of the icon is invisible by default */\n\t\t\t& .ck-icon__selected-indicator {\n\t\t\t\topacity: 0;\n\n\t\t\t\t/* Note: The animation is longer on purpose. Simply feels better. */\n\t\t\t\ttransition: opacity 300ms var(--ck-widget-handler-animation-curve);\n\t\t\t}\n\t\t}\n\n\t\t/* Advertise using the look of the icon that once clicked the handler, the widget will be selected. */\n\t\t&:hover .ck-icon .ck-icon__selected-indicator {\n\t\t\topacity: 1;\n\t\t}\n\t}\n\n\t/* Show the selection handler on mouse hover over the widget. */\n\t&:hover .ck-widget__selection-handle {\n\t\topacity: 1;\n\t\tbackground-color: var(--ck-color-widget-hover-border);\n\t}\n\n\t/* Show the selection handler when the widget is selected. */\n\t&.ck-widget_selected,\n\t&.ck-widget_selected:hover {\n\t\t& .ck-widget__selection-handle {\n\t\t\topacity: 1;\n\t\t\tbackground-color: var(--ck-color-focus-border);\n\n\t\t\t/* When the widget is selected, notify the user using the proper look of the icon. */\n\t\t\t& .ck-icon .ck-icon__selected-indicator {\n\t\t\t\topacity: 1;\n\t\t\t}\n\t\t}\n\t}\n}\n\n/* In a RTL environment, align the selection handler to the right side of the widget */\n/* stylelint-disable-next-line no-descending-specificity */\n.ck[dir="rtl"] .ck-widget.ck-widget_with-selection-handle .ck-widget__selection-handle {\n\tleft: auto;\n\tright: calc(0px - var(--ck-widget-outline-thickness));\n}\n\n/* https://github.com/ckeditor/ckeditor5/issues/6415 */\n.ck.ck-editor__editable.ck-read-only .ck-widget {\n\t/* Prevent the :hover outline from showing up because of the used outline-color transition. */\n\ttransition: none;\n\n\t&:not(.ck-widget_selected) {\n\t\t/* Disable visual effects of hover/active widget when CKEditor is in readOnly mode.\n\t\t * See: https://github.com/ckeditor/ckeditor5/issues/1261\n\t\t *\n\t\t * Leave the unit because this custom property is used in calc() by other features.\n\t\t * See: https://github.com/ckeditor/ckeditor5/issues/6775\n\t\t */\n\t\t--ck-widget-outline-thickness: 0px;\n\t}\n\n\t&.ck-widget_with-selection-handle {\n\t\t& .ck-widget__selection-handle,\n\t\t& .ck-widget__selection-handle:hover {\n\t\t\tbackground: var(--ck-color-widget-blurred-border);\n\t\t}\n\t}\n}\n\n/* Style the widget when it\'s selected but the editable it belongs to lost focus. */\n/* stylelint-disable-next-line no-descending-specificity */\n.ck.ck-editor__editable.ck-blurred .ck-widget {\n\t&.ck-widget_selected,\n\t&.ck-widget_selected:hover {\n\t\toutline-color: var(--ck-color-widget-blurred-border);\n\n\t\t&.ck-widget_with-selection-handle {\n\t\t\t& .ck-widget__selection-handle,\n\t\t\t& .ck-widget__selection-handle:hover {\n\t\t\t\tbackground: var(--ck-color-widget-blurred-border);\n\t\t\t}\n\t\t}\n\t}\n}\n\n.ck.ck-editor__editable > .ck-widget.ck-widget_with-selection-handle:first-child,\n.ck.ck-editor__editable blockquote > .ck-widget.ck-widget_with-selection-handle:first-child {\n\t/* Do not crop selection handler if a widget is a first-child in the blockquote or in the root editable.\n\tIn fact, anything with overflow: hidden.\n\thttps://github.com/ckeditor/ckeditor5-block-quote/issues/28\n\thttps://github.com/ckeditor/ckeditor5-widget/issues/44\n\thttps://github.com/ckeditor/ckeditor5-widget/issues/66 */\n\tmargin-top: calc(1em + var(--ck-widget-handler-icon-size));\n}\n',"/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * A visual style of focused element's border.\n */\n@define-mixin ck-focus-ring {\n\t/* Disable native outline. */\n\toutline: none;\n\tborder: var(--ck-focus-ring)\n}\n","/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * A helper to combine multiple shadows.\n */\n@define-mixin ck-box-shadow $shadowA, $shadowB: 0 0 {\n\tbox-shadow: $shadowA, $shadowB;\n}\n\n/**\n * Gives an element a drop shadow so it looks like a floating panel.\n */\n@define-mixin ck-drop-shadow {\n\t@mixin ck-box-shadow var(--ck-drop-shadow);\n}\n"],sourceRoot:""}]);e["a"]=a},function(t,e,n){"use strict";var o=n(2);var i=n.n(o);var r=n(3);var s=n.n(r);var a=s()(i.a);a.push([t.i,".ck.ck-labeled-field-view>.ck.ck-labeled-field-view__input-wrapper{display:flex;position:relative}.ck.ck-labeled-field-view .ck.ck-label{display:block;position:absolute}:root{--ck-labeled-field-view-transition:.1s cubic-bezier(0,0,0.24,0.95);--ck-labeled-field-empty-unfocused-max-width:100% - 2 * var(--ck-spacing-medium);--ck-color-labeled-field-label-background:var(--ck-color-base-background)}.ck.ck-labeled-field-view{border-radius:0}.ck-rounded-corners .ck.ck-labeled-field-view,.ck.ck-labeled-field-view.ck-rounded-corners{border-radius:var(--ck-border-radius)}.ck.ck-labeled-field-view>.ck.ck-labeled-field-view__input-wrapper{width:100%}.ck.ck-labeled-field-view>.ck.ck-labeled-field-view__input-wrapper>.ck.ck-label{top:0}[dir=ltr] .ck.ck-labeled-field-view>.ck.ck-labeled-field-view__input-wrapper>.ck.ck-label{left:0}[dir=rtl] .ck.ck-labeled-field-view>.ck.ck-labeled-field-view__input-wrapper>.ck.ck-label{right:0}.ck.ck-labeled-field-view>.ck.ck-labeled-field-view__input-wrapper>.ck.ck-label{pointer-events:none;transform-origin:0 0;transform:translate(var(--ck-spacing-medium),-6px) scale(.75);background:var(--ck-color-labeled-field-label-background);padding:0 calc(var(--ck-font-size-tiny)*0.5);line-height:normal;font-weight:400;text-overflow:ellipsis;overflow:hidden;max-width:100%;transition:transform var(--ck-labeled-field-view-transition),padding var(--ck-labeled-field-view-transition),background var(--ck-labeled-field-view-transition)}.ck.ck-labeled-field-view.ck-error .ck-input:not([readonly])+.ck.ck-label,.ck.ck-labeled-field-view.ck-error>.ck.ck-labeled-field-view__input-wrapper>.ck.ck-label{color:var(--ck-color-base-error)}.ck.ck-labeled-field-view .ck-labeled-field-view__status{font-size:var(--ck-font-size-small);margin-top:var(--ck-spacing-small);white-space:normal}.ck.ck-labeled-field-view .ck-labeled-field-view__status.ck-labeled-field-view__status_error{color:var(--ck-color-base-error)}.ck.ck-labeled-field-view.ck-disabled>.ck.ck-labeled-field-view__input-wrapper>.ck.ck-label,.ck.ck-labeled-field-view.ck-labeled-field-view_empty:not(.ck-labeled-field-view_focused)>.ck.ck-labeled-field-view__input-wrapper>.ck.ck-label{color:var(--ck-color-input-disabled-text)}[dir=ltr] .ck.ck-labeled-field-view.ck-disabled>.ck.ck-labeled-field-view__input-wrapper>.ck.ck-label,[dir=ltr] .ck.ck-labeled-field-view.ck-labeled-field-view_empty:not(.ck-labeled-field-view_focused):not(.ck-labeled-field-view_placeholder)>.ck.ck-labeled-field-view__input-wrapper>.ck.ck-label{transform:translate(var(--ck-spacing-medium),calc(var(--ck-font-size-base)*0.6)) scale(1)}[dir=rtl] .ck.ck-labeled-field-view.ck-disabled>.ck.ck-labeled-field-view__input-wrapper>.ck.ck-label,[dir=rtl] .ck.ck-labeled-field-view.ck-labeled-field-view_empty:not(.ck-labeled-field-view_focused):not(.ck-labeled-field-view_placeholder)>.ck.ck-labeled-field-view__input-wrapper>.ck.ck-label{transform:translate(calc(var(--ck-spacing-medium)*-1),calc(var(--ck-font-size-base)*0.6)) scale(1)}.ck.ck-labeled-field-view.ck-disabled>.ck.ck-labeled-field-view__input-wrapper>.ck.ck-label,.ck.ck-labeled-field-view.ck-labeled-field-view_empty:not(.ck-labeled-field-view_focused):not(.ck-labeled-field-view_placeholder)>.ck.ck-labeled-field-view__input-wrapper>.ck.ck-label{max-width:calc(var(--ck-labeled-field-empty-unfocused-max-width));background:transparent;padding:0}.ck.ck-labeled-field-view>.ck.ck-labeled-field-view__input-wrapper>.ck-dropdown>.ck.ck-button{background:transparent}.ck.ck-labeled-field-view.ck-labeled-field-view_empty>.ck.ck-labeled-field-view__input-wrapper>.ck-dropdown>.ck-button>.ck-button__label{opacity:0}.ck.ck-labeled-field-view.ck-labeled-field-view_empty:not(.ck-labeled-field-view_focused):not(.ck-labeled-field-view_placeholder)>.ck.ck-labeled-field-view__input-wrapper>.ck-dropdown+.ck-label{max-width:calc(var(--ck-labeled-field-empty-unfocused-max-width) - var(--ck-dropdown-arrow-size) - var(--ck-spacing-standard))}","",{version:3,sources:["webpack://./node_modules/@ckeditor/ckeditor5-ui/theme/components/labeledfield/labeledfieldview.css","webpack://./node_modules/@ckeditor/ckeditor5-theme-lark/theme/ckeditor5-ui/components/labeledfield/labeledfieldview.css","webpack://./node_modules/@ckeditor/ckeditor5-theme-lark/theme/mixins/_rounded.css"],names:[],mappings:"AAMC,mEACC,YAAa,CACb,iBACD,CAEA,uCACC,aAAc,CACd,iBACD,CCND,MACC,kEAAsE,CACtE,gFAAiF,CACjF,yEACD,CAEA,0BCHC,eD4GD,CAzGA,2FCCE,qCDwGF,CAtGC,mEACC,UAmCD,CAjCC,gFACC,KA+BD,CAhCA,0FAIE,MA4BF,CAhCA,0FAQE,OAwBF,CAhCA,gFAWC,mBAAoB,CACpB,oBAAqB,CAGrB,6DAA+D,CAE/D,yDAA0D,CAC1D,4CAA8C,CAC9C,kBAAoB,CACpB,eAAmB,CAGnB,sBAAuB,CACvB,eAAgB,CAEhB,cAAe,CAEf,+JAID,CAQA,mKACC,gCACD,CAGD,yDACC,mCAAoC,CACpC,kCAAmC,CAInC,kBAKD,CAHC,6FACC,gCACD,CAID,4OAEC,yCACD,CAIA,wSAGE,yFAYF,CAfA,wSAOE,kGAQF,CAfA,oRAWC,iEAAkE,CAElE,sBAAuB,CACvB,SACD,CAKA,8FACC,sBACD,CAGA,yIACC,SACD,CAGA,kMACC,8HACD",sourcesContent:["/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n.ck.ck-labeled-field-view {\n\t& > .ck.ck-labeled-field-view__input-wrapper {\n\t\tdisplay: flex;\n\t\tposition: relative;\n\t}\n\n\t& .ck.ck-label {\n\t\tdisplay: block;\n\t\tposition: absolute;\n\t}\n}\n",'/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n@import "@ckeditor/ckeditor5-ui/theme/mixins/_dir.css";\n@import "../../../mixins/_rounded.css";\n\n:root {\n\t--ck-labeled-field-view-transition: .1s cubic-bezier(0, 0, 0.24, 0.95);\n\t--ck-labeled-field-empty-unfocused-max-width: 100% - 2 * var(--ck-spacing-medium);\n\t--ck-color-labeled-field-label-background: var(--ck-color-base-background);\n}\n\n.ck.ck-labeled-field-view {\n\t@mixin ck-rounded-corners;\n\n\t& > .ck.ck-labeled-field-view__input-wrapper {\n\t\twidth: 100%;\n\n\t\t& > .ck.ck-label {\n\t\t\ttop: 0px;\n\n\t\t\t@mixin ck-dir ltr {\n\t\t\t\tleft: 0px;\n\t\t\t}\n\n\t\t\t@mixin ck-dir rtl {\n\t\t\t\tright: 0px;\n\t\t\t}\n\n\t\t\tpointer-events: none;\n\t\t\ttransform-origin: 0 0;\n\n\t\t\t/* By default, display the label scaled down above the field. */\n\t\t\ttransform: translate(var(--ck-spacing-medium), -6px) scale(.75);\n\n\t\t\tbackground: var(--ck-color-labeled-field-label-background);\n\t\t\tpadding: 0 calc(.5 * var(--ck-font-size-tiny));\n\t\t\tline-height: initial;\n\t\t\tfont-weight: normal;\n\n\t\t\t/* Prevent overflow when the label is longer than the input */\n\t\t\ttext-overflow: ellipsis;\n\t\t\toverflow: hidden;\n\n\t\t\tmax-width: 100%;\n\n\t\t\ttransition:\n\t\t\t\ttransform var(--ck-labeled-field-view-transition),\n\t\t\t\tpadding var(--ck-labeled-field-view-transition),\n\t\t\t\tbackground var(--ck-labeled-field-view-transition);\n\t\t}\n\t}\n\n\t&.ck-error {\n\t\t& > .ck.ck-labeled-field-view__input-wrapper > .ck.ck-label {\n\t\t\tcolor: var(--ck-color-base-error);\n\t\t}\n\n\t\t& .ck-input:not([readonly]) + .ck.ck-label {\n\t\t\tcolor: var(--ck-color-base-error);\n\t\t}\n\t}\n\n\t& .ck-labeled-field-view__status {\n\t\tfont-size: var(--ck-font-size-small);\n\t\tmargin-top: var(--ck-spacing-small);\n\n\t\t/* Let the info wrap to the next line to avoid stretching the layout horizontally.\n\t\tThe status could be very long. */\n\t\twhite-space: normal;\n\n\t\t&.ck-labeled-field-view__status_error {\n\t\t\tcolor: var(--ck-color-base-error);\n\t\t}\n\t}\n\n\t/* Disabled fields and fields that have no focus should fade out. */\n\t&.ck-disabled > .ck.ck-labeled-field-view__input-wrapper > .ck.ck-label,\n\t&.ck-labeled-field-view_empty:not(.ck-labeled-field-view_focused) > .ck.ck-labeled-field-view__input-wrapper > .ck.ck-label {\n\t\tcolor: var(--ck-color-input-disabled-text);\n\t}\n\n\t/* Fields that are disabled or not focused and without a placeholder should have full-sized labels. */\n\t/* stylelint-disable-next-line no-descending-specificity */\n\t&.ck-disabled > .ck.ck-labeled-field-view__input-wrapper > .ck.ck-label,\n\t&.ck-labeled-field-view_empty:not(.ck-labeled-field-view_focused):not(.ck-labeled-field-view_placeholder) > .ck.ck-labeled-field-view__input-wrapper > .ck.ck-label {\n\t\t@mixin ck-dir ltr {\n\t\t\ttransform: translate(var(--ck-spacing-medium), calc(0.6 * var(--ck-font-size-base))) scale(1);\n\t\t}\n\n\t\t@mixin ck-dir rtl {\n\t\t\ttransform: translate(calc(-1 * var(--ck-spacing-medium)), calc(0.6 * var(--ck-font-size-base))) scale(1);\n\t\t}\n\n\t\t/* Compensate for the default translate position. */\n\t\tmax-width: calc(var(--ck-labeled-field-empty-unfocused-max-width));\n\n\t\tbackground: transparent;\n\t\tpadding: 0;\n\t}\n\n\t/*------ DropdownView integration ----------------------------------------------------------------------------------- */\n\n\t/* Make sure dropdown\' background color in any of dropdown\'s state does not collide with labeled field. */\n\t& > .ck.ck-labeled-field-view__input-wrapper > .ck-dropdown > .ck.ck-button {\n\t\tbackground: transparent;\n\t}\n\n\t/* When the dropdown is "empty", the labeled field label replaces its label. */\n\t&.ck-labeled-field-view_empty > .ck.ck-labeled-field-view__input-wrapper > .ck-dropdown > .ck-button > .ck-button__label {\n\t\topacity: 0;\n\t}\n\n\t/* Make sure the label of the empty, unfocused input does not cover the dropdown arrow. */\n\t&.ck-labeled-field-view_empty:not(.ck-labeled-field-view_focused):not(.ck-labeled-field-view_placeholder) > .ck.ck-labeled-field-view__input-wrapper > .ck-dropdown + .ck-label {\n\t\tmax-width: calc(var(--ck-labeled-field-empty-unfocused-max-width) - var(--ck-dropdown-arrow-size) - var(--ck-spacing-standard));\n\t}\n}\n',"/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * Implements rounded corner interface for .ck-rounded-corners class.\n *\n * @see $ck-border-radius\n */\n@define-mixin ck-rounded-corners {\n\tborder-radius: 0;\n\n\t@nest .ck-rounded-corners &,\n\t&.ck-rounded-corners {\n\t\tborder-radius: var(--ck-border-radius);\n\t\t@mixin-content;\n\t}\n}\n"],sourceRoot:""}]);e["a"]=a},function(t,e,n){"use strict";var o=n(2);var i=n.n(o);var r=n(3);var s=n.n(r);var a=s()(i.a);a.push([t.i,":root{--ck-input-text-width:18em}.ck.ck-input-text{border-radius:0}.ck-rounded-corners .ck.ck-input-text,.ck.ck-input-text.ck-rounded-corners{border-radius:var(--ck-border-radius)}.ck.ck-input-text{background:var(--ck-color-input-background);border:1px solid var(--ck-color-input-border);padding:var(--ck-spacing-extra-tiny) var(--ck-spacing-medium);min-width:var(--ck-input-text-width);min-height:var(--ck-ui-component-min-height);transition:box-shadow .1s ease-in-out,border .1s ease-in-out}.ck.ck-input-text:focus{outline:none;border:var(--ck-focus-ring);box-shadow:var(--ck-focus-outer-shadow),0 0}.ck.ck-input-text[readonly]{border:1px solid var(--ck-color-input-disabled-border);background:var(--ck-color-input-disabled-background);color:var(--ck-color-input-disabled-text)}.ck.ck-input-text[readonly]:focus{box-shadow:var(--ck-focus-disabled-outer-shadow),0 0}.ck.ck-input-text.ck-error{border-color:var(--ck-color-input-error-border);animation:ck-text-input-shake .3s ease both}.ck.ck-input-text.ck-error:focus{box-shadow:var(--ck-focus-error-outer-shadow),0 0}@keyframes ck-text-input-shake{20%{transform:translateX(-2px)}40%{transform:translateX(2px)}60%{transform:translateX(-1px)}80%{transform:translateX(1px)}}","",{version:3,sources:["webpack://./node_modules/@ckeditor/ckeditor5-theme-lark/theme/ckeditor5-ui/components/inputtext/inputtext.css","webpack://./node_modules/@ckeditor/ckeditor5-theme-lark/theme/mixins/_rounded.css","webpack://./node_modules/@ckeditor/ckeditor5-theme-lark/theme/mixins/_focus.css","webpack://./node_modules/@ckeditor/ckeditor5-theme-lark/theme/mixins/_shadow.css"],names:[],mappings:"AASA,MACC,0BACD,CAEA,kBCFC,eDwCD,CAtCA,2ECEE,qCDoCF,CAtCA,kBAGC,2CAA4C,CAC5C,6CAA8C,CAC9C,6DAA8D,CAC9D,oCAAqC,CAGrC,4CAA6C,CAG7C,4DA0BD,CAxBC,wBEjBA,YAAa,CACb,2BAA2B,CCF3B,2CHqBA,CAEA,4BACC,sDAAuD,CACvD,oDAAqD,CACrD,yCAMD,CAJC,kCG5BD,oDH+BC,CAGD,2BACC,+CAAgD,CAChD,2CAKD,CAHC,iCGtCD,iDHwCC,CAIF,+BACC,IACC,0BACD,CAEA,IACC,yBACD,CAEA,IACC,0BACD,CAEA,IACC,yBACD,CACD",sourcesContent:['/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n@import "../../../mixins/_rounded.css";\n@import "../../../mixins/_focus.css";\n@import "../../../mixins/_shadow.css";\n\n:root {\n\t--ck-input-text-width: 18em;\n}\n\n.ck.ck-input-text {\n\t@mixin ck-rounded-corners;\n\n\tbackground: var(--ck-color-input-background);\n\tborder: 1px solid var(--ck-color-input-border);\n\tpadding: var(--ck-spacing-extra-tiny) var(--ck-spacing-medium);\n\tmin-width: var(--ck-input-text-width);\n\n\t/* This is important to stay of the same height as surrounding buttons */\n\tmin-height: var(--ck-ui-component-min-height);\n\n\t/* Apply some smooth transition to the box-shadow and border. */\n\ttransition: box-shadow .1s ease-in-out, border .1s ease-in-out;\n\n\t&:focus {\n\t\t@mixin ck-focus-ring;\n\t\t@mixin ck-box-shadow var(--ck-focus-outer-shadow);\n\t}\n\n\t&[readonly] {\n\t\tborder: 1px solid var(--ck-color-input-disabled-border);\n\t\tbackground: var(--ck-color-input-disabled-background);\n\t\tcolor: var(--ck-color-input-disabled-text);\n\n\t\t&:focus {\n\t\t\t/* The read-only input should have a slightly less visible shadow when focused. */\n\t\t\t@mixin ck-box-shadow var(--ck-focus-disabled-outer-shadow);\n\t\t}\n\t}\n\n\t&.ck-error {\n\t\tborder-color: var(--ck-color-input-error-border);\n\t\tanimation: ck-text-input-shake .3s ease both;\n\n\t\t&:focus {\n\t\t\t@mixin ck-box-shadow var(--ck-focus-error-outer-shadow);\n\t\t}\n\t}\n}\n\n@keyframes ck-text-input-shake {\n\t20% {\n\t\ttransform: translateX(-2px);\n\t}\n\n\t40% {\n\t\ttransform: translateX(2px);\n\t}\n\n\t60% {\n\t\ttransform: translateX(-1px);\n\t}\n\n\t80% {\n\t\ttransform: translateX(1px);\n\t}\n}\n',"/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * Implements rounded corner interface for .ck-rounded-corners class.\n *\n * @see $ck-border-radius\n */\n@define-mixin ck-rounded-corners {\n\tborder-radius: 0;\n\n\t@nest .ck-rounded-corners &,\n\t&.ck-rounded-corners {\n\t\tborder-radius: var(--ck-border-radius);\n\t\t@mixin-content;\n\t}\n}\n","/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * A visual style of focused element's border.\n */\n@define-mixin ck-focus-ring {\n\t/* Disable native outline. */\n\toutline: none;\n\tborder: var(--ck-focus-ring)\n}\n","/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * A helper to combine multiple shadows.\n */\n@define-mixin ck-box-shadow $shadowA, $shadowB: 0 0 {\n\tbox-shadow: $shadowA, $shadowB;\n}\n\n/**\n * Gives an element a drop shadow so it looks like a floating panel.\n */\n@define-mixin ck-drop-shadow {\n\t@mixin ck-box-shadow var(--ck-drop-shadow);\n}\n"],sourceRoot:""}]);e["a"]=a},function(t,e,n){"use strict";var o=n(2);var i=n.n(o);var r=n(3);var s=n.n(r);var a=s()(i.a);a.push([t.i,".ck.ck-text-alternative-form{display:flex;flex-direction:row;flex-wrap:nowrap}.ck.ck-text-alternative-form .ck-labeled-field-view{display:inline-block}.ck.ck-text-alternative-form .ck-label{display:none}@media screen and (max-width:600px){.ck.ck-text-alternative-form{flex-wrap:wrap}.ck.ck-text-alternative-form .ck-labeled-field-view{flex-basis:100%}.ck.ck-text-alternative-form .ck-button{flex-basis:50%}}","",{version:3,sources:["webpack://./node_modules/@ckeditor/ckeditor5-image/theme/textalternativeform.css","webpack://./node_modules/@ckeditor/ckeditor5-ui/theme/mixins/_rwd.css"],names:[],mappings:"AAOA,6BACC,YAAa,CACb,kBAAmB,CACnB,gBAqBD,CAnBC,oDACC,oBACD,CAEA,uCACC,YACD,CCZA,oCDCD,6BAcE,cAUF,CARE,oDACC,eACD,CAEA,wCACC,cACD,CCrBD",sourcesContent:['/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n@import "@ckeditor/ckeditor5-ui/theme/mixins/_rwd.css";\n\n.ck.ck-text-alternative-form {\n\tdisplay: flex;\n\tflex-direction: row;\n\tflex-wrap: nowrap;\n\n\t& .ck-labeled-field-view {\n\t\tdisplay: inline-block;\n\t}\n\n\t& .ck-label {\n\t\tdisplay: none;\n\t}\n\n\t@mixin ck-media-phone {\n\t\tflex-wrap: wrap;\n\n\t\t& .ck-labeled-field-view {\n\t\t\tflex-basis: 100%;\n\t\t}\n\n\t\t& .ck-button {\n\t\t\tflex-basis: 50%;\n\t\t}\n\t}\n}\n',"/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n@define-mixin ck-media-phone {\n\t@media screen and (max-width: 600px) {\n\t\t@mixin-content;\n\t}\n}\n"],sourceRoot:""}]);e["a"]=a},function(t,e,n){"use strict";var o=n(2);var i=n.n(o);var r=n(3);var s=n.n(r);var a=s()(i.a);a.push([t.i,'.ck-vertical-form .ck-button:after{content:"";width:0;position:absolute;right:-1px;top:var(--ck-spacing-small);bottom:var(--ck-spacing-small);z-index:1}@media screen and (max-width:600px){.ck.ck-responsive-form .ck-button:after{content:"";width:0;position:absolute;right:-1px;top:var(--ck-spacing-small);bottom:var(--ck-spacing-small);z-index:1}}.ck-vertical-form>.ck-button:nth-last-child(2):after{border-right:1px solid var(--ck-color-base-border)}.ck.ck-responsive-form{padding:var(--ck-spacing-large)}.ck.ck-responsive-form:focus{outline:none}[dir=ltr] .ck.ck-responsive-form>:not(:first-child),[dir=rtl] .ck.ck-responsive-form>:not(:last-child){margin-left:var(--ck-spacing-standard)}@media screen and (max-width:600px){.ck.ck-responsive-form{padding:0;width:calc(var(--ck-input-text-width)*0.8)}.ck.ck-responsive-form .ck-labeled-field-view{margin:var(--ck-spacing-large) var(--ck-spacing-large) 0}.ck.ck-responsive-form .ck-labeled-field-view .ck-input-text{min-width:0;width:100%}.ck.ck-responsive-form .ck-labeled-field-view .ck-labeled-field-view__error{white-space:normal}.ck.ck-responsive-form>.ck-button:last-child,.ck.ck-responsive-form>.ck-button:nth-last-child(2){padding:var(--ck-spacing-standard);margin-top:var(--ck-spacing-large);border-radius:0;border:0;border-top:1px solid var(--ck-color-base-border)}[dir=ltr] .ck.ck-responsive-form>.ck-button:last-child,[dir=ltr] .ck.ck-responsive-form>.ck-button:nth-last-child(2),[dir=rtl] .ck.ck-responsive-form>.ck-button:last-child,[dir=rtl] .ck.ck-responsive-form>.ck-button:nth-last-child(2){margin-left:0}.ck.ck-responsive-form>.ck-button:nth-last-child(2):after,[dir=rtl] .ck.ck-responsive-form>.ck-button:last-child:last-of-type,[dir=rtl] .ck.ck-responsive-form>.ck-button:nth-last-child(2):last-of-type{border-right:1px solid var(--ck-color-base-border)}}',"",{version:3,sources:["webpack://./node_modules/@ckeditor/ckeditor5-ui/theme/components/responsive-form/responsiveform.css","webpack://./node_modules/@ckeditor/ckeditor5-ui/theme/mixins/_rwd.css","webpack://./node_modules/@ckeditor/ckeditor5-theme-lark/theme/ckeditor5-ui/components/responsive-form/responsiveform.css"],names:[],mappings:"AAOA,mCACC,UAAW,CACX,OAAQ,CACR,iBAAkB,CAClB,UAAW,CACX,2BAA4B,CAC5B,8BAA+B,CAC/B,SACD,CCTC,oCDaC,wCACC,UAAW,CACX,OAAQ,CACR,iBAAkB,CAClB,UAAW,CACX,2BAA4B,CAC5B,8BAA+B,CAC/B,SACD,CCnBD,CCAD,qDACC,kDACD,CAEA,uBACC,+BAkED,CAhEC,6BAEC,YACD,CASC,uGACC,sCACD,CDvBD,oCCMD,uBAqBE,SAAU,CACV,0CA6CF,CA3CE,8CACC,wDAWD,CATC,6DACC,WAAY,CACZ,UACD,CAGA,4EACC,kBACD,CAID,iGAEC,kCAAmC,CACnC,kCAAmC,CAEnC,eAAgB,CAChB,QAAS,CACT,gDAaD,CApBA,0OAcE,aAMF,CAGC,yMACC,kDACD,CDpEF",sourcesContent:['/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n@import "@ckeditor/ckeditor5-ui/theme/mixins/_rwd.css";\n\n.ck-vertical-form .ck-button::after {\n\tcontent: "";\n\twidth: 0;\n\tposition: absolute;\n\tright: -1px;\n\ttop: var(--ck-spacing-small);\n\tbottom: var(--ck-spacing-small);\n\tz-index: 1;\n}\n\n.ck.ck-responsive-form {\n\t@mixin ck-media-phone {\n\t\t& .ck-button::after {\n\t\t\tcontent: "";\n\t\t\twidth: 0;\n\t\t\tposition: absolute;\n\t\t\tright: -1px;\n\t\t\ttop: var(--ck-spacing-small);\n\t\t\tbottom: var(--ck-spacing-small);\n\t\t\tz-index: 1;\n\t\t}\n\t}\n}\n',"/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n@define-mixin ck-media-phone {\n\t@media screen and (max-width: 600px) {\n\t\t@mixin-content;\n\t}\n}\n",'/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n@import "@ckeditor/ckeditor5-ui/theme/mixins/_rwd.css";\n@import "@ckeditor/ckeditor5-ui/theme/mixins/_dir.css";\n\n.ck-vertical-form > .ck-button:nth-last-child(2)::after {\n\tborder-right: 1px solid var(--ck-color-base-border);\n}\n\n.ck.ck-responsive-form {\n\tpadding: var(--ck-spacing-large);\n\n\t&:focus {\n\t\t/* See: https://github.com/ckeditor/ckeditor5/issues/4773 */\n\t\toutline: none;\n\t}\n\n\t@mixin ck-dir ltr {\n\t\t& > :not(:first-child) {\n\t\t\tmargin-left: var(--ck-spacing-standard);\n\t\t}\n\t}\n\n\t@mixin ck-dir rtl {\n\t\t& > :not(:last-child) {\n\t\t\tmargin-left: var(--ck-spacing-standard);\n\t\t}\n\t}\n\n\t@mixin ck-media-phone {\n\t\tpadding: 0;\n\t\twidth: calc(.8 * var(--ck-input-text-width));\n\n\t\t& .ck-labeled-field-view {\n\t\t\tmargin: var(--ck-spacing-large) var(--ck-spacing-large) 0;\n\n\t\t\t& .ck-input-text {\n\t\t\t\tmin-width: 0;\n\t\t\t\twidth: 100%;\n\t\t\t}\n\n\t\t\t/* Let the long error messages wrap in the narrow form. */\n\t\t\t& .ck-labeled-field-view__error {\n\t\t\t\twhite-space: normal;\n\t\t\t}\n\t\t}\n\n\t\t/* Styles for two last buttons in the form (save&cancel, edit&unlink, etc.). */\n\t\t& > .ck-button:nth-last-child(1),\n\t\t& > .ck-button:nth-last-child(2) {\n\t\t\tpadding: var(--ck-spacing-standard);\n\t\t\tmargin-top: var(--ck-spacing-large);\n\n\t\t\tborder-radius: 0;\n\t\t\tborder: 0;\n\t\t\tborder-top: 1px solid var(--ck-color-base-border);\n\n\t\t\t@mixin ck-dir ltr {\n\t\t\t\tmargin-left: 0;\n\t\t\t}\n\n\t\t\t@mixin ck-dir rtl {\n\t\t\t\tmargin-left: 0;\n\n\t\t\t\t&:last-of-type {\n\t\t\t\t\tborder-right: 1px solid var(--ck-color-base-border);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t& > .ck-button:nth-last-child(2) {\n\t\t\t&::after {\n\t\t\t\tborder-right: 1px solid var(--ck-color-base-border);\n\t\t\t}\n\t\t}\n\t}\n}\n'],sourceRoot:""}]);e["a"]=a},function(t,e,n){"use strict";var o=n(2);var i=n.n(o);var r=n(3);var s=n.n(r);var a=s()(i.a);a.push([t.i,".ck .ck-balloon-rotator__navigation{display:flex;align-items:center;justify-content:center}.ck .ck-balloon-rotator__content .ck-toolbar{justify-content:center}.ck .ck-balloon-rotator__navigation{background:var(--ck-color-toolbar-background);border-bottom:1px solid var(--ck-color-toolbar-border);padding:0 var(--ck-spacing-small)}.ck .ck-balloon-rotator__navigation>*{margin-right:var(--ck-spacing-small);margin-top:var(--ck-spacing-small);margin-bottom:var(--ck-spacing-small)}.ck .ck-balloon-rotator__navigation .ck-balloon-rotator__counter{margin-right:var(--ck-spacing-standard);margin-left:var(--ck-spacing-small)}.ck .ck-balloon-rotator__content .ck.ck-annotation-wrapper{box-shadow:none}","",{version:3,sources:["webpack://./node_modules/@ckeditor/ckeditor5-ui/theme/components/panel/balloonrotator.css","webpack://./node_modules/@ckeditor/ckeditor5-theme-lark/theme/ckeditor5-ui/components/panel/balloonrotator.css"],names:[],mappings:"AAKA,oCACC,YAAa,CACb,kBAAmB,CACnB,sBACD,CAKA,6CACC,sBACD,CCXA,oCACC,6CAA8C,CAC9C,sDAAuD,CACvD,iCAgBD,CAbC,sCACC,oCAAqC,CACrC,kCAAmC,CACnC,qCACD,CAGA,iEACC,uCAAwC,CAGxC,mCACD,CAMA,2DACC,eACD",sourcesContent:["/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n.ck .ck-balloon-rotator__navigation {\n\tdisplay: flex;\n\talign-items: center;\n\tjustify-content: center;\n}\n\n/* Buttons inside a toolbar should be centered when rotator bar is wider.\n * See: https://github.com/ckeditor/ckeditor5-ui/issues/495\n */\n.ck .ck-balloon-rotator__content .ck-toolbar {\n\tjustify-content: center;\n}\n","/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n.ck .ck-balloon-rotator__navigation {\n\tbackground: var(--ck-color-toolbar-background);\n\tborder-bottom: 1px solid var(--ck-color-toolbar-border);\n\tpadding: 0 var(--ck-spacing-small);\n\n\t/* Let's keep similar appearance to `ck-toolbar`. */\n\t& > * {\n\t\tmargin-right: var(--ck-spacing-small);\n\t\tmargin-top: var(--ck-spacing-small);\n\t\tmargin-bottom: var(--ck-spacing-small);\n\t}\n\n\t/* Gives counter more breath than buttons. */\n\t& .ck-balloon-rotator__counter {\n\t\tmargin-right: var(--ck-spacing-standard);\n\n\t\t/* We need to use smaller margin because of previous button's right margin. */\n\t\tmargin-left: var(--ck-spacing-small);\n\t}\n}\n\n.ck .ck-balloon-rotator__content {\n\n\t/* Disable default annotation shadow inside rotator with fake panels. */\n\t& .ck.ck-annotation-wrapper {\n\t\tbox-shadow: none;\n\t}\n}\n"],sourceRoot:""}]);e["a"]=a},function(t,e,n){"use strict";var o=n(2);var i=n.n(o);var r=n(3);var s=n.n(r);var a=s()(i.a);a.push([t.i,".ck .ck-fake-panel{position:absolute;z-index:calc(var(--ck-z-modal) - 1)}.ck .ck-fake-panel div{position:absolute}.ck .ck-fake-panel div:first-child{z-index:2}.ck .ck-fake-panel div:nth-child(2){z-index:1}:root{--ck-balloon-fake-panel-offset-horizontal:6px;--ck-balloon-fake-panel-offset-vertical:6px}.ck .ck-fake-panel div{box-shadow:var(--ck-drop-shadow),0 0;min-height:15px;background:var(--ck-color-panel-background);border:1px solid var(--ck-color-panel-border);border-radius:var(--ck-border-radius);width:100%;height:100%}.ck .ck-fake-panel div:first-child{margin-left:var(--ck-balloon-fake-panel-offset-horizontal);margin-top:var(--ck-balloon-fake-panel-offset-vertical)}.ck .ck-fake-panel div:nth-child(2){margin-left:calc(var(--ck-balloon-fake-panel-offset-horizontal)*2);margin-top:calc(var(--ck-balloon-fake-panel-offset-vertical)*2)}.ck .ck-fake-panel div:nth-child(3){margin-left:calc(var(--ck-balloon-fake-panel-offset-horizontal)*3);margin-top:calc(var(--ck-balloon-fake-panel-offset-vertical)*3)}.ck .ck-balloon-panel_arrow_s+.ck-fake-panel,.ck .ck-balloon-panel_arrow_se+.ck-fake-panel,.ck .ck-balloon-panel_arrow_sw+.ck-fake-panel{--ck-balloon-fake-panel-offset-vertical:-6px}","",{version:3,sources:["webpack://./node_modules/@ckeditor/ckeditor5-ui/theme/components/panel/fakepanel.css","webpack://./node_modules/@ckeditor/ckeditor5-theme-lark/theme/ckeditor5-ui/components/panel/fakepanel.css","webpack://./node_modules/@ckeditor/ckeditor5-theme-lark/theme/mixins/_shadow.css"],names:[],mappings:"AAKA,mBACC,iBAAkB,CAGlB,mCACD,CAEA,uBACC,iBACD,CAEA,mCACC,SACD,CAEA,oCACC,SACD,CCfA,MACC,6CAA8C,CAC9C,2CACD,CAGA,uBCJC,oCAA8B,CDO9B,eAAgB,CAEhB,2CAA4C,CAC5C,6CAA8C,CAC9C,qCAAsC,CAEtC,UAAW,CACX,WACD,CAEA,mCACC,0DAA2D,CAC3D,uDACD,CAEA,oCACC,kEAAqE,CACrE,+DACD,CACA,oCACC,kEAAqE,CACrE,+DACD,CAGA,yIAGC,4CACD",sourcesContent:["/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n.ck .ck-fake-panel {\n\tposition: absolute;\n\n\t/* Fake panels should be placed under main balloon content. */\n\tz-index: calc(var(--ck-z-modal) - 1);\n}\n\n.ck .ck-fake-panel div {\n\tposition: absolute;\n}\n\n.ck .ck-fake-panel div:nth-child( 1 ) {\n\tz-index: 2;\n}\n\n.ck .ck-fake-panel div:nth-child( 2 ) {\n\tz-index: 1;\n}\n",'/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n@import "../../../mixins/_shadow.css";\n\n:root {\n\t--ck-balloon-fake-panel-offset-horizontal: 6px;\n\t--ck-balloon-fake-panel-offset-vertical: 6px;\n}\n\n/* Let\'s use `.ck-balloon-panel` appearance. See: balloonpanel.css. */\n.ck .ck-fake-panel div {\n\t@mixin ck-drop-shadow;\n\n\tmin-height: 15px;\n\n\tbackground: var(--ck-color-panel-background);\n\tborder: 1px solid var(--ck-color-panel-border);\n\tborder-radius: var(--ck-border-radius);\n\n\twidth: 100%;\n\theight: 100%;\n}\n\n.ck .ck-fake-panel div:nth-child( 1 ) {\n\tmargin-left: var(--ck-balloon-fake-panel-offset-horizontal);\n\tmargin-top: var(--ck-balloon-fake-panel-offset-vertical);\n}\n\n.ck .ck-fake-panel div:nth-child( 2 ) {\n\tmargin-left: calc(var(--ck-balloon-fake-panel-offset-horizontal) * 2);\n\tmargin-top: calc(var(--ck-balloon-fake-panel-offset-vertical) * 2);\n}\n.ck .ck-fake-panel div:nth-child( 3 ) {\n\tmargin-left: calc(var(--ck-balloon-fake-panel-offset-horizontal) * 3);\n\tmargin-top: calc(var(--ck-balloon-fake-panel-offset-vertical) * 3);\n}\n\n/* If balloon is positioned above element, we need to move fake panel to the top. */\n.ck .ck-balloon-panel_arrow_s + .ck-fake-panel,\n.ck .ck-balloon-panel_arrow_se + .ck-fake-panel,\n.ck .ck-balloon-panel_arrow_sw + .ck-fake-panel {\n\t--ck-balloon-fake-panel-offset-vertical: -6px;\n}\n',"/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * A helper to combine multiple shadows.\n */\n@define-mixin ck-box-shadow $shadowA, $shadowB: 0 0 {\n\tbox-shadow: $shadowA, $shadowB;\n}\n\n/**\n * Gives an element a drop shadow so it looks like a floating panel.\n */\n@define-mixin ck-drop-shadow {\n\t@mixin ck-box-shadow var(--ck-drop-shadow);\n}\n"],sourceRoot:""}]);e["a"]=a},function(t,e,n){"use strict";var o=n(2);var i=n.n(o);var r=n(3);var s=n.n(r);var a=s()(i.a);a.push([t.i,".ck-content .image{display:table;clear:both;text-align:center;margin:1em auto}.ck-content .image img{display:block;margin:0 auto;max-width:100%;min-width:50px}","",{version:3,sources:["webpack://./node_modules/@ckeditor/ckeditor5-image/theme/image.css"],names:[],mappings:"AAKA,mBACC,aAAc,CACd,UAAW,CACX,iBAAkB,CAGlB,eAeD,CAbC,uBAEC,aAAc,CAGd,aAAc,CAGd,cAAe,CAGf,cACD",sourcesContent:["/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n.ck-content .image {\n\tdisplay: table;\n\tclear: both;\n\ttext-align: center;\n\n\t/* Make sure there is some space between the content and the image. Center image by default. */\n\tmargin: 1em auto;\n\n\t& img {\n\t\t/* Prevent unnecessary margins caused by line-height (see #44). */\n\t\tdisplay: block;\n\n\t\t/* Center the image if its width is smaller than the content's width. */\n\t\tmargin: 0 auto;\n\n\t\t/* Make sure the image never exceeds the size of the parent container (ckeditor/ckeditor5-ui#67). */\n\t\tmax-width: 100%;\n\n\t\t/* Make sure the caption will be displayed properly (See: https://github.com/ckeditor/ckeditor5/issues/1870). */\n\t\tmin-width: 50px;\n\t}\n}\n"],sourceRoot:""}]);e["a"]=a},function(t,e,n){"use strict";var o=n(2);var i=n.n(o);var r=n(3);var s=n.n(r);var a=s()(i.a);a.push([t.i,".ck-content .image>figcaption{display:table-caption;caption-side:bottom;word-break:break-word;color:#333;background-color:#f7f7f7;padding:.6em;font-size:.75em;outline-offset:-1px}","",{version:3,sources:["webpack://./node_modules/@ckeditor/ckeditor5-image/theme/imagecaption.css"],names:[],mappings:"AAKA,8BACC,qBAAsB,CACtB,mBAAoB,CACpB,qBAAsB,CACtB,UAAsB,CACtB,wBAAiC,CACjC,YAAa,CACb,eAAgB,CAChB,mBACD",sourcesContent:["/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n.ck-content .image > figcaption {\n\tdisplay: table-caption;\n\tcaption-side: bottom;\n\tword-break: break-word;\n\tcolor: hsl(0, 0%, 20%);\n\tbackground-color: hsl(0, 0%, 97%);\n\tpadding: .6em;\n\tfont-size: .75em;\n\toutline-offset: -1px;\n}\n"],sourceRoot:""}]);e["a"]=a},function(t,e,n){"use strict";var o=n(2);var i=n.n(o);var r=n(3);var s=n.n(r);var a=s()(i.a);a.push([t.i,".ck .ck-widget_with-resizer{position:relative}.ck .ck-widget__resizer{display:none;position:absolute;pointer-events:none;left:0;top:0;outline:1px solid var(--ck-color-resizer)}.ck-focused .ck-widget_with-resizer.ck-widget_selected>.ck-widget__resizer{display:block}.ck .ck-widget__resizer__handle{position:absolute;pointer-events:all;width:var(--ck-resizer-size);height:var(--ck-resizer-size);background:var(--ck-color-focus-border);border:var(--ck-resizer-border-width) solid #fff;border-radius:var(--ck-resizer-border-radius)}.ck .ck-widget__resizer__handle.ck-widget__resizer__handle-top-left{top:var(--ck-resizer-offset);left:var(--ck-resizer-offset);cursor:nwse-resize}.ck .ck-widget__resizer__handle.ck-widget__resizer__handle-top-right{top:var(--ck-resizer-offset);right:var(--ck-resizer-offset);cursor:nesw-resize}.ck .ck-widget__resizer__handle.ck-widget__resizer__handle-bottom-right{bottom:var(--ck-resizer-offset);right:var(--ck-resizer-offset);cursor:nwse-resize}.ck .ck-widget__resizer__handle.ck-widget__resizer__handle-bottom-left{bottom:var(--ck-resizer-offset);left:var(--ck-resizer-offset);cursor:nesw-resize}","",{version:3,sources:["webpack://./node_modules/@ckeditor/ckeditor5-widget/theme/widgetresize.css"],names:[],mappings:"AAKA,4BAEC,iBACD,CAEA,wBACC,YAAa,CACb,iBAAkB,CAGlB,mBAAoB,CAEpB,MAAO,CACP,KAAM,CAEN,yCACD,CAGC,2EACC,aACD,CAGD,gCACC,iBAAkB,CAGlB,kBAAmB,CAEnB,4BAA6B,CAC7B,6BAA8B,CAC9B,uCAAwC,CACxC,gDAA6D,CAC7D,6CAyBD,CAvBC,oEACC,4BAA+B,CAC/B,6BAAgC,CAChC,kBACD,CAEA,qEACC,4BAA+B,CAC/B,8BAAiC,CACjC,kBACD,CAEA,wEACC,+BAAkC,CAClC,8BAAiC,CACjC,kBACD,CAEA,uEACC,+BAAkC,CAClC,6BAAgC,CAChC,kBACD",sourcesContent:["/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n.ck .ck-widget_with-resizer {\n\t/* Make the widget wrapper a relative positioning container for the drag handle. */\n\tposition: relative;\n}\n\n.ck .ck-widget__resizer {\n\tdisplay: none;\n\tposition: absolute;\n\n\t/* The wrapper itself should not interfere with the pointer device, only the handles should. */\n\tpointer-events: none;\n\n\tleft: 0;\n\ttop: 0;\n\n\toutline: 1px solid var(--ck-color-resizer);\n}\n\n.ck-focused .ck-widget_with-resizer.ck-widget_selected {\n\t& > .ck-widget__resizer {\n\t\tdisplay: block;\n\t}\n}\n\n.ck .ck-widget__resizer__handle {\n\tposition: absolute;\n\n\t/* Resizers are the only UI elements that should interfere with a pointer device. */\n\tpointer-events: all;\n\n\twidth: var(--ck-resizer-size);\n\theight: var(--ck-resizer-size);\n\tbackground: var(--ck-color-focus-border);\n\tborder: var(--ck-resizer-border-width) solid hsl(0, 0%, 100%);\n\tborder-radius: var(--ck-resizer-border-radius);\n\n\t&.ck-widget__resizer__handle-top-left {\n\t\ttop: var( --ck-resizer-offset );\n\t\tleft: var( --ck-resizer-offset );\n\t\tcursor: nwse-resize;\n\t}\n\n\t&.ck-widget__resizer__handle-top-right {\n\t\ttop: var( --ck-resizer-offset );\n\t\tright: var( --ck-resizer-offset );\n\t\tcursor: nesw-resize;\n\t}\n\n\t&.ck-widget__resizer__handle-bottom-right {\n\t\tbottom: var( --ck-resizer-offset );\n\t\tright: var( --ck-resizer-offset );\n\t\tcursor: nwse-resize;\n\t}\n\n\t&.ck-widget__resizer__handle-bottom-left {\n\t\tbottom: var( --ck-resizer-offset );\n\t\tleft: var( --ck-resizer-offset );\n\t\tcursor: nesw-resize;\n\t}\n}\n"],sourceRoot:""}]);e["a"]=a},function(t,e,n){"use strict";var o=n(2);var i=n.n(o);var r=n(3);var s=n.n(r);var a=s()(i.a);a.push([t.i,".ck-content .image.image_resized{max-width:100%;display:block;box-sizing:border-box}.ck-content .image.image_resized img{width:100%}.ck-content .image.image_resized>figcaption{display:block}[dir=ltr] .ck.ck-button.ck-button_with-text.ck-resize-image-button .ck-button__icon{margin-right:var(--ck-spacing-standard)}[dir=rtl] .ck.ck-button.ck-button_with-text.ck-resize-image-button .ck-button__icon{margin-left:var(--ck-spacing-standard)}.ck.ck-dropdown .ck-button.ck-resize-image-button .ck-button__label{width:4em}","",{version:3,sources:["webpack://./node_modules/@ckeditor/ckeditor5-image/theme/imageresize.css"],names:[],mappings:"AAKA,iCACC,cAAe,CAMf,aAAc,CACd,qBAWD,CATC,qCAEC,UACD,CAEA,4CAEC,aACD,CAGD,oFACC,uCACD,CAEA,oFACC,sCACD,CAEA,oEACC,SACD",sourcesContent:['/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n.ck-content .image.image_resized {\n\tmax-width: 100%;\n\t/*\n\tThe `
` element for resized images must not use `display:table` as browsers do not support `max-width` for it well.\n\tSee https://stackoverflow.com/questions/4019604/chrome-safari-ignoring-max-width-in-table/14420691#14420691 for more.\n\tFortunately, since we control the width, there is no risk that the image will look bad.\n\t*/\n\tdisplay: block;\n\tbox-sizing: border-box;\n\n\t& img {\n\t\t/* For resized images it is the `
` element that determines the image width. */\n\t\twidth: 100%;\n\t}\n\n\t& > figcaption {\n\t\t/* The `
` element uses `display:block`, so `
` also has to. */\n\t\tdisplay: block;\n\t}\n}\n\n[dir="ltr"] .ck.ck-button.ck-button_with-text.ck-resize-image-button .ck-button__icon {\n\tmargin-right: var(--ck-spacing-standard);\n}\n\n[dir="rtl"] .ck.ck-button.ck-button_with-text.ck-resize-image-button .ck-button__icon {\n\tmargin-left: var(--ck-spacing-standard);\n}\n\n.ck.ck-dropdown .ck-button.ck-resize-image-button .ck-button__label {\n\twidth: 4em;\n}\n'],sourceRoot:""}]);e["a"]=a},function(t,e,n){"use strict";var o=n(2);var i=n.n(o);var r=n(3);var s=n.n(r);var a=s()(i.a);a.push([t.i,":root{--ck-image-style-spacing:1.5em}.ck-content .image-style-side{float:right;margin-left:var(--ck-image-style-spacing);max-width:50%}.ck-content .image-style-align-left{float:left;margin-right:var(--ck-image-style-spacing)}.ck-content .image-style-align-center{margin-left:auto;margin-right:auto}.ck-content .image-style-align-right{float:right;margin-left:var(--ck-image-style-spacing)}","",{version:3,sources:["webpack://./node_modules/@ckeditor/ckeditor5-image/theme/imagestyle.css"],names:[],mappings:"AAKA,MACC,8BACD,CAGC,8BACC,WAAY,CACZ,yCAA0C,CAC1C,aACD,CAEA,oCACC,UAAW,CACX,0CACD,CAEA,sCACC,gBAAiB,CACjB,iBACD,CAEA,qCACC,WAAY,CACZ,yCACD",sourcesContent:["/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n:root {\n\t--ck-image-style-spacing: 1.5em;\n}\n\n.ck-content {\n\t& .image-style-side {\n\t\tfloat: right;\n\t\tmargin-left: var(--ck-image-style-spacing);\n\t\tmax-width: 50%;\n\t}\n\n\t& .image-style-align-left {\n\t\tfloat: left;\n\t\tmargin-right: var(--ck-image-style-spacing);\n\t}\n\n\t& .image-style-align-center {\n\t\tmargin-left: auto;\n\t\tmargin-right: auto;\n\t}\n\n\t& .image-style-align-right {\n\t\tfloat: right;\n\t\tmargin-left: var(--ck-image-style-spacing);\n\t}\n}\n"],sourceRoot:""}]);e["a"]=a},function(t,e,n){"use strict";var o=n(2);var i=n.n(o);var r=n(3);var s=n.n(r);var a=s()(i.a);a.push([t.i,".ck.ck-editor__editable .image{position:relative}.ck.ck-editor__editable .image .ck-progress-bar{position:absolute;top:0;left:0}.ck.ck-editor__editable .image.ck-appear{animation:fadeIn .7s}.ck.ck-editor__editable .image .ck-progress-bar{height:2px;width:0;background:var(--ck-color-upload-bar-background);transition:width .1s}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}","",{version:3,sources:["webpack://./node_modules/@ckeditor/ckeditor5-image/theme/imageuploadprogress.css","webpack://./node_modules/@ckeditor/ckeditor5-theme-lark/theme/ckeditor5-image/imageuploadprogress.css"],names:[],mappings:"AAKA,+BACC,iBACD,CAGA,gDACC,iBAAkB,CAClB,KAAM,CACN,MACD,CCPC,yCACC,oBACD,CAID,gDACC,UAAW,CACX,OAAQ,CACR,gDAAiD,CACjD,oBACD,CAEA,kBACC,GAAO,SAAY,CACnB,GAAO,SAAY,CACpB",sourcesContent:["/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n.ck.ck-editor__editable .image {\n\tposition: relative;\n}\n\n/* Upload progress bar. */\n.ck.ck-editor__editable .image .ck-progress-bar {\n\tposition: absolute;\n\ttop: 0;\n\tleft: 0;\n}\n","/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n.ck.ck-editor__editable .image {\n\t/* Showing animation. */\n\t&.ck-appear {\n\t\tanimation: fadeIn 700ms;\n\t}\n}\n\n/* Upload progress bar. */\n.ck.ck-editor__editable .image .ck-progress-bar {\n\theight: 2px;\n\twidth: 0;\n\tbackground: var(--ck-color-upload-bar-background);\n\ttransition: width 100ms;\n}\n\n@keyframes fadeIn {\n\tfrom { opacity: 0; }\n\tto { opacity: 1; }\n}\n"],sourceRoot:""}]);e["a"]=a},function(t,e,n){"use strict";var o=n(2);var i=n.n(o);var r=n(3);var s=n.n(r);var a=s()(i.a);a.push([t.i,'.ck-image-upload-complete-icon{display:block;position:absolute;top:10px;right:10px;border-radius:50%}.ck-image-upload-complete-icon:after{content:"";position:absolute}:root{--ck-color-image-upload-icon:#fff;--ck-color-image-upload-icon-background:#008a00;--ck-image-upload-icon-size:20px;--ck-image-upload-icon-width:2px}.ck-image-upload-complete-icon{width:var(--ck-image-upload-icon-size);height:var(--ck-image-upload-icon-size);opacity:0;background:var(--ck-color-image-upload-icon-background);animation-name:ck-upload-complete-icon-show,ck-upload-complete-icon-hide;animation-fill-mode:forwards,forwards;animation-duration:.5s,.5s;font-size:var(--ck-image-upload-icon-size);animation-delay:0ms,3s}.ck-image-upload-complete-icon:after{left:25%;top:50%;opacity:0;height:0;width:0;transform:scaleX(-1) rotate(135deg);transform-origin:left top;border-top:var(--ck-image-upload-icon-width) solid var(--ck-color-image-upload-icon);border-right:var(--ck-image-upload-icon-width) solid var(--ck-color-image-upload-icon);animation-name:ck-upload-complete-icon-check;animation-duration:.5s;animation-delay:.5s;animation-fill-mode:forwards;box-sizing:border-box}@keyframes ck-upload-complete-icon-show{0%{opacity:0}to{opacity:1}}@keyframes ck-upload-complete-icon-hide{0%{opacity:1}to{opacity:0}}@keyframes ck-upload-complete-icon-check{0%{opacity:1;width:0;height:0}33%{width:.3em;height:0}to{opacity:1;width:.3em;height:.45em}}',"",{version:3,sources:["webpack://./node_modules/@ckeditor/ckeditor5-image/theme/imageuploadicon.css","webpack://./node_modules/@ckeditor/ckeditor5-theme-lark/theme/ckeditor5-image/imageuploadicon.css"],names:[],mappings:"AAKA,+BACC,aAAc,CACd,iBAAkB,CAClB,QAAS,CACT,UAAW,CACX,iBAMD,CAJC,qCACC,UAAW,CACX,iBACD,CCVD,MACC,iCAA8C,CAC9C,+CAA4D,CAE5D,gCAAiC,CACjC,gCACD,CAEA,+BACC,sCAAuC,CACvC,uCAAwC,CACxC,SAAU,CACV,uDAAwD,CACxD,wEAA0E,CAC1E,qCAAuC,CACvC,0BAAgC,CAGhC,0CAA2C,CAG3C,sBAyBD,CAtBC,qCAEC,QAAS,CAET,OAAQ,CACR,SAAU,CACV,QAAS,CACT,OAAQ,CAER,mCAAoC,CACpC,yBAA0B,CAC1B,oFAAqF,CACrF,sFAAuF,CAEvF,4CAA6C,CAC7C,sBAAyB,CACzB,mBAAsB,CACtB,4BAA6B,CAG7B,qBACD,CAGD,wCACC,GACC,SACD,CAEA,GACC,SACD,CACD,CAEA,wCACC,GACC,SACD,CAEA,GACC,SACD,CACD,CAEA,yCACC,GACC,SAAU,CACV,OAAQ,CACR,QACD,CACA,IACC,UAAY,CACZ,QACD,CACA,GACC,SAAU,CACV,UAAY,CACZ,YACD,CACD",sourcesContent:['/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n.ck-image-upload-complete-icon {\n\tdisplay: block;\n\tposition: absolute;\n\ttop: 10px;\n\tright: 10px;\n\tborder-radius: 50%;\n\n\t&::after {\n\t\tcontent: "";\n\t\tposition: absolute;\n\t}\n}\n','/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n:root {\n\t--ck-color-image-upload-icon: hsl(0, 0%, 100%);\n\t--ck-color-image-upload-icon-background: hsl(120, 100%, 27%);\n\n\t--ck-image-upload-icon-size: 20px;\n\t--ck-image-upload-icon-width: 2px;\n}\n\n.ck-image-upload-complete-icon {\n\twidth: var(--ck-image-upload-icon-size);\n\theight: var(--ck-image-upload-icon-size);\n\topacity: 0;\n\tbackground: var(--ck-color-image-upload-icon-background);\n\tanimation-name: ck-upload-complete-icon-show, ck-upload-complete-icon-hide;\n\tanimation-fill-mode: forwards, forwards;\n\tanimation-duration: 500ms, 500ms;\n\n\t/* To make animation scalable. */\n\tfont-size: var(--ck-image-upload-icon-size);\n\n\t/* Hide completed upload icon after 3 seconds. */\n\tanimation-delay: 0ms, 3000ms;\n\n\t/* This is check icon element made from border-width mixed with animations. */\n\t&::after {\n\t\t/* Because of border transformation we need to "hard code" left position. */\n\t\tleft: 25%;\n\n\t\ttop: 50%;\n\t\topacity: 0;\n\t\theight: 0;\n\t\twidth: 0;\n\n\t\ttransform: scaleX(-1) rotate(135deg);\n\t\ttransform-origin: left top;\n\t\tborder-top: var(--ck-image-upload-icon-width) solid var(--ck-color-image-upload-icon);\n\t\tborder-right: var(--ck-image-upload-icon-width) solid var(--ck-color-image-upload-icon);\n\n\t\tanimation-name: ck-upload-complete-icon-check;\n\t\tanimation-duration: 500ms;\n\t\tanimation-delay: 500ms;\n\t\tanimation-fill-mode: forwards;\n\n\t\t/* #1095. While reset is not providing proper box-sizing for pseudoelements, we need to handle it. */\n\t\tbox-sizing: border-box;\n\t}\n}\n\n@keyframes ck-upload-complete-icon-show {\n\tfrom {\n\t\topacity: 0;\n\t}\n\n\tto {\n\t\topacity: 1;\n\t}\n}\n\n@keyframes ck-upload-complete-icon-hide {\n\tfrom {\n\t\topacity: 1;\n\t}\n\n\tto {\n\t\topacity: 0;\n\t}\n}\n\n@keyframes ck-upload-complete-icon-check {\n\t0% {\n\t\topacity: 1;\n\t\twidth: 0;\n\t\theight: 0;\n\t}\n\t33% {\n\t\twidth: 0.3em;\n\t\theight: 0;\n\t}\n\t100% {\n\t\topacity: 1;\n\t\twidth: 0.3em;\n\t\theight: 0.45em;\n\t}\n}\n'],sourceRoot:""}]);e["a"]=a},function(t,e,n){"use strict";var o=n(2);var i=n.n(o);var r=n(3);var s=n.n(r);var a=s()(i.a);a.push([t.i,'.ck .ck-upload-placeholder-loader{position:absolute;display:flex;align-items:center;justify-content:center;top:0;left:0}.ck .ck-upload-placeholder-loader:before{content:"";position:relative}:root{--ck-color-upload-placeholder-loader:#b3b3b3;--ck-upload-placeholder-loader-size:32px}.ck .ck-image-upload-placeholder{width:100%;margin:0}.ck .ck-upload-placeholder-loader{width:100%;height:100%}.ck .ck-upload-placeholder-loader:before{width:var(--ck-upload-placeholder-loader-size);height:var(--ck-upload-placeholder-loader-size);border-radius:50%;border-top:3px solid var(--ck-color-upload-placeholder-loader);border-right:2px solid transparent;animation:ck-upload-placeholder-loader 1s linear infinite}@keyframes ck-upload-placeholder-loader{to{transform:rotate(1turn)}}',"",{version:3,sources:["webpack://./node_modules/@ckeditor/ckeditor5-image/theme/imageuploadloader.css","webpack://./node_modules/@ckeditor/ckeditor5-theme-lark/theme/ckeditor5-image/imageuploadloader.css"],names:[],mappings:"AAKA,kCACC,iBAAkB,CAClB,YAAa,CACb,kBAAmB,CACnB,sBAAuB,CACvB,KAAM,CACN,MAMD,CAJC,yCACC,UAAW,CACX,iBACD,CCXD,MACC,4CAAqD,CACrD,wCACD,CAEA,iCAEC,UAAW,CACX,QACD,CAEA,kCACC,UAAW,CACX,WAUD,CARC,yCACC,8CAA+C,CAC/C,+CAAgD,CAChD,iBAAkB,CAClB,8DAA+D,CAC/D,kCAAmC,CACnC,yDACD,CAGD,wCACC,GACC,uBACD,CACD",sourcesContent:["/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n.ck .ck-upload-placeholder-loader {\n\tposition: absolute;\n\tdisplay: flex;\n\talign-items: center;\n\tjustify-content: center;\n\ttop: 0;\n\tleft: 0;\n\n\t&::before {\n\t\tcontent: '';\n\t\tposition: relative;\n\t}\n}\n","/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n:root {\n\t--ck-color-upload-placeholder-loader: hsl(0, 0%, 70%);\n\t--ck-upload-placeholder-loader-size: 32px;\n}\n\n.ck .ck-image-upload-placeholder {\n\t/* We need to control the full width of the SVG gray background. */\n\twidth: 100%;\n\tmargin: 0;\n}\n\n.ck .ck-upload-placeholder-loader {\n\twidth: 100%;\n\theight: 100%;\n\n\t&::before {\n\t\twidth: var(--ck-upload-placeholder-loader-size);\n\t\theight: var(--ck-upload-placeholder-loader-size);\n\t\tborder-radius: 50%;\n\t\tborder-top: 3px solid var(--ck-color-upload-placeholder-loader);\n\t\tborder-right: 2px solid transparent;\n\t\tanimation: ck-upload-placeholder-loader 1s linear infinite;\n\t}\n}\n\n@keyframes ck-upload-placeholder-loader {\n\tto {\n\t\ttransform: rotate( 360deg );\n\t}\n}\n"],sourceRoot:""}]);e["a"]=a},function(t,e,n){"use strict";var o=n(2);var i=n.n(o);var r=n(3);var s=n.n(r);var a=s()(i.a);a.push([t.i,".ck.ck-link-form{display:flex}.ck.ck-link-form .ck-label{display:none}@media screen and (max-width:600px){.ck.ck-link-form{flex-wrap:wrap}.ck.ck-link-form .ck-labeled-field-view{flex-basis:100%}.ck.ck-link-form .ck-button{flex-basis:50%}}.ck.ck-link-form_layout-vertical{display:block}.ck.ck-link-form_layout-vertical .ck-button.ck-button-cancel,.ck.ck-link-form_layout-vertical .ck-button.ck-button-save{margin-top:var(--ck-spacing-medium)}.ck.ck-link-form_layout-vertical{padding:0;min-width:var(--ck-input-text-width)}.ck.ck-link-form_layout-vertical .ck-labeled-field-view{margin:var(--ck-spacing-large) var(--ck-spacing-large) var(--ck-spacing-small)}.ck.ck-link-form_layout-vertical .ck-labeled-field-view .ck-input-text{min-width:0;width:100%}.ck.ck-link-form_layout-vertical .ck-button{padding:var(--ck-spacing-standard);margin:0;border-radius:0;border:0;border-top:1px solid var(--ck-color-base-border);width:50%}[dir=ltr] .ck.ck-link-form_layout-vertical .ck-button,[dir=rtl] .ck.ck-link-form_layout-vertical .ck-button{margin-left:0}[dir=rtl] .ck.ck-link-form_layout-vertical .ck-button:last-of-type{border-right:1px solid var(--ck-color-base-border)}.ck.ck-link-form_layout-vertical .ck.ck-list{margin:var(--ck-spacing-standard) var(--ck-spacing-large)}.ck.ck-link-form_layout-vertical .ck.ck-list .ck-button.ck-switchbutton{border:0;padding:0;width:100%}.ck.ck-link-form_layout-vertical .ck.ck-list .ck-button.ck-switchbutton:hover{background:none}","",{version:3,sources:["webpack://./node_modules/@ckeditor/ckeditor5-link/theme/linkform.css","webpack://./node_modules/@ckeditor/ckeditor5-ui/theme/mixins/_rwd.css","webpack://./node_modules/@ckeditor/ckeditor5-theme-lark/theme/ckeditor5-link/linkform.css"],names:[],mappings:"AAOA,iBACC,YAiBD,CAfC,2BACC,YACD,CCNA,oCDCD,iBAQE,cAUF,CARE,wCACC,eACD,CAEA,4BACC,cACD,CCfD,CDuBD,iCACC,aAYD,CALE,wHAEC,mCACD,CE/BF,iCACC,SAAU,CACV,oCA8CD,CA5CC,wDACC,8EAMD,CAJC,uEACC,WAAY,CACZ,UACD,CAGD,4CACC,kCAAmC,CACnC,QAAS,CACT,eAAgB,CAChB,QAAS,CACT,gDAAiD,CACjD,SAaD,CAnBA,4GAaE,aAMF,CAJE,mEACC,kDACD,CAKF,6CACC,yDAWD,CATC,wEACC,QAAS,CACT,SAAU,CACV,UAKD,CAHC,8EACC,eACD",sourcesContent:['/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n@import "@ckeditor/ckeditor5-ui/theme/mixins/_rwd.css";\n\n.ck.ck-link-form {\n\tdisplay: flex;\n\n\t& .ck-label {\n\t\tdisplay: none;\n\t}\n\n\t@mixin ck-media-phone {\n\t\tflex-wrap: wrap;\n\n\t\t& .ck-labeled-field-view {\n\t\t\tflex-basis: 100%;\n\t\t}\n\n\t\t& .ck-button {\n\t\t\tflex-basis: 50%;\n\t\t}\n\t}\n}\n\n/*\n * Style link form differently when manual decorators are available.\n * See: https://github.com/ckeditor/ckeditor5-link/issues/186.\n */\n.ck.ck-link-form_layout-vertical {\n\tdisplay: block;\n\n\t/*\n\t * Whether the form is in the responsive mode or not, if there are decorator buttons\n\t * keep the top margin of action buttons medium.\n\t */\n\t& .ck-button {\n\t\t&.ck-button-save,\n\t\t&.ck-button-cancel {\n\t\t\tmargin-top: var(--ck-spacing-medium);\n\t\t}\n\t}\n}\n',"/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n@define-mixin ck-media-phone {\n\t@media screen and (max-width: 600px) {\n\t\t@mixin-content;\n\t}\n}\n",'/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n@import "@ckeditor/ckeditor5-ui/theme/mixins/_dir.css";\n\n/*\n * Style link form differently when manual decorators are available.\n * See: https://github.com/ckeditor/ckeditor5-link/issues/186.\n */\n.ck.ck-link-form_layout-vertical {\n\tpadding: 0;\n\tmin-width: var(--ck-input-text-width);\n\n\t& .ck-labeled-field-view {\n\t\tmargin: var(--ck-spacing-large) var(--ck-spacing-large) var(--ck-spacing-small);\n\n\t\t& .ck-input-text {\n\t\t\tmin-width: 0;\n\t\t\twidth: 100%;\n\t\t}\n\t}\n\n\t& .ck-button {\n\t\tpadding: var(--ck-spacing-standard);\n\t\tmargin: 0;\n\t\tborder-radius: 0;\n\t\tborder: 0;\n\t\tborder-top: 1px solid var(--ck-color-base-border);\n\t\twidth: 50%;\n\n\t\t@mixin ck-dir ltr {\n\t\t\tmargin-left: 0;\n\t\t}\n\n\t\t@mixin ck-dir rtl {\n\t\t\tmargin-left: 0;\n\n\t\t\t&:last-of-type {\n\t\t\t\tborder-right: 1px solid var(--ck-color-base-border);\n\t\t\t}\n\t\t}\n\t}\n\n\t/* Using additional `.ck` class for stronger CSS specificity than `.ck.ck-link-form > :not(:first-child)`. */\n\t& .ck.ck-list {\n\t\tmargin: var(--ck-spacing-standard) var(--ck-spacing-large);\n\n\t\t& .ck-button.ck-switchbutton {\n\t\t\tborder: 0;\n\t\t\tpadding: 0;\n\t\t\twidth: 100%;\n\n\t\t\t&:hover {\n\t\t\t\tbackground: none;\n\t\t\t}\n\t\t}\n\t}\n}\n'],sourceRoot:""}]);e["a"]=a},function(t,e,n){"use strict";var o=n(2);var i=n.n(o);var r=n(3);var s=n.n(r);var a=s()(i.a);a.push([t.i,".ck.ck-link-actions{display:flex;flex-direction:row;flex-wrap:nowrap}.ck.ck-link-actions .ck-link-actions__preview{display:inline-block}.ck.ck-link-actions .ck-link-actions__preview .ck-button__label{overflow:hidden}@media screen and (max-width:600px){.ck.ck-link-actions{flex-wrap:wrap}.ck.ck-link-actions .ck-link-actions__preview{flex-basis:100%}.ck.ck-link-actions .ck-button:not(.ck-link-actions__preview){flex-basis:50%}}.ck.ck-link-actions .ck-button.ck-link-actions__preview{padding-left:0;padding-right:0}.ck.ck-link-actions .ck-button.ck-link-actions__preview .ck-button__label{padding:0 var(--ck-spacing-medium);color:var(--ck-color-link-default);text-overflow:ellipsis;cursor:pointer;max-width:var(--ck-input-text-width);min-width:3em;text-align:center}.ck.ck-link-actions .ck-button.ck-link-actions__preview .ck-button__label:hover{text-decoration:underline}.ck.ck-link-actions .ck-button.ck-link-actions__preview,.ck.ck-link-actions .ck-button.ck-link-actions__preview:active,.ck.ck-link-actions .ck-button.ck-link-actions__preview:focus,.ck.ck-link-actions .ck-button.ck-link-actions__preview:hover{background:none}.ck.ck-link-actions .ck-button.ck-link-actions__preview:active{box-shadow:none}.ck.ck-link-actions .ck-button.ck-link-actions__preview:focus .ck-button__label{text-decoration:underline}[dir=ltr] .ck.ck-link-actions .ck-button:not(:first-child),[dir=rtl] .ck.ck-link-actions .ck-button:not(:last-child){margin-left:var(--ck-spacing-standard)}@media screen and (max-width:600px){.ck.ck-link-actions .ck-button.ck-link-actions__preview{margin:var(--ck-spacing-standard) var(--ck-spacing-standard) 0}.ck.ck-link-actions .ck-button.ck-link-actions__preview .ck-button__label{min-width:0;max-width:100%}[dir=ltr] .ck.ck-link-actions .ck-button:not(.ck-link-actions__preview),[dir=rtl] .ck.ck-link-actions .ck-button:not(.ck-link-actions__preview){margin-left:0}}","",{version:3,sources:["webpack://./node_modules/@ckeditor/ckeditor5-link/theme/linkactions.css","webpack://./node_modules/@ckeditor/ckeditor5-ui/theme/mixins/_rwd.css","webpack://./node_modules/@ckeditor/ckeditor5-theme-lark/theme/ckeditor5-link/linkactions.css"],names:[],mappings:"AAOA,oBACC,YAAa,CACb,kBAAmB,CACnB,gBAqBD,CAnBC,8CACC,oBAKD,CAHC,gEACC,eACD,CCXD,oCDCD,oBAcE,cAUF,CARE,8CACC,eACD,CAEA,8DACC,cACD,CCrBD,CCKA,wDACC,cAAe,CACf,eAmCD,CAjCC,0EACC,kCAAmC,CACnC,kCAAmC,CACnC,sBAAuB,CACvB,cAAe,CAIf,oCAAqC,CACrC,aAAc,CACd,iBAKD,CAHC,gFACC,yBACD,CAGD,mPAIC,eACD,CAEA,+DACC,eACD,CAGC,gFACC,yBACD,CAWD,qHACC,sCACD,CDvDD,oCC2DC,wDACC,8DAMD,CAJC,0EACC,WAAY,CACZ,cACD,CAGD,gJAME,aAEF,CD1ED",sourcesContent:['/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n@import "@ckeditor/ckeditor5-ui/theme/mixins/_rwd.css";\n\n.ck.ck-link-actions {\n\tdisplay: flex;\n\tflex-direction: row;\n\tflex-wrap: nowrap;\n\n\t& .ck-link-actions__preview {\n\t\tdisplay: inline-block;\n\n\t\t& .ck-button__label {\n\t\t\toverflow: hidden;\n\t\t}\n\t}\n\n\t@mixin ck-media-phone {\n\t\tflex-wrap: wrap;\n\n\t\t& .ck-link-actions__preview {\n\t\t\tflex-basis: 100%;\n\t\t}\n\n\t\t& .ck-button:not(.ck-link-actions__preview) {\n\t\t\tflex-basis: 50%;\n\t\t}\n\t}\n}\n',"/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n@define-mixin ck-media-phone {\n\t@media screen and (max-width: 600px) {\n\t\t@mixin-content;\n\t}\n}\n",'/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n@import "@ckeditor/ckeditor5-ui/theme/components/tooltip/mixins/_tooltip.css";\n@import "@ckeditor/ckeditor5-ui/theme/mixins/_unselectable.css";\n@import "@ckeditor/ckeditor5-ui/theme/mixins/_dir.css";\n@import "../mixins/_focus.css";\n@import "../mixins/_shadow.css";\n@import "@ckeditor/ckeditor5-ui/theme/mixins/_rwd.css";\n\n.ck.ck-link-actions {\n\t& .ck-button.ck-link-actions__preview {\n\t\tpadding-left: 0;\n\t\tpadding-right: 0;\n\n\t\t& .ck-button__label {\n\t\t\tpadding: 0 var(--ck-spacing-medium);\n\t\t\tcolor: var(--ck-color-link-default);\n\t\t\ttext-overflow: ellipsis;\n\t\t\tcursor: pointer;\n\n\t\t\t/* Match the box model of the link editor form\'s input so the balloon\n\t\t\tdoes not change width when moving between actions and the form. */\n\t\t\tmax-width: var(--ck-input-text-width);\n\t\t\tmin-width: 3em;\n\t\t\ttext-align: center;\n\n\t\t\t&:hover {\n\t\t\t\ttext-decoration: underline;\n\t\t\t}\n\t\t}\n\n\t\t&,\n\t\t&:hover,\n\t\t&:focus,\n\t\t&:active {\n\t\t\tbackground: none;\n\t\t}\n\n\t\t&:active {\n\t\t\tbox-shadow: none;\n\t\t}\n\n\t\t&:focus {\n\t\t\t& .ck-button__label {\n\t\t\t\ttext-decoration: underline;\n\t\t\t}\n\t\t}\n\t}\n\n\t@mixin ck-dir ltr {\n\t\t& .ck-button:not(:first-child) {\n\t\t\tmargin-left: var(--ck-spacing-standard);\n\t\t}\n\t}\n\n\t@mixin ck-dir rtl {\n\t\t& .ck-button:not(:last-child) {\n\t\t\tmargin-left: var(--ck-spacing-standard);\n\t\t}\n\t}\n\n\t@mixin ck-media-phone {\n\t\t& .ck-button.ck-link-actions__preview {\n\t\t\tmargin: var(--ck-spacing-standard) var(--ck-spacing-standard) 0;\n\n\t\t\t& .ck-button__label {\n\t\t\t\tmin-width: 0;\n\t\t\t\tmax-width: 100%;\n\t\t\t}\n\t\t}\n\n\t\t& .ck-button:not(.ck-link-actions__preview) {\n\t\t\t@mixin ck-dir ltr {\n\t\t\t\tmargin-left: 0;\n\t\t\t}\n\n\t\t\t@mixin ck-dir rtl {\n\t\t\t\tmargin-left: 0;\n\t\t\t}\n\t\t}\n\t}\n}\n'],sourceRoot:""}]);e["a"]=a},function(t,e,n){"use strict";var o=n(2);var i=n.n(o);var r=n(3);var s=n.n(r);var a=s()(i.a);a.push([t.i,'.ck-media__wrapper .ck-media__placeholder{display:flex;flex-direction:column;align-items:center}.ck-media__wrapper .ck-media__placeholder .ck-media__placeholder__url .ck-tooltip{display:block}@media (hover:none){.ck-media__wrapper .ck-media__placeholder .ck-media__placeholder__url .ck-tooltip{display:none}}.ck-media__wrapper .ck-media__placeholder .ck-media__placeholder__url{max-width:100%;position:relative}.ck-media__wrapper .ck-media__placeholder .ck-media__placeholder__url:hover .ck-tooltip{visibility:visible;opacity:1}.ck-media__wrapper .ck-media__placeholder .ck-media__placeholder__url .ck-media__placeholder__url__text{overflow:hidden;display:block}.ck-media__wrapper[data-oembed-url*="facebook.com"] .ck-media__placeholder__icon *,.ck-media__wrapper[data-oembed-url*="google.com/maps"] .ck-media__placeholder__icon *,.ck-media__wrapper[data-oembed-url*="instagram.com"] .ck-media__placeholder__icon *,.ck-media__wrapper[data-oembed-url*="twitter.com"] .ck-media__placeholder__icon *{display:none}.ck-editor__editable:not(.ck-read-only) .ck-media__wrapper>:not(.ck-media__placeholder),.ck-editor__editable:not(.ck-read-only) .ck-widget:not(.ck-widget_selected) .ck-media__placeholder{pointer-events:none}:root{--ck-media-embed-placeholder-icon-size:3em;--ck-color-media-embed-placeholder-url-text:#757575;--ck-color-media-embed-placeholder-url-text-hover:var(--ck-color-base-text)}.ck-media__wrapper{margin:0 auto}.ck-media__wrapper .ck-media__placeholder{padding:calc(var(--ck-spacing-standard)*3);background:var(--ck-color-base-foreground)}.ck-media__wrapper .ck-media__placeholder .ck-media__placeholder__icon{min-width:var(--ck-media-embed-placeholder-icon-size);height:var(--ck-media-embed-placeholder-icon-size);margin-bottom:var(--ck-spacing-large);background-position:50%;background-size:cover}.ck-media__wrapper .ck-media__placeholder .ck-media__placeholder__icon .ck-icon{width:100%;height:100%}.ck-media__wrapper .ck-media__placeholder .ck-media__placeholder__url__text{color:var(--ck-color-media-embed-placeholder-url-text);white-space:nowrap;text-align:center;font-style:italic;text-overflow:ellipsis}.ck-media__wrapper .ck-media__placeholder .ck-media__placeholder__url__text:hover{color:var(--ck-color-media-embed-placeholder-url-text-hover);cursor:pointer;text-decoration:underline}.ck-media__wrapper[data-oembed-url*="open.spotify.com"]{max-width:300px;max-height:380px}.ck-media__wrapper[data-oembed-url*="google.com/maps"] .ck-media__placeholder__icon{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNTAuMzc4IiBoZWlnaHQ9IjI1NC4xNjciIHZpZXdCb3g9IjAgMCA2Ni4yNDYgNjcuMjQ4Ij48ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtMTcyLjUzMSAtMjE4LjQ1NSkgc2NhbGUoLjk4MDEyKSI+PHJlY3Qgcnk9IjUuMjM4IiByeD0iNS4yMzgiIHk9IjIzMS4zOTkiIHg9IjE3Ni4wMzEiIGhlaWdodD0iNjAuMDk5IiB3aWR0aD0iNjAuMDk5IiBmaWxsPSIjMzRhNjY4IiBwYWludC1vcmRlcj0ibWFya2VycyBzdHJva2UgZmlsbCIvPjxwYXRoIGQ9Ik0yMDYuNDc3IDI2MC45bC0yOC45ODcgMjguOTg3YTUuMjE4IDUuMjE4IDAgMDAzLjc4IDEuNjFoNDkuNjIxYzEuNjk0IDAgMy4xOS0uNzk4IDQuMTQ2LTIuMDM3eiIgZmlsbD0iIzVjODhjNSIvPjxwYXRoIGQ9Ik0yMjYuNzQyIDIyMi45ODhjLTkuMjY2IDAtMTYuNzc3IDcuMTctMTYuNzc3IDE2LjAxNC4wMDcgMi43NjIuNjYzIDUuNDc0IDIuMDkzIDcuODc1LjQzLjcwMy44MyAxLjQwOCAxLjE5IDIuMTA3LjMzMy41MDIuNjUgMS4wMDUuOTUgMS41MDguMzQzLjQ3Ny42NzMuOTU3Ljk4OCAxLjQ0IDEuMzEgMS43NjkgMi41IDMuNTAyIDMuNjM3IDUuMTY4Ljc5MyAxLjI3NSAxLjY4MyAyLjY0IDIuNDY2IDMuOTkgMi4zNjMgNC4wOTQgNC4wMDcgOC4wOTIgNC42IDEzLjkxNHYuMDEyYy4xODIuNDEyLjUxNi42NjYuODc5LjY2Ny40MDMtLjAwMS43NjgtLjMxNC45My0uNzk5LjYwMy01Ljc1NiAyLjIzOC05LjcyOSA0LjU4NS0xMy43OTQuNzgyLTEuMzUgMS42NzMtMi43MTUgMi40NjUtMy45OSAxLjEzNy0xLjY2NiAyLjMyOC0zLjQgMy42MzgtNS4xNjkuMzE1LS40ODIuNjQ1LS45NjIuOTg4LTEuNDM5LjMtLjUwMy42MTctMS4wMDYuOTUtMS41MDguMzU5LS43Ljc2LTEuNDA0IDEuMTktMi4xMDcgMS40MjYtMi40MDIgMi01LjExNCAyLjAwNC03Ljg3NSAwLTguODQ0LTcuNTExLTE2LjAxNC0xNi43NzYtMTYuMDE0eiIgZmlsbD0iI2RkNGIzZSIgcGFpbnQtb3JkZXI9Im1hcmtlcnMgc3Ryb2tlIGZpbGwiLz48ZWxsaXBzZSByeT0iNS41NjQiIHJ4PSI1LjgyOCIgY3k9IjIzOS4wMDIiIGN4PSIyMjYuNzQyIiBmaWxsPSIjODAyZDI3IiBwYWludC1vcmRlcj0ibWFya2VycyBzdHJva2UgZmlsbCIvPjxwYXRoIGQ9Ik0xOTAuMzAxIDIzNy4yODNjLTQuNjcgMC04LjQ1NyAzLjg1My04LjQ1NyA4LjYwNnMzLjc4NiA4LjYwNyA4LjQ1NyA4LjYwN2MzLjA0MyAwIDQuODA2LS45NTggNi4zMzctMi41MTYgMS41My0xLjU1NyAyLjA4Ny0zLjkxMyAyLjA4Ny02LjI5IDAtLjM2Mi0uMDIzLS43MjItLjA2NC0xLjA3OWgtOC4yNTd2My4wNDNoNC44NWMtLjE5Ny43NTktLjUzMSAxLjQ1LTEuMDU4IDEuOTg2LS45NDIuOTU4LTIuMDI4IDEuNTQ4LTMuOTAxIDEuNTQ4LTIuODc2IDAtNS4yMDgtMi4zNzItNS4yMDgtNS4yOTkgMC0yLjkyNiAyLjMzMi01LjI5OSA1LjIwOC01LjI5OSAxLjM5OSAwIDIuNjE4LjQwNyAzLjU4NCAxLjI5M2wyLjM4MS0yLjM4YzAtLjAwMi0uMDAzLS4wMDQtLjAwNC0uMDA1LTEuNTg4LTEuNTI0LTMuNjItMi4yMTUtNS45NTUtMi4yMTV6bTQuNDMgNS42NmwuMDAzLjAwNnYtLjAwM3oiIGZpbGw9IiNmZmYiIHBhaW50LW9yZGVyPSJtYXJrZXJzIHN0cm9rZSBmaWxsIi8+PHBhdGggZD0iTTIxNS4xODQgMjUxLjkyOWwtNy45OCA3Ljk3OSAyOC40NzcgMjguNDc1YTUuMjMzIDUuMjMzIDAgMDAuNDQ5LTIuMTIzdi0zMS4xNjVjLS40NjkuNjc1LS45MzQgMS4zNDktMS4zODIgMi4wMDUtLjc5MiAxLjI3NS0xLjY4MiAyLjY0LTIuNDY1IDMuOTktMi4zNDcgNC4wNjUtMy45ODIgOC4wMzgtNC41ODUgMTMuNzk0LS4xNjIuNDg1LS41MjcuNzk4LS45My43OTktLjM2My0uMDAxLS42OTctLjI1NS0uODc5LS42Njd2LS4wMTJjLS41OTMtNS44MjItMi4yMzctOS44Mi00LjYtMTMuOTE0LS43ODMtMS4zNS0xLjY3My0yLjcxNS0yLjQ2Ni0zLjk5LTEuMTM3LTEuNjY2LTIuMzI3LTMuNC0zLjYzNy01LjE2OWwtLjAwMi0uMDAzeiIgZmlsbD0iI2MzYzNjMyIvPjxwYXRoIGQ9Ik0yMTIuOTgzIDI0OC40OTVsLTM2Ljk1MiAzNi45NTN2LjgxMmE1LjIyNyA1LjIyNyAwIDAwNS4yMzggNS4yMzhoMS4wMTVsMzUuNjY2LTM1LjY2NmExMzYuMjc1IDEzNi4yNzUgMCAwMC0yLjc2NC0zLjkgMzcuNTc1IDM3LjU3NSAwIDAwLS45ODktMS40NCAzNS4xMjcgMzUuMTI3IDAgMDAtLjk1LTEuNTA4Yy0uMDgzLS4xNjItLjE3Ni0uMzI2LS4yNjQtLjQ4OXoiIGZpbGw9IiNmZGRjNGYiIHBhaW50LW9yZGVyPSJtYXJrZXJzIHN0cm9rZSBmaWxsIi8+PHBhdGggZD0iTTIxMS45OTggMjYxLjA4M2wtNi4xNTIgNi4xNTEgMjQuMjY0IDI0LjI2NGguNzgxYTUuMjI3IDUuMjI3IDAgMDA1LjIzOS01LjIzOHYtMS4wNDV6IiBmaWxsPSIjZmZmIiBwYWludC1vcmRlcj0ibWFya2VycyBzdHJva2UgZmlsbCIvPjwvZz48L3N2Zz4=)}.ck-media__wrapper[data-oembed-url*="facebook.com"] .ck-media__placeholder{background:#4268b3}.ck-media__wrapper[data-oembed-url*="facebook.com"] .ck-media__placeholder .ck-media__placeholder__icon{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTAyNCIgaGVpZ2h0PSIxMDI0IiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxwYXRoIGQ9Ik05NjcuNDg0IDBINTYuNTE3QzI1LjMwNCAwIDAgMjUuMzA0IDAgNTYuNTE3djkxMC45NjZDMCA5OTguNjk0IDI1LjI5NyAxMDI0IDU2LjUyMiAxMDI0SDU0N1Y2MjhINDE0VjQ3M2gxMzNWMzU5LjAyOWMwLTEzMi4yNjIgODAuNzczLTIwNC4yODIgMTk4Ljc1Ni0yMDQuMjgyIDU2LjUxMyAwIDEwNS4wODYgNC4yMDggMTE5LjI0NCA2LjA4OVYyOTlsLTgxLjYxNi4wMzdjLTYzLjk5MyAwLTc2LjM4NCAzMC40OTItNzYuMzg0IDc1LjIzNlY0NzNoMTUzLjQ4N2wtMTkuOTg2IDE1NUg3MDd2Mzk2aDI2MC40ODRjMzEuMjEzIDAgNTYuNTE2LTI1LjMwMyA1Ni41MTYtNTYuNTE2VjU2LjUxNUMxMDI0IDI1LjMwMyA5OTguNjk3IDAgOTY3LjQ4NCAwIiBmaWxsPSIjRkZGRkZFIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiLz48L3N2Zz4=)}.ck-media__wrapper[data-oembed-url*="facebook.com"] .ck-media__placeholder .ck-media__placeholder__url__text{color:#cdf}.ck-media__wrapper[data-oembed-url*="facebook.com"] .ck-media__placeholder .ck-media__placeholder__url__text:hover{color:#fff}.ck-media__wrapper[data-oembed-url*="instagram.com"] .ck-media__placeholder{background:linear-gradient(-135deg,#1400c7,#b800b1,#f50000)}.ck-media__wrapper[data-oembed-url*="instagram.com"] .ck-media__placeholder .ck-media__placeholder__icon{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTA0IiBoZWlnaHQ9IjUwNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayI+PGRlZnM+PHBhdGggaWQ9ImEiIGQ9Ik0wIC4xNTloNTAzLjg0MVY1MDMuOTRIMHoiLz48L2RlZnM+PGcgZmlsbD0ibm9uZSIgZmlsbC1ydWxlPSJldmVub2RkIj48bWFzayBpZD0iYiIgZmlsbD0iI2ZmZiI+PHVzZSB4bGluazpocmVmPSIjYSIvPjwvbWFzaz48cGF0aCBkPSJNMjUxLjkyMS4xNTljLTY4LjQxOCAwLTc2Ljk5Ny4yOS0xMDMuODY3IDEuNTE2LTI2LjgxNCAxLjIyMy00NS4xMjcgNS40ODItNjEuMTUxIDExLjcxLTE2LjU2NiA2LjQzNy0zMC42MTUgMTUuMDUxLTQ0LjYyMSAyOS4wNTYtMTQuMDA1IDE0LjAwNi0yMi42MTkgMjguMDU1LTI5LjA1NiA0NC42MjEtNi4yMjggMTYuMDI0LTEwLjQ4NyAzNC4zMzctMTEuNzEgNjEuMTUxQy4yOSAxNzUuMDgzIDAgMTgzLjY2MiAwIDI1Mi4wOGMwIDY4LjQxNy4yOSA3Ni45OTYgMS41MTYgMTAzLjg2NiAxLjIyMyAyNi44MTQgNS40ODIgNDUuMTI3IDExLjcxIDYxLjE1MSA2LjQzNyAxNi41NjYgMTUuMDUxIDMwLjYxNSAyOS4wNTYgNDQuNjIxIDE0LjAwNiAxNC4wMDUgMjguMDU1IDIyLjYxOSA0NC42MjEgMjkuMDU3IDE2LjAyNCA2LjIyNyAzNC4zMzcgMTAuNDg2IDYxLjE1MSAxMS43MDkgMjYuODcgMS4yMjYgMzUuNDQ5IDEuNTE2IDEwMy44NjcgMS41MTYgNjguNDE3IDAgNzYuOTk2LS4yOSAxMDMuODY2LTEuNTE2IDI2LjgxNC0xLjIyMyA0NS4xMjctNS40ODIgNjEuMTUxLTExLjcwOSAxNi41NjYtNi40MzggMzAuNjE1LTE1LjA1MiA0NC42MjEtMjkuMDU3IDE0LjAwNS0xNC4wMDYgMjIuNjE5LTI4LjA1NSAyOS4wNTctNDQuNjIxIDYuMjI3LTE2LjAyNCAxMC40ODYtMzQuMzM3IDExLjcwOS02MS4xNTEgMS4yMjYtMjYuODcgMS41MTYtMzUuNDQ5IDEuNTE2LTEwMy44NjYgMC02OC40MTgtLjI5LTc2Ljk5Ny0xLjUxNi0xMDMuODY3LTEuMjIzLTI2LjgxNC01LjQ4Mi00NS4xMjctMTEuNzA5LTYxLjE1MS02LjQzOC0xNi41NjYtMTUuMDUyLTMwLjYxNS0yOS4wNTctNDQuNjIxLTE0LjAwNi0xNC4wMDUtMjguMDU1LTIyLjYxOS00NC42MjEtMjkuMDU2LTE2LjAyNC02LjIyOC0zNC4zMzctMTAuNDg3LTYxLjE1MS0xMS43MUMzMjguOTE3LjQ0OSAzMjAuMzM4LjE1OSAyNTEuOTIxLjE1OXptMCA0NS4zOTFjNjcuMjY1IDAgNzUuMjMzLjI1NyAxMDEuNzk3IDEuNDY5IDI0LjU2MiAxLjEyIDM3LjkwMSA1LjIyNCA0Ni43NzggOC42NzQgMTEuNzU5IDQuNTcgMjAuMTUxIDEwLjAyOSAyOC45NjYgMTguODQ1IDguODE2IDguODE1IDE0LjI3NSAxNy4yMDcgMTguODQ1IDI4Ljk2NiAzLjQ1IDguODc3IDcuNTU0IDIyLjIxNiA4LjY3NCA0Ni43NzggMS4yMTIgMjYuNTY0IDEuNDY5IDM0LjUzMiAxLjQ2OSAxMDEuNzk4IDAgNjcuMjY1LS4yNTcgNzUuMjMzLTEuNDY5IDEwMS43OTctMS4xMiAyNC41NjItNS4yMjQgMzcuOTAxLTguNjc0IDQ2Ljc3OC00LjU3IDExLjc1OS0xMC4wMjkgMjAuMTUxLTE4Ljg0NSAyOC45NjYtOC44MTUgOC44MTYtMTcuMjA3IDE0LjI3NS0yOC45NjYgMTguODQ1LTguODc3IDMuNDUtMjIuMjE2IDcuNTU0LTQ2Ljc3OCA4LjY3NC0yNi41NiAxLjIxMi0zNC41MjcgMS40NjktMTAxLjc5NyAxLjQ2OS02Ny4yNzEgMC03NS4yMzctLjI1Ny0xMDEuNzk4LTEuNDY5LTI0LjU2Mi0xLjEyLTM3LjkwMS01LjIyNC00Ni43NzgtOC42NzQtMTEuNzU5LTQuNTctMjAuMTUxLTEwLjAyOS0yOC45NjYtMTguODQ1LTguODE1LTguODE1LTE0LjI3NS0xNy4yMDctMTguODQ1LTI4Ljk2Ni0zLjQ1LTguODc3LTcuNTU0LTIyLjIxNi04LjY3NC00Ni43NzgtMS4yMTItMjYuNTY0LTEuNDY5LTM0LjUzMi0xLjQ2OS0xMDEuNzk3IDAtNjcuMjY2LjI1Ny03NS4yMzQgMS40NjktMTAxLjc5OCAxLjEyLTI0LjU2MiA1LjIyNC0zNy45MDEgOC42NzQtNDYuNzc4IDQuNTctMTEuNzU5IDEwLjAyOS0yMC4xNTEgMTguODQ1LTI4Ljk2NiA4LjgxNS04LjgxNiAxNy4yMDctMTQuMjc1IDI4Ljk2Ni0xOC44NDUgOC44NzctMy40NSAyMi4yMTYtNy41NTQgNDYuNzc4LTguNjc0IDI2LjU2NC0xLjIxMiAzNC41MzItMS40NjkgMTAxLjc5OC0xLjQ2OXoiIGZpbGw9IiNGRkYiIG1hc2s9InVybCgjYikiLz48cGF0aCBkPSJNMjUxLjkyMSAzMzYuMDUzYy00Ni4zNzggMC04My45NzQtMzcuNTk2LTgzLjk3NC04My45NzMgMC00Ni4zNzggMzcuNTk2LTgzLjk3NCA4My45NzQtODMuOTc0IDQ2LjM3NyAwIDgzLjk3MyAzNy41OTYgODMuOTczIDgzLjk3NCAwIDQ2LjM3Ny0zNy41OTYgODMuOTczLTgzLjk3MyA4My45NzN6bTAtMjEzLjMzOGMtNzEuNDQ3IDAtMTI5LjM2NSA1Ny45MTgtMTI5LjM2NSAxMjkuMzY1IDAgNzEuNDQ2IDU3LjkxOCAxMjkuMzY0IDEyOS4zNjUgMTI5LjM2NCA3MS40NDYgMCAxMjkuMzY0LTU3LjkxOCAxMjkuMzY0LTEyOS4zNjQgMC03MS40NDctNTcuOTE4LTEyOS4zNjUtMTI5LjM2NC0xMjkuMzY1ek00MTYuNjI3IDExNy42MDRjMCAxNi42OTYtMTMuNTM1IDMwLjIzLTMwLjIzMSAzMC4yMy0xNi42OTUgMC0zMC4yMy0xMy41MzQtMzAuMjMtMzAuMjMgMC0xNi42OTYgMTMuNTM1LTMwLjIzMSAzMC4yMy0zMC4yMzEgMTYuNjk2IDAgMzAuMjMxIDEzLjUzNSAzMC4yMzEgMzAuMjMxIiBmaWxsPSIjRkZGIi8+PC9nPjwvc3ZnPg==)}.ck-media__wrapper[data-oembed-url*="instagram.com"] .ck-media__placeholder .ck-media__placeholder__url__text{color:#ffe0fe}.ck-media__wrapper[data-oembed-url*="instagram.com"] .ck-media__placeholder .ck-media__placeholder__url__text:hover{color:#fff}.ck-media__wrapper[data-oembed-url*="twitter.com"] .ck.ck-media__placeholder{background:linear-gradient(90deg,#71c6f4,#0d70a5)}.ck-media__wrapper[data-oembed-url*="twitter.com"] .ck.ck-media__placeholder .ck-media__placeholder__icon{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MDAgNDAwIj48cGF0aCBkPSJNNDAwIDIwMGMwIDExMC41LTg5LjUgMjAwLTIwMCAyMDBTMCAzMTAuNSAwIDIwMCA4OS41IDAgMjAwIDBzMjAwIDg5LjUgMjAwIDIwMHpNMTYzLjQgMzA1LjVjODguNyAwIDEzNy4yLTczLjUgMTM3LjItMTM3LjIgMC0yLjEgMC00LjItLjEtNi4yIDkuNC02LjggMTcuNi0xNS4zIDI0LjEtMjUtOC42IDMuOC0xNy45IDYuNC0yNy43IDcuNiAxMC02IDE3LjYtMTUuNCAyMS4yLTI2LjctOS4zIDUuNS0xOS42IDkuNS0zMC42IDExLjctOC44LTkuNC0yMS4zLTE1LjItMzUuMi0xNS4yLTI2LjYgMC00OC4yIDIxLjYtNDguMiA0OC4yIDAgMy44LjQgNy41IDEuMyAxMS00MC4xLTItNzUuNi0yMS4yLTk5LjQtNTAuNC00LjEgNy4xLTYuNSAxNS40LTYuNSAyNC4yIDAgMTYuNyA4LjUgMzEuNSAyMS41IDQwLjEtNy45LS4yLTE1LjMtMi40LTIxLjgtNnYuNmMwIDIzLjQgMTYuNiA0Mi44IDM4LjcgNDcuMy00IDEuMS04LjMgMS43LTEyLjcgMS43LTMuMSAwLTYuMS0uMy05LjEtLjkgNi4xIDE5LjIgMjMuOSAzMy4xIDQ1IDMzLjUtMTYuNSAxMi45LTM3LjMgMjAuNi01OS45IDIwLjYtMy45IDAtNy43LS4yLTExLjUtLjcgMjEuMSAxMy44IDQ2LjUgMjEuOCA3My43IDIxLjgiIGZpbGw9IiNmZmYiLz48L3N2Zz4=)}.ck-media__wrapper[data-oembed-url*="twitter.com"] .ck.ck-media__placeholder .ck-media__placeholder__url__text{color:#b8e6ff}.ck-media__wrapper[data-oembed-url*="twitter.com"] .ck.ck-media__placeholder .ck-media__placeholder__url__text:hover{color:#fff}',"",{version:3,sources:["webpack://./node_modules/@ckeditor/ckeditor5-media-embed/theme/mediaembedediting.css","webpack://./node_modules/@ckeditor/ckeditor5-ui/theme/components/tooltip/mixins/_tooltip.css","webpack://./node_modules/@ckeditor/ckeditor5-theme-lark/theme/ckeditor5-media-embed/mediaembedediting.css"],names:[],mappings:"AAQC,0CACC,YAAa,CACb,qBAAsB,CACtB,kBAmBD,CCpBA,kFACC,aAqBD,CAHC,oBAnBD,kFAoBE,YAEF,CADC,CDlBA,sEAIC,cAAe,CAEf,iBAUD,CCoBD,wFACC,kBAAmB,CACnB,SACD,CD3BE,wGACC,eAAgB,CAChB,aACD,CAQD,+UACC,YACD,CAYF,2LACC,mBACD,CE/CA,MACC,0CAA2C,CAE3C,mDAA4D,CAC5D,2EACD,CAEA,mBACC,aA4FD,CA1FC,0CACC,0CAA+C,CAC/C,0CA4BD,CA1BC,uEACC,qDAAsD,CACtD,kDAAmD,CACnD,qCAAsC,CACtC,uBAA2B,CAC3B,qBAMD,CAJC,gFACC,UAAW,CACX,WACD,CAGD,4EACC,sDAAuD,CACvD,kBAAmB,CACnB,iBAAkB,CAClB,iBAAkB,CAClB,sBAOD,CALC,kFACC,4DAA6D,CAC7D,cAAe,CACf,yBACD,CAIF,wDACC,eAAgB,CAChB,gBACD,CAEA,oFACC,gvGACD,CAEA,2EACC,kBAaD,CAXC,wGACC,orBACD,CAEA,6GACC,UAKD,CAHC,mHACC,UACD,CAIF,4EACC,2DAcD,CAZC,yGACC,4jHACD,CAGA,8GACC,aAKD,CAHC,oHACC,UACD,CAIF,6EAEC,iDAaD,CAXC,0GACC,48BACD,CAEA,+GACC,aAKD,CAHC,qHACC,UACD",sourcesContent:['/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n@import "@ckeditor/ckeditor5-ui/theme/components/tooltip/mixins/_tooltip.css";\n\n.ck-media__wrapper {\n\t& .ck-media__placeholder {\n\t\tdisplay: flex;\n\t\tflex-direction: column;\n\t\talign-items: center;\n\n\t\t& .ck-media__placeholder__url {\n\t\t\t@mixin ck-tooltip_enabled;\n\n\t\t\t/* Otherwise the URL will overflow when the content is very narrow. */\n\t\t\tmax-width: 100%;\n\n\t\t\tposition: relative;\n\n\t\t\t&:hover {\n\t\t\t\t@mixin ck-tooltip_visible;\n\t\t\t}\n\n\t\t\t& .ck-media__placeholder__url__text {\n\t\t\t\toverflow: hidden;\n\t\t\t\tdisplay: block;\n\t\t\t}\n\t\t}\n\t}\n\n\t&[data-oembed-url*="twitter.com"],\n\t&[data-oembed-url*="google.com/maps"],\n\t&[data-oembed-url*="facebook.com"],\n\t&[data-oembed-url*="instagram.com"] {\n\t\t& .ck-media__placeholder__icon * {\n\t\t\tdisplay: none;\n\t\t}\n\t}\n}\n\n/* Disable all mouse interaction as long as the editor is not read–only.\n https://github.com/ckeditor/ckeditor5-media-embed/issues/58 */\n.ck-editor__editable:not(.ck-read-only) .ck-media__wrapper > *:not(.ck-media__placeholder) {\n\tpointer-events: none;\n}\n\n/* Disable all mouse interaction when the widget is not selected (e.g. to avoid opening links by accident).\n https://github.com/ckeditor/ckeditor5-media-embed/issues/18 */\n.ck-editor__editable:not(.ck-read-only) .ck-widget:not(.ck-widget_selected) .ck-media__placeholder {\n\tpointer-events: none;\n}\n',"/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * Enables the tooltip, which is the tooltip is in DOM but\n * not yet displayed.\n */\n@define-mixin ck-tooltip_enabled {\n\t& .ck-tooltip {\n\t\tdisplay: block;\n\n\t\t/*\n\t\t * Don't display tooltips in devices which don't support :hover.\n\t\t * In fact, it's all about iOS, which forces user to click UI elements twice to execute\n\t\t * the primary action, when tooltips are enabled.\n\t\t *\n\t\t * Q: OK, but why not the following query?\n\t\t *\n\t\t * @media (hover) {\n\t\t * display: block;\n\t\t * }\n\t\t *\n\t\t * A: Because FF does not support it and it would completely disable tooltips\n\t\t * in that browser.\n\t\t *\n\t\t * More in https://github.com/ckeditor/ckeditor5/issues/920.\n\t\t */\n\t\t@media (hover:none) {\n\t\t\tdisplay: none;\n\t\t}\n\t}\n}\n\n/**\n * Disables the tooltip making it disappear from DOM.\n */\n@define-mixin ck-tooltip_disabled {\n\t& .ck-tooltip {\n\t\tdisplay: none;\n\t}\n}\n\n/**\n * Shows the tooltip, which is already in DOM.\n * Requires `ck-tooltip_enabled` first.\n */\n@define-mixin ck-tooltip_visible {\n\t& .ck-tooltip {\n\t\tvisibility: visible;\n\t\topacity: 1;\n\t}\n}\n",'/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n:root {\n\t--ck-media-embed-placeholder-icon-size: 3em;\n\n\t--ck-color-media-embed-placeholder-url-text: hsl(0, 0%, 46%);\n\t--ck-color-media-embed-placeholder-url-text-hover: var(--ck-color-base-text);\n}\n\n.ck-media__wrapper {\n\tmargin: 0 auto;\n\n\t& .ck-media__placeholder {\n\t\tpadding: calc( 3 * var(--ck-spacing-standard) );\n\t\tbackground: var(--ck-color-base-foreground);\n\n\t\t& .ck-media__placeholder__icon {\n\t\t\tmin-width: var(--ck-media-embed-placeholder-icon-size);\n\t\t\theight: var(--ck-media-embed-placeholder-icon-size);\n\t\t\tmargin-bottom: var(--ck-spacing-large);\n\t\t\tbackground-position: center;\n\t\t\tbackground-size: cover;\n\n\t\t\t& .ck-icon {\n\t\t\t\twidth: 100%;\n\t\t\t\theight: 100%;\n\t\t\t}\n\t\t}\n\n\t\t& .ck-media__placeholder__url__text {\n\t\t\tcolor: var(--ck-color-media-embed-placeholder-url-text);\n\t\t\twhite-space: nowrap;\n\t\t\ttext-align: center;\n\t\t\tfont-style: italic;\n\t\t\ttext-overflow: ellipsis;\n\n\t\t\t&:hover {\n\t\t\t\tcolor: var(--ck-color-media-embed-placeholder-url-text-hover);\n\t\t\t\tcursor: pointer;\n\t\t\t\ttext-decoration: underline;\n\t\t\t}\n\t\t}\n\t}\n\n\t&[data-oembed-url*="open.spotify.com"] {\n\t\tmax-width: 300px;\n\t\tmax-height: 380px;\n\t}\n\n\t&[data-oembed-url*="google.com/maps"] .ck-media__placeholder__icon {\n\t\tbackground-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNTAuMzc4IiBoZWlnaHQ9IjI1NC4xNjciIHZpZXdCb3g9IjAgMCA2Ni4yNDYgNjcuMjQ4Ij48ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtMTcyLjUzMSAtMjE4LjQ1NSkgc2NhbGUoLjk4MDEyKSI+PHJlY3Qgcnk9IjUuMjM4IiByeD0iNS4yMzgiIHk9IjIzMS4zOTkiIHg9IjE3Ni4wMzEiIGhlaWdodD0iNjAuMDk5IiB3aWR0aD0iNjAuMDk5IiBmaWxsPSIjMzRhNjY4IiBwYWludC1vcmRlcj0ibWFya2VycyBzdHJva2UgZmlsbCIvPjxwYXRoIGQ9Ik0yMDYuNDc3IDI2MC45bC0yOC45ODcgMjguOTg3YTUuMjE4IDUuMjE4IDAgMCAwIDMuNzggMS42MWg0OS42MjFjMS42OTQgMCAzLjE5LS43OTggNC4xNDYtMi4wMzd6IiBmaWxsPSIjNWM4OGM1Ii8+PHBhdGggZD0iTTIyNi43NDIgMjIyLjk4OGMtOS4yNjYgMC0xNi43NzcgNy4xNy0xNi43NzcgMTYuMDE0LjAwNyAyLjc2Mi42NjMgNS40NzQgMi4wOTMgNy44NzUuNDMuNzAzLjgzIDEuNDA4IDEuMTkgMi4xMDcuMzMzLjUwMi42NSAxLjAwNS45NSAxLjUwOC4zNDMuNDc3LjY3My45NTcuOTg4IDEuNDQgMS4zMSAxLjc2OSAyLjUgMy41MDIgMy42MzcgNS4xNjguNzkzIDEuMjc1IDEuNjgzIDIuNjQgMi40NjYgMy45OSAyLjM2MyA0LjA5NCA0LjAwNyA4LjA5MiA0LjYgMTMuOTE0di4wMTJjLjE4Mi40MTIuNTE2LjY2Ni44NzkuNjY3LjQwMy0uMDAxLjc2OC0uMzE0LjkzLS43OTkuNjAzLTUuNzU2IDIuMjM4LTkuNzI5IDQuNTg1LTEzLjc5NC43ODItMS4zNSAxLjY3My0yLjcxNSAyLjQ2NS0zLjk5IDEuMTM3LTEuNjY2IDIuMzI4LTMuNCAzLjYzOC01LjE2OS4zMTUtLjQ4Mi42NDUtLjk2Mi45ODgtMS40MzkuMy0uNTAzLjYxNy0xLjAwNi45NS0xLjUwOC4zNTktLjcuNzYtMS40MDQgMS4xOS0yLjEwNyAxLjQyNi0yLjQwMiAyLTUuMTE0IDIuMDA0LTcuODc1IDAtOC44NDQtNy41MTEtMTYuMDE0LTE2Ljc3Ni0xNi4wMTR6IiBmaWxsPSIjZGQ0YjNlIiBwYWludC1vcmRlcj0ibWFya2VycyBzdHJva2UgZmlsbCIvPjxlbGxpcHNlIHJ5PSI1LjU2NCIgcng9IjUuODI4IiBjeT0iMjM5LjAwMiIgY3g9IjIyNi43NDIiIGZpbGw9IiM4MDJkMjciIHBhaW50LW9yZGVyPSJtYXJrZXJzIHN0cm9rZSBmaWxsIi8+PHBhdGggZD0iTTE5MC4zMDEgMjM3LjI4M2MtNC42NyAwLTguNDU3IDMuODUzLTguNDU3IDguNjA2czMuNzg2IDguNjA3IDguNDU3IDguNjA3YzMuMDQzIDAgNC44MDYtLjk1OCA2LjMzNy0yLjUxNiAxLjUzLTEuNTU3IDIuMDg3LTMuOTEzIDIuMDg3LTYuMjkgMC0uMzYyLS4wMjMtLjcyMi0uMDY0LTEuMDc5aC04LjI1N3YzLjA0M2g0Ljg1Yy0uMTk3Ljc1OS0uNTMxIDEuNDUtMS4wNTggMS45ODYtLjk0Mi45NTgtMi4wMjggMS41NDgtMy45MDEgMS41NDgtMi44NzYgMC01LjIwOC0yLjM3Mi01LjIwOC01LjI5OSAwLTIuOTI2IDIuMzMyLTUuMjk5IDUuMjA4LTUuMjk5IDEuMzk5IDAgMi42MTguNDA3IDMuNTg0IDEuMjkzbDIuMzgxLTIuMzhjMC0uMDAyLS4wMDMtLjAwNC0uMDA0LS4wMDUtMS41ODgtMS41MjQtMy42Mi0yLjIxNS01Ljk1NS0yLjIxNXptNC40MyA1LjY2bC4wMDMuMDA2di0uMDAzeiIgZmlsbD0iI2ZmZiIgcGFpbnQtb3JkZXI9Im1hcmtlcnMgc3Ryb2tlIGZpbGwiLz48cGF0aCBkPSJNMjE1LjE4NCAyNTEuOTI5bC03Ljk4IDcuOTc5IDI4LjQ3NyAyOC40NzVjLjI4Ny0uNjQ5LjQ0OS0xLjM2Ni40NDktMi4xMjN2LTMxLjE2NWMtLjQ2OS42NzUtLjkzNCAxLjM0OS0xLjM4MiAyLjAwNS0uNzkyIDEuMjc1LTEuNjgyIDIuNjQtMi40NjUgMy45OS0yLjM0NyA0LjA2NS0zLjk4MiA4LjAzOC00LjU4NSAxMy43OTQtLjE2Mi40ODUtLjUyNy43OTgtLjkzLjc5OS0uMzYzLS4wMDEtLjY5Ny0uMjU1LS44NzktLjY2N3YtLjAxMmMtLjU5My01LjgyMi0yLjIzNy05LjgyLTQuNi0xMy45MTQtLjc4My0xLjM1LTEuNjczLTIuNzE1LTIuNDY2LTMuOTktMS4xMzctMS42NjYtMi4zMjctMy40LTMuNjM3LTUuMTY5bC0uMDAyLS4wMDN6IiBmaWxsPSIjYzNjM2MzIi8+PHBhdGggZD0iTTIxMi45ODMgMjQ4LjQ5NWwtMzYuOTUyIDM2Ljk1M3YuODEyYTUuMjI3IDUuMjI3IDAgMCAwIDUuMjM4IDUuMjM4aDEuMDE1bDM1LjY2Ni0zNS42NjZhMTM2LjI3NSAxMzYuMjc1IDAgMCAwLTIuNzY0LTMuOSAzNy41NzUgMzcuNTc1IDAgMCAwLS45ODktMS40NGMtLjI5OS0uNTAzLS42MTYtMS4wMDYtLjk1LTEuNTA4LS4wODMtLjE2Mi0uMTc2LS4zMjYtLjI2NC0uNDg5eiIgZmlsbD0iI2ZkZGM0ZiIgcGFpbnQtb3JkZXI9Im1hcmtlcnMgc3Ryb2tlIGZpbGwiLz48cGF0aCBkPSJNMjExLjk5OCAyNjEuMDgzbC02LjE1MiA2LjE1MSAyNC4yNjQgMjQuMjY0aC43ODFhNS4yMjcgNS4yMjcgMCAwIDAgNS4yMzktNS4yMzh2LTEuMDQ1eiIgZmlsbD0iI2ZmZiIgcGFpbnQtb3JkZXI9Im1hcmtlcnMgc3Ryb2tlIGZpbGwiLz48L2c+PC9zdmc+);\n\t}\n\n\t&[data-oembed-url*="facebook.com"] .ck-media__placeholder {\n\t\tbackground: hsl(220, 46%, 48%);\n\n\t\t& .ck-media__placeholder__icon {\n\t\t\tbackground-image: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48c3ZnIHdpZHRoPSIxMDI0cHgiIGhlaWdodD0iMTAyNHB4IiB2aWV3Qm94PSIwIDAgMTAyNCAxMDI0IiB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiPiAgICAgICAgPHRpdGxlPkZpbGwgMTwvdGl0bGU+ICAgIDxkZXNjPkNyZWF0ZWQgd2l0aCBTa2V0Y2guPC9kZXNjPiAgICA8ZGVmcz48L2RlZnM+ICAgIDxnIGlkPSJQYWdlLTEiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIxIiBmaWxsPSJub25lIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPiAgICAgICAgPGcgaWQ9ImZMb2dvX1doaXRlIiBmaWxsPSIjRkZGRkZFIj4gICAgICAgICAgICA8cGF0aCBkPSJNOTY3LjQ4NCwwIEw1Ni41MTcsMCBDMjUuMzA0LDAgMCwyNS4zMDQgMCw1Ni41MTcgTDAsOTY3LjQ4MyBDMCw5OTguNjk0IDI1LjI5NywxMDI0IDU2LjUyMiwxMDI0IEw1NDcsMTAyNCBMNTQ3LDYyOCBMNDE0LDYyOCBMNDE0LDQ3MyBMNTQ3LDQ3MyBMNTQ3LDM1OS4wMjkgQzU0NywyMjYuNzY3IDYyNy43NzMsMTU0Ljc0NyA3NDUuNzU2LDE1NC43NDcgQzgwMi4yNjksMTU0Ljc0NyA4NTAuODQyLDE1OC45NTUgODY1LDE2MC44MzYgTDg2NSwyOTkgTDc4My4zODQsMjk5LjAzNyBDNzE5LjM5MSwyOTkuMDM3IDcwNywzMjkuNTI5IDcwNywzNzQuMjczIEw3MDcsNDczIEw4NjAuNDg3LDQ3MyBMODQwLjUwMSw2MjggTDcwNyw2MjggTDcwNywxMDI0IEw5NjcuNDg0LDEwMjQgQzk5OC42OTcsMTAyNCAxMDI0LDk5OC42OTcgMTAyNCw5NjcuNDg0IEwxMDI0LDU2LjUxNSBDMTAyNCwyNS4zMDMgOTk4LjY5NywwIDk2Ny40ODQsMCIgaWQ9IkZpbGwtMSI+PC9wYXRoPiAgICAgICAgPC9nPiAgICA8L2c+PC9zdmc+);\n\t\t}\n\n\t\t& .ck-media__placeholder__url__text {\n\t\t\tcolor: hsl(220, 100%, 90%);\n\n\t\t\t&:hover {\n\t\t\t\tcolor: hsl(0, 0%, 100%);\n\t\t\t}\n\t\t}\n\t}\n\n\t&[data-oembed-url*="instagram.com"] .ck-media__placeholder {\n\t\tbackground: linear-gradient(-135deg,hsl(246, 100%, 39%),hsl(302, 100%, 36%),hsl(0, 100%, 48%));\n\n\t\t& .ck-media__placeholder__icon {\n\t\t\tbackground-image: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48c3ZnIHdpZHRoPSI1MDRweCIgaGVpZ2h0PSI1MDRweCIgdmlld0JveD0iMCAwIDUwNCA1MDQiIHZlcnNpb249IjEuMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayI+ICAgICAgICA8dGl0bGU+Z2x5cGgtbG9nb19NYXkyMDE2PC90aXRsZT4gICAgPGRlc2M+Q3JlYXRlZCB3aXRoIFNrZXRjaC48L2Rlc2M+ICAgIDxkZWZzPiAgICAgICAgPHBvbHlnb24gaWQ9InBhdGgtMSIgcG9pbnRzPSIwIDAuMTU5IDUwMy44NDEgMC4xNTkgNTAzLjg0MSA1MDMuOTQgMCA1MDMuOTQiPjwvcG9seWdvbj4gICAgPC9kZWZzPiAgICA8ZyBpZD0iZ2x5cGgtbG9nb19NYXkyMDE2IiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMSIgZmlsbD0ibm9uZSIgZmlsbC1ydWxlPSJldmVub2RkIj4gICAgICAgIDxnIGlkPSJHcm91cC0zIj4gICAgICAgICAgICA8bWFzayBpZD0ibWFzay0yIiBmaWxsPSJ3aGl0ZSI+ICAgICAgICAgICAgICAgIDx1c2UgeGxpbms6aHJlZj0iI3BhdGgtMSI+PC91c2U+ICAgICAgICAgICAgPC9tYXNrPiAgICAgICAgICAgIDxnIGlkPSJDbGlwLTIiPjwvZz4gICAgICAgICAgICA8cGF0aCBkPSJNMjUxLjkyMSwwLjE1OSBDMTgzLjUwMywwLjE1OSAxNzQuOTI0LDAuNDQ5IDE0OC4wNTQsMS42NzUgQzEyMS4yNCwyLjg5OCAxMDIuOTI3LDcuMTU3IDg2LjkwMywxMy4zODUgQzcwLjMzNywxOS44MjIgNTYuMjg4LDI4LjQzNiA0Mi4yODIsNDIuNDQxIEMyOC4yNzcsNTYuNDQ3IDE5LjY2Myw3MC40OTYgMTMuMjI2LDg3LjA2MiBDNi45OTgsMTAzLjA4NiAyLjczOSwxMjEuMzk5IDEuNTE2LDE0OC4yMTMgQzAuMjksMTc1LjA4MyAwLDE4My42NjIgMCwyNTIuMDggQzAsMzIwLjQ5NyAwLjI5LDMyOS4wNzYgMS41MTYsMzU1Ljk0NiBDMi43MzksMzgyLjc2IDYuOTk4LDQwMS4wNzMgMTMuMjI2LDQxNy4wOTcgQzE5LjY2Myw0MzMuNjYzIDI4LjI3Nyw0NDcuNzEyIDQyLjI4Miw0NjEuNzE4IEM1Ni4yODgsNDc1LjcyMyA3MC4zMzcsNDg0LjMzNyA4Ni45MDMsNDkwLjc3NSBDMTAyLjkyNyw0OTcuMDAyIDEyMS4yNCw1MDEuMjYxIDE0OC4wNTQsNTAyLjQ4NCBDMTc0LjkyNCw1MDMuNzEgMTgzLjUwMyw1MDQgMjUxLjkyMSw1MDQgQzMyMC4zMzgsNTA0IDMyOC45MTcsNTAzLjcxIDM1NS43ODcsNTAyLjQ4NCBDMzgyLjYwMSw1MDEuMjYxIDQwMC45MTQsNDk3LjAwMiA0MTYuOTM4LDQ5MC43NzUgQzQzMy41MDQsNDg0LjMzNyA0NDcuNTUzLDQ3NS43MjMgNDYxLjU1OSw0NjEuNzE4IEM0NzUuNTY0LDQ0Ny43MTIgNDg0LjE3OCw0MzMuNjYzIDQ5MC42MTYsNDE3LjA5NyBDNDk2Ljg0Myw0MDEuMDczIDUwMS4xMDIsMzgyLjc2IDUwMi4zMjUsMzU1Ljk0NiBDNTAzLjU1MSwzMjkuMDc2IDUwMy44NDEsMzIwLjQ5NyA1MDMuODQxLDI1Mi4wOCBDNTAzLjg0MSwxODMuNjYyIDUwMy41NTEsMTc1LjA4MyA1MDIuMzI1LDE0OC4yMTMgQzUwMS4xMDIsMTIxLjM5OSA0OTYuODQzLDEwMy4wODYgNDkwLjYxNiw4Ny4wNjIgQzQ4NC4xNzgsNzAuNDk2IDQ3NS41NjQsNTYuNDQ3IDQ2MS41NTksNDIuNDQxIEM0NDcuNTUzLDI4LjQzNiA0MzMuNTA0LDE5LjgyMiA0MTYuOTM4LDEzLjM4NSBDNDAwLjkxNCw3LjE1NyAzODIuNjAxLDIuODk4IDM1NS43ODcsMS42NzUgQzMyOC45MTcsMC40NDkgMzIwLjMzOCwwLjE1OSAyNTEuOTIxLDAuMTU5IFogTTI1MS45MjEsNDUuNTUgQzMxOS4xODYsNDUuNTUgMzI3LjE1NCw0NS44MDcgMzUzLjcxOCw0Ny4wMTkgQzM3OC4yOCw0OC4xMzkgMzkxLjYxOSw1Mi4yNDMgNDAwLjQ5Niw1NS42OTMgQzQxMi4yNTUsNjAuMjYzIDQyMC42NDcsNjUuNzIyIDQyOS40NjIsNzQuNTM4IEM0MzguMjc4LDgzLjM1MyA0NDMuNzM3LDkxLjc0NSA0NDguMzA3LDEwMy41MDQgQzQ1MS43NTcsMTEyLjM4MSA0NTUuODYxLDEyNS43MiA0NTYuOTgxLDE1MC4yODIgQzQ1OC4xOTMsMTc2Ljg0NiA0NTguNDUsMTg0LjgxNCA0NTguNDUsMjUyLjA4IEM0NTguNDUsMzE5LjM0NSA0NTguMTkzLDMyNy4zMTMgNDU2Ljk4MSwzNTMuODc3IEM0NTUuODYxLDM3OC40MzkgNDUxLjc1NywzOTEuNzc4IDQ0OC4zMDcsNDAwLjY1NSBDNDQzLjczNyw0MTIuNDE0IDQzOC4yNzgsNDIwLjgwNiA0MjkuNDYyLDQyOS42MjEgQzQyMC42NDcsNDM4LjQzNyA0MTIuMjU1LDQ0My44OTYgNDAwLjQ5Niw0NDguNDY2IEMzOTEuNjE5LDQ1MS45MTYgMzc4LjI4LDQ1Ni4wMiAzNTMuNzE4LDQ1Ny4xNCBDMzI3LjE1OCw0NTguMzUyIDMxOS4xOTEsNDU4LjYwOSAyNTEuOTIxLDQ1OC42MDkgQzE4NC42NSw0NTguNjA5IDE3Ni42ODQsNDU4LjM1MiAxNTAuMTIzLDQ1Ny4xNCBDMTI1LjU2MSw0NTYuMDIgMTEyLjIyMiw0NTEuOTE2IDEwMy4zNDUsNDQ4LjQ2NiBDOTEuNTg2LDQ0My44OTYgODMuMTk0LDQzOC40MzcgNzQuMzc5LDQyOS42MjEgQzY1LjU2NCw0MjAuODA2IDYwLjEwNCw0MTIuNDE0IDU1LjUzNCw0MDAuNjU1IEM1Mi4wODQsMzkxLjc3OCA0Ny45OCwzNzguNDM5IDQ2Ljg2LDM1My44NzcgQzQ1LjY0OCwzMjcuMzEzIDQ1LjM5MSwzMTkuMzQ1IDQ1LjM5MSwyNTIuMDggQzQ1LjM5MSwxODQuODE0IDQ1LjY0OCwxNzYuODQ2IDQ2Ljg2LDE1MC4yODIgQzQ3Ljk4LDEyNS43MiA1Mi4wODQsMTEyLjM4MSA1NS41MzQsMTAzLjUwNCBDNjAuMTA0LDkxLjc0NSA2NS41NjMsODMuMzUzIDc0LjM3OSw3NC41MzggQzgzLjE5NCw2NS43MjIgOTEuNTg2LDYwLjI2MyAxMDMuMzQ1LDU1LjY5MyBDMTEyLjIyMiw1Mi4yNDMgMTI1LjU2MSw0OC4xMzkgMTUwLjEyMyw0Ny4wMTkgQzE3Ni42ODcsNDUuODA3IDE4NC42NTUsNDUuNTUgMjUxLjkyMSw0NS41NSBaIiBpZD0iRmlsbC0xIiBmaWxsPSIjRkZGRkZGIiBtYXNrPSJ1cmwoI21hc2stMikiPjwvcGF0aD4gICAgICAgIDwvZz4gICAgICAgIDxwYXRoIGQ9Ik0yNTEuOTIxLDMzNi4wNTMgQzIwNS41NDMsMzM2LjA1MyAxNjcuOTQ3LDI5OC40NTcgMTY3Ljk0NywyNTIuMDggQzE2Ny45NDcsMjA1LjcwMiAyMDUuNTQzLDE2OC4xMDYgMjUxLjkyMSwxNjguMTA2IEMyOTguMjk4LDE2OC4xMDYgMzM1Ljg5NCwyMDUuNzAyIDMzNS44OTQsMjUyLjA4IEMzMzUuODk0LDI5OC40NTcgMjk4LjI5OCwzMzYuMDUzIDI1MS45MjEsMzM2LjA1MyBaIE0yNTEuOTIxLDEyMi43MTUgQzE4MC40NzQsMTIyLjcxNSAxMjIuNTU2LDE4MC42MzMgMTIyLjU1NiwyNTIuMDggQzEyMi41NTYsMzIzLjUyNiAxODAuNDc0LDM4MS40NDQgMjUxLjkyMSwzODEuNDQ0IEMzMjMuMzY3LDM4MS40NDQgMzgxLjI4NSwzMjMuNTI2IDM4MS4yODUsMjUyLjA4IEMzODEuMjg1LDE4MC42MzMgMzIzLjM2NywxMjIuNzE1IDI1MS45MjEsMTIyLjcxNSBaIiBpZD0iRmlsbC00IiBmaWxsPSIjRkZGRkZGIj48L3BhdGg+ICAgICAgICA8cGF0aCBkPSJNNDE2LjYyNywxMTcuNjA0IEM0MTYuNjI3LDEzNC4zIDQwMy4wOTIsMTQ3LjgzNCAzODYuMzk2LDE0Ny44MzQgQzM2OS43MDEsMTQ3LjgzNCAzNTYuMTY2LDEzNC4zIDM1Ni4xNjYsMTE3LjYwNCBDMzU2LjE2NiwxMDAuOTA4IDM2OS43MDEsODcuMzczIDM4Ni4zOTYsODcuMzczIEM0MDMuMDkyLDg3LjM3MyA0MTYuNjI3LDEwMC45MDggNDE2LjYyNywxMTcuNjA0IiBpZD0iRmlsbC01IiBmaWxsPSIjRkZGRkZGIj48L3BhdGg+ICAgIDwvZz48L3N2Zz4=);\n\t\t}\n\n\t\t/* stylelint-disable-next-line no-descending-specificity */\n\t\t& .ck-media__placeholder__url__text {\n\t\t\tcolor: hsl(302, 100%, 94%);\n\n\t\t\t&:hover {\n\t\t\t\tcolor: hsl(0, 0%, 100%);\n\t\t\t}\n\t\t}\n\t}\n\n\t&[data-oembed-url*="twitter.com"] .ck.ck-media__placeholder {\n\t\t/* Use gradient to contrast with focused widget (ckeditor/ckeditor5-media-embed#22). */\n\t\tbackground: linear-gradient( to right, hsl(201, 85%, 70%), hsl(201, 85%, 35%) );\n\n\t\t& .ck-media__placeholder__icon {\n\t\t\tbackground-image: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz48c3ZnIHZlcnNpb249IjEuMSIgaWQ9IldoaXRlIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB4PSIwcHgiIHk9IjBweCIgdmlld0JveD0iMCAwIDQwMCA0MDAiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDQwMCA0MDA7IiB4bWw6c3BhY2U9InByZXNlcnZlIj48c3R5bGUgdHlwZT0idGV4dC9jc3MiPi5zdDB7ZmlsbDojRkZGRkZGO308L3N0eWxlPjxwYXRoIGNsYXNzPSJzdDAiIGQ9Ik00MDAsMjAwYzAsMTEwLjUtODkuNSwyMDAtMjAwLDIwMFMwLDMxMC41LDAsMjAwUzg5LjUsMCwyMDAsMFM0MDAsODkuNSw0MDAsMjAweiBNMTYzLjQsMzA1LjVjODguNywwLDEzNy4yLTczLjUsMTM3LjItMTM3LjJjMC0yLjEsMC00LjItMC4xLTYuMmM5LjQtNi44LDE3LjYtMTUuMywyNC4xLTI1Yy04LjYsMy44LTE3LjksNi40LTI3LjcsNy42YzEwLTYsMTcuNi0xNS40LDIxLjItMjYuN2MtOS4zLDUuNS0xOS42LDkuNS0zMC42LDExLjdjLTguOC05LjQtMjEuMy0xNS4yLTM1LjItMTUuMmMtMjYuNiwwLTQ4LjIsMjEuNi00OC4yLDQ4LjJjMCwzLjgsMC40LDcuNSwxLjMsMTFjLTQwLjEtMi03NS42LTIxLjItOTkuNC01MC40Yy00LjEsNy4xLTYuNSwxNS40LTYuNSwyNC4yYzAsMTYuNyw4LjUsMzEuNSwyMS41LDQwLjFjLTcuOS0wLjItMTUuMy0yLjQtMjEuOC02YzAsMC4yLDAsMC40LDAsMC42YzAsMjMuNCwxNi42LDQyLjgsMzguNyw0Ny4zYy00LDEuMS04LjMsMS43LTEyLjcsMS43Yy0zLjEsMC02LjEtMC4zLTkuMS0wLjljNi4xLDE5LjIsMjMuOSwzMy4xLDQ1LDMzLjVjLTE2LjUsMTIuOS0zNy4zLDIwLjYtNTkuOSwyMC42Yy0zLjksMC03LjctMC4yLTExLjUtMC43QzExMC44LDI5Ny41LDEzNi4yLDMwNS41LDE2My40LDMwNS41Ii8+PC9zdmc+);\n\t\t}\n\n\t\t& .ck-media__placeholder__url__text {\n\t\t\tcolor: hsl(201, 100%, 86%);\n\n\t\t\t&:hover {\n\t\t\t\tcolor: hsl(0, 0%, 100%);\n\t\t\t}\n\t\t}\n\t}\n}\n'],sourceRoot:""}]);e["a"]=a},function(t,e,n){"use strict";var o=n(2);var i=n.n(o);var r=n(3);var s=n.n(r);var a=s()(i.a);a.push([t.i,".ck.ck-media-form{display:flex;align-items:flex-start;flex-direction:row;flex-wrap:nowrap}.ck.ck-media-form .ck-labeled-field-view{display:inline-block}.ck.ck-media-form .ck-label{display:none}@media screen and (max-width:600px){.ck.ck-media-form{flex-wrap:wrap}.ck.ck-media-form .ck-labeled-field-view{flex-basis:100%}.ck.ck-media-form .ck-button{flex-basis:50%}}","",{version:3,sources:["webpack://./node_modules/@ckeditor/ckeditor5-media-embed/theme/mediaform.css","webpack://./node_modules/@ckeditor/ckeditor5-ui/theme/mixins/_rwd.css"],names:[],mappings:"AAOA,kBACC,YAAa,CACb,sBAAuB,CACvB,kBAAmB,CACnB,gBAqBD,CAnBC,yCACC,oBACD,CAEA,4BACC,YACD,CCbA,oCDCD,kBAeE,cAUF,CARE,yCACC,eACD,CAEA,6BACC,cACD,CCtBD",sourcesContent:['/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n@import "@ckeditor/ckeditor5-ui/theme/mixins/_rwd.css";\n\n.ck.ck-media-form {\n\tdisplay: flex;\n\talign-items: flex-start;\n\tflex-direction: row;\n\tflex-wrap: nowrap;\n\n\t& .ck-labeled-field-view {\n\t\tdisplay: inline-block;\n\t}\n\n\t& .ck-label {\n\t\tdisplay: none;\n\t}\n\n\t@mixin ck-media-phone {\n\t\tflex-wrap: wrap;\n\n\t\t& .ck-labeled-field-view {\n\t\t\tflex-basis: 100%;\n\t\t}\n\n\t\t& .ck-button {\n\t\t\tflex-basis: 50%;\n\t\t}\n\t}\n}\n',"/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n@define-mixin ck-media-phone {\n\t@media screen and (max-width: 600px) {\n\t\t@mixin-content;\n\t}\n}\n"],sourceRoot:""}]);e["a"]=a},function(t,e,n){"use strict";var o=n(2);var i=n.n(o);var r=n(3);var s=n.n(r);var a=s()(i.a);a.push([t.i,".ck-content .media{clear:both;margin:1em 0;display:block;min-width:15em}","",{version:3,sources:["webpack://./node_modules/@ckeditor/ckeditor5-media-embed/theme/mediaembed.css"],names:[],mappings:"AAKA,mBAGC,UAAW,CAGX,YAAa,CAIb,aAAc,CAId,cACD",sourcesContent:['/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n.ck-content .media {\n\t/* Don\'t allow floated content overlap the media.\n\thttps://github.com/ckeditor/ckeditor5-media-embed/issues/53 */\n\tclear: both;\n\n\t/* Make sure there is some space between the content and the media. */\n\tmargin: 1em 0;\n\n\t/* Make sure media is not overriden with Bootstrap default `flex` value.\n\tSee: https://github.com/ckeditor/ckeditor5/issues/1373. */\n\tdisplay: block;\n\n\t/* Give the media some minimal width in the content to prevent them\n\tfrom being "squashed" in tight spaces, e.g. in table cells (#44) */\n\tmin-width: 15em;\n}\n'],sourceRoot:""}]);e["a"]=a},function(t,e,n){"use strict";var o=n(2);var i=n.n(o);var r=n(3);var s=n.n(r);var a=s()(i.a);a.push([t.i,":root{--ck-color-table-focused-cell-background:rgba(158,207,250,0.3)}.ck-widget.table td.ck-editor__nested-editable.ck-editor__nested-editable_focused,.ck-widget.table td.ck-editor__nested-editable:focus,.ck-widget.table th.ck-editor__nested-editable.ck-editor__nested-editable_focused,.ck-widget.table th.ck-editor__nested-editable:focus{background:var(--ck-color-table-focused-cell-background);border-style:none;outline:1px solid var(--ck-color-focus-border);outline-offset:-1px}","",{version:3,sources:["webpack://./node_modules/@ckeditor/ckeditor5-theme-lark/theme/ckeditor5-table/tableediting.css"],names:[],mappings:"AAKA,MACC,8DACD,CAKE,8QAGC,wDAAyD,CAKzD,iBAAkB,CAClB,8CAA+C,CAC/C,mBACD",sourcesContent:["/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n:root {\n\t--ck-color-table-focused-cell-background: hsla(208, 90%, 80%, .3);\n}\n\n.ck-widget.table {\n\t& td,\n\t& th {\n\t\t&.ck-editor__nested-editable.ck-editor__nested-editable_focused,\n\t\t&.ck-editor__nested-editable:focus {\n\t\t\t/* A very slight background to highlight the focused cell */\n\t\t\tbackground: var(--ck-color-table-focused-cell-background);\n\n\t\t\t/* Fixes the problem where surrounding cells cover the focused cell's border.\n\t\t\tIt does not fix the problem in all places but the UX is improved.\n\t\t\tSee https://github.com/ckeditor/ckeditor5-table/issues/29. */\n\t\t\tborder-style: none;\n\t\t\toutline: 1px solid var(--ck-color-focus-border);\n\t\t\toutline-offset: -1px; /* progressive enhancement - no IE support */\n\t\t}\n\t}\n}\n"],sourceRoot:""}]);e["a"]=a},function(t,e,n){"use strict";var o=n(2);var i=n.n(o);var r=n(3);var s=n.n(r);var a=s()(i.a);a.push([t.i,".ck.ck-splitbutton{font-size:inherit}.ck.ck-splitbutton .ck-splitbutton__action:focus{z-index:calc(var(--ck-z-default) + 1)}.ck.ck-splitbutton.ck-splitbutton_open>.ck-button .ck-tooltip{display:none}:root{--ck-color-split-button-hover-background:#ebebeb;--ck-color-split-button-hover-border:#b3b3b3}[dir=ltr] .ck.ck-splitbutton>.ck-splitbutton__action{border-top-right-radius:unset;border-bottom-right-radius:unset}[dir=rtl] .ck.ck-splitbutton>.ck-splitbutton__action{border-top-left-radius:unset;border-bottom-left-radius:unset}.ck.ck-splitbutton>.ck-splitbutton__arrow{min-width:unset}[dir=ltr] .ck.ck-splitbutton>.ck-splitbutton__arrow{border-radius:0}.ck-rounded-corners [dir=ltr] .ck.ck-splitbutton>.ck-splitbutton__arrow,[dir=ltr] .ck.ck-splitbutton>.ck-splitbutton__arrow.ck-rounded-corners{border-radius:var(--ck-border-radius);border-top-left-radius:unset;border-bottom-left-radius:unset}[dir=rtl] .ck.ck-splitbutton>.ck-splitbutton__arrow{border-top-right-radius:unset;border-bottom-right-radius:unset}.ck.ck-splitbutton>.ck-splitbutton__arrow svg{width:var(--ck-dropdown-arrow-size)}.ck.ck-splitbutton.ck-splitbutton_open>.ck-button:not(.ck-on):not(.ck-disabled):not(:hover),.ck.ck-splitbutton:hover>.ck-button:not(.ck-on):not(.ck-disabled):not(:hover){background:var(--ck-color-split-button-hover-background)}[dir=ltr] .ck.ck-splitbutton.ck-splitbutton_open>.ck-splitbutton__arrow:not(.ck-disabled),[dir=ltr] .ck.ck-splitbutton:hover>.ck-splitbutton__arrow:not(.ck-disabled){border-left-color:var(--ck-color-split-button-hover-border)}[dir=rtl] .ck.ck-splitbutton.ck-splitbutton_open>.ck-splitbutton__arrow:not(.ck-disabled),[dir=rtl] .ck.ck-splitbutton:hover>.ck-splitbutton__arrow:not(.ck-disabled){border-right-color:var(--ck-color-split-button-hover-border)}.ck.ck-splitbutton.ck-splitbutton_open{border-radius:0}.ck-rounded-corners .ck.ck-splitbutton.ck-splitbutton_open,.ck.ck-splitbutton.ck-splitbutton_open.ck-rounded-corners{border-radius:var(--ck-border-radius)}.ck-rounded-corners .ck.ck-splitbutton.ck-splitbutton_open>.ck-splitbutton__action,.ck.ck-splitbutton.ck-splitbutton_open.ck-rounded-corners>.ck-splitbutton__action{border-bottom-left-radius:0}.ck-rounded-corners .ck.ck-splitbutton.ck-splitbutton_open>.ck-splitbutton__arrow,.ck.ck-splitbutton.ck-splitbutton_open.ck-rounded-corners>.ck-splitbutton__arrow{border-bottom-right-radius:0}","",{version:3,sources:["webpack://./node_modules/@ckeditor/ckeditor5-ui/theme/components/dropdown/splitbutton.css","webpack://./node_modules/@ckeditor/ckeditor5-ui/theme/components/tooltip/mixins/_tooltip.css","webpack://./node_modules/@ckeditor/ckeditor5-theme-lark/theme/ckeditor5-ui/components/dropdown/splitbutton.css","webpack://./node_modules/@ckeditor/ckeditor5-theme-lark/theme/mixins/_rounded.css"],names:[],mappings:"AAOA,mBAEC,iBAUD,CARC,iDACC,qCACD,CC0BA,8DACC,YACD,CClCD,MACC,gDAAyD,CACzD,4CACD,CAMC,qDAGE,6BAA8B,CAC9B,gCAQF,CAZA,qDASE,4BAA6B,CAC7B,+BAEF,CAEA,0CAGC,eAmBD,CAtBA,oDCnBA,eDyCA,CAtBA,+ICfC,qCAAsC,CDuBpC,4BAA6B,CAC7B,+BAaH,CAtBA,oDAeE,6BAA8B,CAC9B,gCAMF,CAHC,8CACC,mCACD,CASA,0KACC,wDACD,CAGC,sKACC,2DACD,CAIA,sKACC,4DACD,CAMF,uCCpEA,eD8EA,CAVA,qHChEC,qCD0ED,CARE,qKACC,2BACD,CAEA,mKACC,4BACD",sourcesContent:['/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n@import "../tooltip/mixins/_tooltip.css";\n\n.ck.ck-splitbutton {\n\t/* Enable font size inheritance, which allows fluid UI scaling. */\n\tfont-size: inherit;\n\n\t& .ck-splitbutton__action:focus {\n\t\tz-index: calc(var(--ck-z-default) + 1);\n\t}\n\n\t/* Disable tooltips for the buttons when the button is "open" */\n\t&.ck-splitbutton_open > .ck-button {\n\t\t@mixin ck-tooltip_disabled;\n\t}\n}\n\n',"/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * Enables the tooltip, which is the tooltip is in DOM but\n * not yet displayed.\n */\n@define-mixin ck-tooltip_enabled {\n\t& .ck-tooltip {\n\t\tdisplay: block;\n\n\t\t/*\n\t\t * Don't display tooltips in devices which don't support :hover.\n\t\t * In fact, it's all about iOS, which forces user to click UI elements twice to execute\n\t\t * the primary action, when tooltips are enabled.\n\t\t *\n\t\t * Q: OK, but why not the following query?\n\t\t *\n\t\t * @media (hover) {\n\t\t * display: block;\n\t\t * }\n\t\t *\n\t\t * A: Because FF does not support it and it would completely disable tooltips\n\t\t * in that browser.\n\t\t *\n\t\t * More in https://github.com/ckeditor/ckeditor5/issues/920.\n\t\t */\n\t\t@media (hover:none) {\n\t\t\tdisplay: none;\n\t\t}\n\t}\n}\n\n/**\n * Disables the tooltip making it disappear from DOM.\n */\n@define-mixin ck-tooltip_disabled {\n\t& .ck-tooltip {\n\t\tdisplay: none;\n\t}\n}\n\n/**\n * Shows the tooltip, which is already in DOM.\n * Requires `ck-tooltip_enabled` first.\n */\n@define-mixin ck-tooltip_visible {\n\t& .ck-tooltip {\n\t\tvisibility: visible;\n\t\topacity: 1;\n\t}\n}\n",'/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n@import "../../../mixins/_rounded.css";\n\n:root {\n\t--ck-color-split-button-hover-background: hsl(0, 0%, 92%);\n\t--ck-color-split-button-hover-border: hsl(0, 0%, 70%);\n}\n\n.ck.ck-splitbutton {\n\t/*\n\t * Note: ck-rounded and ck-dir mixins don\'t go together (because they both use @nest).\n\t */\n\t& > .ck-splitbutton__action {\n\t\t@nest [dir="ltr"] & {\n\t\t\t/* Don\'t round the action button on the right side */\n\t\t\tborder-top-right-radius: unset;\n\t\t\tborder-bottom-right-radius: unset;\n\t\t}\n\n\t\t@nest [dir="rtl"] & {\n\t\t\t/* Don\'t round the action button on the left side */\n\t\t\tborder-top-left-radius: unset;\n\t\t\tborder-bottom-left-radius: unset;\n\t\t}\n\t}\n\n\t& > .ck-splitbutton__arrow {\n\t\t/* It\'s a text-less button and since the icon is positioned absolutely in such situation,\n\t\tit must get some arbitrary min-width. */\n\t\tmin-width: unset;\n\n\t\t@nest [dir="ltr"] & {\n\t\t\t/* Don\'t round the arrow button on the left side */\n\t\t\t@mixin ck-rounded-corners {\n\t\t\t\tborder-top-left-radius: unset;\n\t\t\t\tborder-bottom-left-radius: unset;\n\t\t\t}\n\t\t}\n\n\t\t@nest [dir="rtl"] & {\n\t\t\t/* Don\'t round the arrow button on the right side */\n\t\t\tborder-top-right-radius: unset;\n\t\t\tborder-bottom-right-radius: unset;\n\t\t}\n\n\t\t& svg {\n\t\t\twidth: var(--ck-dropdown-arrow-size);\n\t\t}\n\t}\n\n\t/* When the split button is "open" (the arrow is on) or being hovered, it should get some styling\n\tas a whole. The background of both buttons should stand out and there should be a visual\n\tseparation between both buttons. */\n\t&.ck-splitbutton_open,\n\t&:hover {\n\t\t/* When the split button hovered as a whole, not as individual buttons. */\n\t\t& > .ck-button:not(.ck-on):not(.ck-disabled):not(:hover) {\n\t\t\tbackground: var(--ck-color-split-button-hover-background);\n\t\t}\n\n\t\t@nest [dir="ltr"] & {\n\t\t\t& > .ck-splitbutton__arrow:not(.ck-disabled) {\n\t\t\t\tborder-left-color: var(--ck-color-split-button-hover-border);\n\t\t\t}\n\t\t}\n\n\t\t@nest [dir="rtl"] & {\n\t\t\t& > .ck-splitbutton__arrow:not(.ck-disabled) {\n\t\t\t\tborder-right-color: var(--ck-color-split-button-hover-border);\n\t\t\t}\n\t\t}\n\t}\n\n\t/* Don\'t round the bottom left and right corners of the buttons when "open"\n\thttps://github.com/ckeditor/ckeditor5/issues/816 */\n\t&.ck-splitbutton_open {\n\t\t@mixin ck-rounded-corners {\n\t\t\t& > .ck-splitbutton__action {\n\t\t\t\tborder-bottom-left-radius: 0;\n\t\t\t}\n\n\t\t\t& > .ck-splitbutton__arrow {\n\t\t\t\tborder-bottom-right-radius: 0;\n\t\t\t}\n\t\t}\n\t}\n}\n',"/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * Implements rounded corner interface for .ck-rounded-corners class.\n *\n * @see $ck-border-radius\n */\n@define-mixin ck-rounded-corners {\n\tborder-radius: 0;\n\n\t@nest .ck-rounded-corners &,\n\t&.ck-rounded-corners {\n\t\tborder-radius: var(--ck-border-radius);\n\t\t@mixin-content;\n\t}\n}\n"],sourceRoot:""}]);e["a"]=a},function(t,e,n){"use strict";var o=n(2);var i=n.n(o);var r=n(3);var s=n.n(r);var a=s()(i.a);a.push([t.i,".ck .ck-insert-table-dropdown__grid{display:flex;flex-direction:row;flex-wrap:wrap}:root{--ck-insert-table-dropdown-padding:10px;--ck-insert-table-dropdown-box-height:11px;--ck-insert-table-dropdown-box-width:12px;--ck-insert-table-dropdown-box-margin:1px}.ck .ck-insert-table-dropdown__grid{width:calc(var(--ck-insert-table-dropdown-box-width)*10 + var(--ck-insert-table-dropdown-box-margin)*20 + var(--ck-insert-table-dropdown-padding)*2);padding:var(--ck-insert-table-dropdown-padding) var(--ck-insert-table-dropdown-padding) 0}.ck .ck-insert-table-dropdown__label{text-align:center}.ck .ck-insert-table-dropdown-grid-box{width:var(--ck-insert-table-dropdown-box-width);height:var(--ck-insert-table-dropdown-box-height);margin:var(--ck-insert-table-dropdown-box-margin);border:1px solid var(--ck-color-base-border);border-radius:1px}.ck .ck-insert-table-dropdown-grid-box.ck-on{border-color:var(--ck-color-focus-border);background:var(--ck-color-focus-outer-shadow)}","",{version:3,sources:["webpack://./node_modules/@ckeditor/ckeditor5-table/theme/inserttable.css","webpack://./node_modules/@ckeditor/ckeditor5-theme-lark/theme/ckeditor5-table/inserttable.css"],names:[],mappings:"AAKA,oCACC,YAAa,CACb,kBAAmB,CACnB,cACD,CCJA,MACC,uCAAwC,CACxC,0CAA2C,CAC3C,yCAA0C,CAC1C,yCACD,CAEA,oCAEC,oJAA2J,CAC3J,yFACD,CAEA,qCACC,iBACD,CAEA,uCACC,+CAAgD,CAChD,iDAAkD,CAClD,iDAAkD,CAClD,4CAA6C,CAC7C,iBAMD,CAJC,6CACC,yCAA0C,CAC1C,6CACD",sourcesContent:["/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n.ck .ck-insert-table-dropdown__grid {\n\tdisplay: flex;\n\tflex-direction: row;\n\tflex-wrap: wrap;\n}\n","/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n:root {\n\t--ck-insert-table-dropdown-padding: 10px;\n\t--ck-insert-table-dropdown-box-height: 11px;\n\t--ck-insert-table-dropdown-box-width: 12px;\n\t--ck-insert-table-dropdown-box-margin: 1px;\n}\n\n.ck .ck-insert-table-dropdown__grid {\n\t/* The width of a container should match 10 items in a row so there will be a 10x10 grid. */\n\twidth: calc(var(--ck-insert-table-dropdown-box-width) * 10 + var(--ck-insert-table-dropdown-box-margin) * 20 + var(--ck-insert-table-dropdown-padding) * 2);\n\tpadding: var(--ck-insert-table-dropdown-padding) var(--ck-insert-table-dropdown-padding) 0;\n}\n\n.ck .ck-insert-table-dropdown__label {\n\ttext-align: center;\n}\n\n.ck .ck-insert-table-dropdown-grid-box {\n\twidth: var(--ck-insert-table-dropdown-box-width);\n\theight: var(--ck-insert-table-dropdown-box-height);\n\tmargin: var(--ck-insert-table-dropdown-box-margin);\n\tborder: 1px solid var(--ck-color-base-border);\n\tborder-radius: 1px;\n\n\t&.ck-on {\n\t\tborder-color: var(--ck-color-focus-border);\n\t\tbackground: var(--ck-color-focus-outer-shadow);\n\t}\n}\n\n"],sourceRoot:""}]);e["a"]=a},function(t,e,n){"use strict";var o=n(2);var i=n.n(o);var r=n(3);var s=n.n(r);var a=s()(i.a);a.push([t.i,':root{--ck-table-selected-cell-background:rgba(158,207,250,0.3)}.ck.ck-editor__editable .table table td.ck-editor__editable_selected,.ck.ck-editor__editable .table table th.ck-editor__editable_selected{position:relative;caret-color:transparent;outline:unset;box-shadow:unset}.ck.ck-editor__editable .table table td.ck-editor__editable_selected:after,.ck.ck-editor__editable .table table th.ck-editor__editable_selected:after{content:"";pointer-events:none;background-color:var(--ck-table-selected-cell-background);position:absolute;top:0;left:0;right:0;bottom:0}.ck.ck-editor__editable .table table td.ck-editor__editable_selected ::selection,.ck.ck-editor__editable .table table td.ck-editor__editable_selected:focus,.ck.ck-editor__editable .table table th.ck-editor__editable_selected ::selection,.ck.ck-editor__editable .table table th.ck-editor__editable_selected:focus{background-color:transparent}.ck.ck-editor__editable .table table td.ck-editor__editable_selected .ck-widget_selected,.ck.ck-editor__editable .table table th.ck-editor__editable_selected .ck-widget_selected{outline:unset}',"",{version:3,sources:["webpack://./node_modules/@ckeditor/ckeditor5-theme-lark/theme/ckeditor5-table/tableselection.css"],names:[],mappings:"AAKA,MACC,yDACD,CAGC,0IAEC,iBAAkB,CAClB,uBAAwB,CACxB,aAAc,CACd,gBAsBD,CAnBC,sJACC,UAAW,CACX,mBAAoB,CACpB,yDAA0D,CAC1D,iBAAkB,CAClB,KAAM,CACN,MAAO,CACP,OAAQ,CACR,QACD,CAEA,wTAEC,4BACD,CAEA,kLACC,aACD",sourcesContent:["/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n:root {\n\t--ck-table-selected-cell-background: hsla(208, 90%, 80%, .3);\n}\n\n.ck.ck-editor__editable .table table {\n\t& td.ck-editor__editable_selected,\n\t& th.ck-editor__editable_selected {\n\t\tposition: relative;\n\t\tcaret-color: transparent;\n\t\toutline: unset;\n\t\tbox-shadow: unset;\n\n\t\t/* https://github.com/ckeditor/ckeditor5/issues/6446 */\n\t\t&:after {\n\t\t\tcontent: '';\n\t\t\tpointer-events: none;\n\t\t\tbackground-color: var(--ck-table-selected-cell-background);\n\t\t\tposition: absolute;\n\t\t\ttop: 0;\n\t\t\tleft: 0;\n\t\t\tright: 0;\n\t\t\tbottom: 0;\n\t\t}\n\n\t\t& ::selection,\n\t\t&:focus {\n\t\t\tbackground-color: transparent;\n\t\t}\n\n\t\t& .ck-widget_selected {\n\t\t\toutline: unset;\n\t\t}\n\t}\n}\n"],sourceRoot:""}]);e["a"]=a},function(t,e,n){"use strict";var o=n(2);var i=n.n(o);var r=n(3);var s=n.n(r);var a=s()(i.a);a.push([t.i,".ck-content .table{margin:1em auto;display:table}.ck-content .table table{border-collapse:collapse;border-spacing:0;width:100%;height:100%;border:1px double #b3b3b3}.ck-content .table table td,.ck-content .table table th{min-width:2em;padding:.4em;border:1px solid #bfbfbf}.ck-content .table table th{font-weight:700;background:hsla(0,0%,0%,5%)}.ck-content[dir=rtl] .table th{text-align:right}.ck-content[dir=ltr] .table th{text-align:left}","",{version:3,sources:["webpack://./node_modules/@ckeditor/ckeditor5-table/theme/table.css"],names:[],mappings:"AAKA,mBAEC,eAAgB,CAChB,aAgCD,CA9BC,yBAEC,wBAAyB,CACzB,gBAAiB,CAIjB,UAAW,CACX,WAAY,CAIZ,yBAiBD,CAfC,wDAEC,aAAc,CACd,YAAa,CAKb,wBACD,CAEA,4BACC,eAAiB,CACjB,2BACD,CAMF,+BACC,gBACD,CAEA,+BACC,eACD",sourcesContent:['/*\n * Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n.ck-content .table {\n\t/* Give the table widget some air and center it horizontally */\n\tmargin: 1em auto;\n\tdisplay: table;\n\n\t& table {\n\t\t/* The table cells should have slight borders */\n\t\tborder-collapse: collapse;\n\t\tborder-spacing: 0;\n\n\t\t/* Table width and height are set on the parent
. Make sure the table inside stretches\n\t\tto the full dimensions of the container (https://github.com/ckeditor/ckeditor5/issues/6186). */\n\t\twidth: 100%;\n\t\theight: 100%;\n\n\t\t/* The outer border of the table should be slightly darker than the inner lines.\n\t\tAlso see https://github.com/ckeditor/ckeditor5-table/issues/50. */\n\t\tborder: 1px double hsl(0, 0%, 70%);\n\n\t\t& td,\n\t\t& th {\n\t\t\tmin-width: 2em;\n\t\t\tpadding: .4em;\n\n\t\t\t/* The border is inherited from .ck-editor__nested-editable styles, so theoretically it\'s not necessary here.\n\t\t\tHowever, the border is a content style, so it should use .ck-content (so it works outside the editor).\n\t\t\tHence, the duplication. See https://github.com/ckeditor/ckeditor5/issues/6314 */\n\t\t\tborder: 1px solid hsl(0, 0%, 75%);\n\t\t}\n\n\t\t& th {\n\t\t\tfont-weight: bold;\n\t\t\tbackground: hsla(0, 0%, 0%, 5%);\n\t\t}\n\t}\n}\n\n/* Text alignment of the table header should match the editor settings and override the native browser styling,\nwhen content is available outside the ediitor. See https://github.com/ckeditor/ckeditor5/issues/6638 */\n.ck-content[dir="rtl"] .table th {\n\ttext-align: right;\n}\n\n.ck-content[dir="ltr"] .table th {\n\ttext-align: left;\n}\n'],sourceRoot:""}]);e["a"]=a},function(t,e){var n;n=function(){return this}();try{n=n||new Function("return this")()}catch(t){if(typeof window==="object")n=window}t.exports=n},function(t,e,n){"use strict";function o(){return false}e["a"]=o},function(t,e,n){"use strict";n.r(e);var o=n(5);var i=o["a"].Symbol;var r=i;var s=Object.prototype;var a=s.hasOwnProperty;var c=s.toString;var l=r?r.toStringTag:undefined;function d(t){var e=a.call(t,l),n=t[l];try{t[l]=undefined;var o=true}catch(t){}var i=c.call(t);if(o){if(e){t[l]=n}else{delete t[l]}}return i}var u=d;var h=Object.prototype;var f=h.toString;function m(t){return f.call(t)}var g=m;var p="[object Null]",k="[object Undefined]";var b=r?r.toStringTag:undefined;function w(t){if(t==null){return t===undefined?k:p}return b&&b in Object(t)?u(t):g(t)}var C=w;function A(t,e){return function(n){return t(e(n))}}var _=A;var v=_(Object.getPrototypeOf,Object);var y=v;function x(t){return t!=null&&typeof t=="object"}var D=x;var E="[object Object]";var M=Function.prototype,T=Object.prototype;var S=M.toString;var I=T.hasOwnProperty;var N=S.call(Object);function B(t){if(!D(t)||C(t)!=E){return false}var e=y(t);if(e===null){return true}var n=I.call(e,"constructor")&&e.constructor;return typeof n=="function"&&n instanceof n&&S.call(n)==N}var P=B;function z(){this.__data__=[];this.size=0}var L=z;function O(t,e){return t===e||t!==t&&e!==e}var R=O;function j(t,e){var n=t.length;while(n--){if(R(t[n][0],e)){return n}}return-1}var F=j;var V=Array.prototype;var U=V.splice;function H(t){var e=this.__data__,n=F(e,t);if(n<0){return false}var o=e.length-1;if(n==o){e.pop()}else{U.call(e,n,1)}--this.size;return true}var G=H;function K(t){var e=this.__data__,n=F(e,t);return n<0?undefined:e[n][1]}var W=K;function q(t){return F(this.__data__,t)>-1}var Y=q;function Q(t,e){var n=this.__data__,o=F(n,t);if(o<0){++this.size;n.push([t,e])}else{n[o][1]=e}return this}var $=Q;function J(t){var e=-1,n=t==null?0:t.length;this.clear();while(++e-1&&t%1==0&&t-1&&t%1==0&&t<=en}var on=nn;var rn="[object Arguments]",sn="[object Array]",an="[object Boolean]",cn="[object Date]",ln="[object Error]",dn="[object Function]",un="[object Map]",hn="[object Number]",fn="[object Object]",mn="[object RegExp]",gn="[object Set]",pn="[object String]",kn="[object WeakMap]";var bn="[object ArrayBuffer]",wn="[object DataView]",Cn="[object Float32Array]",An="[object Float64Array]",_n="[object Int8Array]",vn="[object Int16Array]",yn="[object Int32Array]",xn="[object Uint8Array]",Dn="[object Uint8ClampedArray]",En="[object Uint16Array]",Mn="[object Uint32Array]";var Tn={};Tn[Cn]=Tn[An]=Tn[_n]=Tn[vn]=Tn[yn]=Tn[xn]=Tn[Dn]=Tn[En]=Tn[Mn]=true;Tn[rn]=Tn[sn]=Tn[bn]=Tn[an]=Tn[wn]=Tn[cn]=Tn[ln]=Tn[dn]=Tn[un]=Tn[hn]=Tn[fn]=Tn[mn]=Tn[gn]=Tn[pn]=Tn[kn]=false;function Sn(t){return D(t)&&on(t.length)&&!!Tn[C(t)]}var In=Sn;function Nn(t){return function(e){return t(e)}}var Bn=Nn;var Pn=n(7);var zn=Pn["a"]&&Pn["a"].isTypedArray;var Ln=zn?Bn(zn):In;var On=Ln;var Rn=Object.prototype;var jn=Rn.hasOwnProperty;function Fn(t,e){var n=Qe(t),o=!n&&qe(t),i=!n&&!o&&Object($e["a"])(t),r=!n&&!o&&!i&&On(t),s=n||o||i||r,a=s?je(t.length,String):[],c=a.length;for(var l in t){if((e||jn.call(t,l))&&!(s&&(l=="length"||i&&(l=="offset"||l=="parent")||r&&(l=="buffer"||l=="byteLength"||l=="byteOffset")||tn(l,c)))){a.push(l)}}return a}var Vn=Fn;var Un=Object.prototype;function Hn(t){var e=t&&t.constructor,n=typeof e=="function"&&e.prototype||Un;return t===n}var Gn=Hn;var Kn=_(Object.keys,Object);var Wn=Kn;var qn=Object.prototype;var Yn=qn.hasOwnProperty;function Qn(t){if(!Gn(t)){return Wn(t)}var e=[];for(var n in Object(t)){if(Yn.call(t,n)&&n!="constructor"){e.push(n)}}return e}var $n=Qn;function Jn(t){return t!=null&&on(t.length)&&!mt(t)}var Zn=Jn;function Xn(t){return Zn(t)?Vn(t):$n(t)}var to=Xn;function eo(t,e){return t&&Oe(e,to(e),t)}var no=eo;function oo(t){var e=[];if(t!=null){for(var n in Object(t)){e.push(n)}}return e}var io=oo;var ro=Object.prototype;var so=ro.hasOwnProperty;function ao(t){if(!ct(t)){return io(t)}var e=Gn(t),n=[];for(var o in t){if(!(o=="constructor"&&(e||!so.call(t,o)))){n.push(o)}}return n}var co=ao;function lo(t){return Zn(t)?Vn(t,true):co(t)}var uo=lo;function ho(t,e){return t&&Oe(e,uo(e),t)}var fo=ho;var mo=n(10);function go(t,e){var n=-1,o=t.length;e||(e=Array(o));while(++n{this._setToTarget(t,o,e[o],n)}))}}function $r(t){return Wr(t,Jr)}function Jr(t){return Yr(t)?t:undefined}function Zr(){return function t(){t.called=true}}var Xr=Zr;class ts{constructor(t,e){this.source=t;this.name=e;this.path=[];this.stop=Xr();this.off=Xr()}}const es=new Array(256).fill().map(((t,e)=>("0"+e.toString(16)).slice(-2)));function ns(){const t=Math.random()*4294967296>>>0;const e=Math.random()*4294967296>>>0;const n=Math.random()*4294967296>>>0;const o=Math.random()*4294967296>>>0;return"e"+es[t>>0&255]+es[t>>8&255]+es[t>>16&255]+es[t>>24&255]+es[e>>0&255]+es[e>>8&255]+es[e>>16&255]+es[e>>24&255]+es[n>>0&255]+es[n>>8&255]+es[n>>16&255]+es[n>>24&255]+es[o>>0&255]+es[o>>8&255]+es[o>>16&255]+es[o>>24&255]}const os={get(t){if(typeof t!="number"){return this[t]||this.normal}else{return t}},highest:1e5,high:1e3,normal:0,low:-1e3,lowest:-1e5};var is=os;var rs=n(8);var ss=n(0);const as=Symbol("listeningTo");const cs=Symbol("emitterId");const ls={on(t,e,n={}){this.listenTo(this,t,e,n)},once(t,e,n){let o=false;const i=function(t,...n){if(!o){o=true;t.off();e.call(this,t,...n)}};this.listenTo(this,t,i,n)},off(t,e){this.stopListening(this,t,e)},listenTo(t,e,n,o={}){let i,r;if(!this[as]){this[as]={}}const s=this[as];if(!fs(t)){hs(t)}const a=fs(t);if(!(i=s[a])){i=s[a]={emitter:t,callbacks:{}}}if(!(r=i.callbacks[e])){r=i.callbacks[e]=[]}r.push(n);ps(t,e);const c=ks(t,e);const l=is.get(o.priority);const d={callback:n,priority:l};for(const t of c){let e=false;for(let n=0;n{if(!this._delegations){this._delegations=new Map}t.forEach((t=>{const o=this._delegations.get(t);if(!o){this._delegations.set(t,new Map([[e,n]]))}else{o.set(e,n)}}))}}},stopDelegating(t,e){if(!this._delegations){return}if(!t){this._delegations.clear()}else if(!e){this._delegations.delete(t)}else{const n=this._delegations.get(t);if(n){n.delete(e)}}}};var ds=ls;function us(t,e){if(t[as]&&t[as][e]){return t[as][e].emitter}return null}function hs(t,e){if(!t[cs]){t[cs]=e||ns()}}function fs(t){return t[cs]}function ms(t){if(!t._events){Object.defineProperty(t,"_events",{value:{}})}return t._events}function gs(){return{callbacks:[],childEvents:[]}}function ps(t,e){const n=ms(t);if(n[e]){return}let o=e;let i=null;const r=[];while(o!==""){if(n[o]){break}n[o]=gs();r.push(n[o]);if(i){n[o].childEvents.push(i)}i=o;o=o.substr(0,o.lastIndexOf(":"))}if(o!==""){for(const t of r){t.callbacks=n[o].callbacks.slice()}n[o].childEvents.push(i)}}function ks(t,e){const n=ms(t)[e];if(!n){return[]}let o=[n.callbacks];for(let e=0;e-1){return bs(t,e.substr(0,e.lastIndexOf(":")))}else{return null}}return n.callbacks}function ws(t,e,n){for(let[o,i]of t){if(!i){i=e.name}else if(typeof i=="function"){i=i(e.name)}const t=new ts(e.source,i);t.path=[...e.path];o.fire(t,...n)}}function Cs(t,e,n){const o=ks(t,e);for(const t of o){for(let e=0;e{Object.getOwnPropertyNames(e).concat(Object.getOwnPropertySymbols(e)).forEach((n=>{if(n in t.prototype){return}const o=Object.getOwnPropertyDescriptor(e,n);o.enumerable=false;Object.defineProperty(t.prototype,n,o)}))}))}class vs{constructor(t={},e={}){const n=As(t);if(!n){e=t}this._items=[];this._itemMap=new Map;this._idProperty=e.idProperty||"id";this._bindToExternalToInternalMap=new WeakMap;this._bindToInternalToExternalMap=new WeakMap;this._skippedIndexesFromExternal=[];if(n){for(const e of t){this._items.push(e);this._itemMap.set(this._getItemIdBeforeAdding(e),e)}}}get length(){return this._items.length}get first(){return this._items[0]||null}get last(){return this._items[this.length-1]||null}add(t,e){return this.addMany([t],e)}addMany(t,e){if(e===undefined){e=this._items.length}else if(e>this._items.length||e<0){throw new ss["a"]("collection-add-item-invalid-index",this)}for(let n=0;n{this._setUpBindToBinding((e=>new t(e)))},using:t=>{if(typeof t=="function"){this._setUpBindToBinding((e=>t(e)))}else{this._setUpBindToBinding((e=>e[t]))}}}}_setUpBindToBinding(t){const e=this._bindToCollection;const n=(n,o,i)=>{const r=e._bindToCollection==this;const s=e._bindToInternalToExternalMap.get(o);if(r&&s){this._bindToExternalToInternalMap.set(o,s);this._bindToInternalToExternalMap.set(s,o)}else{const n=t(o);if(!n){this._skippedIndexesFromExternal.push(i);return}let r=i;for(const t of this._skippedIndexesFromExternal){if(i>t){r--}}for(const t of e._skippedIndexesFromExternal){if(r>=t){r++}}this._bindToExternalToInternalMap.set(o,n);this._bindToInternalToExternalMap.set(n,o);this.add(n,r);for(let t=0;t{const o=this._bindToExternalToInternalMap.get(e);if(o){this.remove(o)}this._skippedIndexesFromExternal=this._skippedIndexesFromExternal.reduce(((t,e)=>{if(ne){t.push(e)}return t}),[])}))}_getItemIdBeforeAdding(t){const e=this._idProperty;let n;if(e in t){n=t[e];if(typeof n!="string"){throw new ss["a"]("collection-add-invalid-id",this)}if(this.get(n)){throw new ss["a"]("collection-add-item-already-exists",this)}}else{t[e]=n=ns()}return n}_remove(t){let e,n,o;let i=false;const r=this._idProperty;if(typeof t=="string"){n=t;o=this._itemMap.get(n);i=!o;if(o){e=this._items.indexOf(o)}}else if(typeof t=="number"){e=t;o=this._items[e];i=!o;if(o){n=o[r]}}else{o=t;n=o[r];e=this._items.indexOf(o);i=e==-1||!this._itemMap.get(n)}if(i){throw new ss["a"]("collection-remove-404",this)}this._items.splice(e,1);this._itemMap.delete(n);const s=this._bindToInternalToExternalMap.get(o);this._bindToInternalToExternalMap.delete(o);this._bindToExternalToInternalMap.delete(s);this.fire("remove",o,e);return[o,e]}[Symbol.iterator](){return this._items[Symbol.iterator]()}}_s(vs,ds);class ys{constructor(t,e=[],n=[]){this._context=t;this._plugins=new Map;this._availablePlugins=new Map;for(const t of e){if(t.pluginName){this._availablePlugins.set(t.pluginName,t)}}this._contextPlugins=new Map;for(const[t,e]of n){this._contextPlugins.set(t,e);this._contextPlugins.set(e,t);if(t.pluginName){this._availablePlugins.set(t.pluginName,t)}}}*[Symbol.iterator](){for(const t of this._plugins){if(typeof t[0]=="function"){yield t}}}get(t){const e=this._plugins.get(t);if(!e){let e=t;if(typeof t=="function"){e=t.pluginName||t.name}throw new ss["a"]("plugincollection-plugin-not-loaded",this._context,{plugin:e})}return e}has(t){return this._plugins.has(t)}init(t,e=[]){const n=this;const o=this._context;const i=new Set;const r=[];const s=m(t);const a=m(e);const c=f(t);if(c){const t="plugincollection-plugin-not-found";Object(ss["b"])(t,{plugins:c});return Promise.reject(new ss["a"](t,o,{plugins:c}))}return Promise.all(s.map(l)).then((()=>d(r,"init"))).then((()=>d(r,"afterInit"))).then((()=>r));function l(t){if(a.includes(t)){return}if(n._plugins.has(t)||i.has(t)){return}return u(t).catch((e=>{Object(ss["b"])("plugincollection-load",{plugin:t});throw e}))}function d(t,e){return t.reduce(((t,o)=>{if(!o[e]){return t}if(n._contextPlugins.has(o)){return t}return t.then(o[e].bind(o))}),Promise.resolve())}function u(t){return new Promise((s=>{i.add(t);if(t.requires){t.requires.forEach((n=>{const i=h(n);if(t.isContextPlugin&&!i.isContextPlugin){throw new ss["a"]("plugincollection-context-required",null,{plugin:i.name,requiredBy:t.name})}if(e.includes(i)){throw new ss["a"]("plugincollection-required",o,{plugin:i.name,requiredBy:t.name})}l(i)}))}const a=n._contextPlugins.get(t)||new t(o);n._add(t,a);r.push(a);s()}))}function h(t){if(typeof t=="function"){return t}return n._availablePlugins.get(t)}function f(t){const e=[];for(const n of t){if(!h(n)){e.push(n)}}return e.length?e:null}function m(t){return t.map((t=>h(t))).filter((t=>!!t))}}destroy(){const t=[];for(const[,e]of this){if(typeof e.destroy=="function"&&!this._contextPlugins.has(e)){t.push(e.destroy())}}return Promise.all(t)}_add(t,e){this._plugins.set(t,e);const n=t.pluginName;if(!n){return}if(this._plugins.has(n)){throw new ss["a"]("plugincollection-plugin-name-conflict",null,{pluginName:n,plugin1:this._plugins.get(n).constructor,plugin2:t})}this._plugins.set(n,e)}}_s(ys,ds);function xs(t){return Array.isArray(t)?t:[t]}if(!window.CKEDITOR_TRANSLATIONS){window.CKEDITOR_TRANSLATIONS={}}function Ds(t,e,n){if(!window.CKEDITOR_TRANSLATIONS[t]){window.CKEDITOR_TRANSLATIONS[t]={}}const o=window.CKEDITOR_TRANSLATIONS[t];o.dictionary=o.dictionary||{};o.getPluralForm=n||o.getPluralForm;Object.assign(o.dictionary,e)}function Es(t,e,n=1){if(typeof n!=="number"){throw new ss["a"]("translation-service-quantity-not-a-number",null,{quantity:n})}const o=Ss();if(o===1){t=Object.keys(window.CKEDITOR_TRANSLATIONS)[0]}const i=e.id||e.string;if(o===0||!Ts(t,i)){if(n!==1){return e.plural}return e.string}const r=window.CKEDITOR_TRANSLATIONS[t].dictionary;const s=window.CKEDITOR_TRANSLATIONS[t].getPluralForm||(t=>t===1?0:1);if(typeof r[i]==="string"){return r[i]}const a=Number(s(n));return r[i][a]}function Ms(){window.CKEDITOR_TRANSLATIONS={}}function Ts(t,e){return!!window.CKEDITOR_TRANSLATIONS[t]&&!!window.CKEDITOR_TRANSLATIONS[t].dictionary[e]}function Ss(){return Object.keys(window.CKEDITOR_TRANSLATIONS).length}const Is=["ar","fa","he","ku","ug"];class Ns{constructor(t={}){this.uiLanguage=t.uiLanguage||"en";this.contentLanguage=t.contentLanguage||this.uiLanguage;this.uiLanguageDirection=Ps(this.uiLanguage);this.contentLanguageDirection=Ps(this.contentLanguage);this.t=(t,e)=>this._t(t,e)}get language(){console.warn("locale-deprecated-language-property: "+"The Locale#language property has been deprecated and will be removed in the near future. "+"Please use #uiLanguage and #contentLanguage properties instead.");return this.uiLanguage}_t(t,e=[]){e=xs(e);if(typeof t==="string"){t={string:t}}const n=!!t.plural;const o=n?e[0]:1;const i=Es(this.uiLanguage,t,o);return Bs(i,e)}}function Bs(t,e){return t.replace(/%(\d+)/g,((t,n)=>nt.destroy()))).then((()=>this.plugins.destroy()))}_addEditor(t,e){if(this._contextOwner){throw new ss["a"]("context-addeditor-private-context")}this.editors.add(t);if(e){this._contextOwner=t}}_removeEditor(t){if(this.editors.has(t)){this.editors.remove(t)}if(this._contextOwner===t){return this.destroy()}return Promise.resolve()}_getEditorConfig(){const t={};for(const e of this.config.names()){if(!["plugins","removePlugins","extraPlugins"].includes(e)){t[e]=this.config.get(e)}}return t}static create(t){return new Promise((e=>{const n=new this(t);e(n.initPlugins().then((()=>n)))}))}}function Ls(t,e){const n=Math.min(t.length,e.length);for(let o=0;ot.data.length){throw new ss["a"]("view-textproxy-wrong-offsetintext",this)}if(n<0||e+n>t.data.length){throw new ss["a"]("view-textproxy-wrong-length",this)}this.data=t.data.substring(e,e+n);this.offsetInText=e}get offsetSize(){return this.data.length}get isPartial(){return this.data.length!==this.textNode.data.length}get parent(){return this.textNode.parent}get root(){return this.textNode.root}get document(){return this.textNode.document}is(t){return t==="$textProxy"||t==="view:$textProxy"||t==="textProxy"||t==="view:textProxy"}getAncestors(t={includeSelf:false,parentFirst:false}){const e=[];let n=t.includeSelf?this.textNode:this.parent;while(n!==null){e[t.parentFirst?"push":"unshift"](n);n=n.parent}return e}}function Hs(t){const e=new Map;for(const n in t){e.set(n,t[n])}return e}function Gs(t){if(As(t)){return new Map(t)}else{return Hs(t)}}class Ks{constructor(...t){this._patterns=[];this.add(...t)}add(...t){for(let e of t){if(typeof e=="string"||e instanceof RegExp){e={name:e}}if(e.classes&&(typeof e.classes=="string"||e.classes instanceof RegExp)){e.classes=[e.classes]}this._patterns.push(e)}}match(...t){for(const e of t){for(const t of this._patterns){const n=Ws(e,t);if(n){return{element:e,pattern:t,match:n}}}}return null}matchAll(...t){const e=[];for(const n of t){for(const t of this._patterns){const o=Ws(n,t);if(o){e.push({element:n,pattern:t,match:o})}}}return e.length>0?e:null}getElementName(){if(this._patterns.length!==1){return null}const t=this._patterns[0];const e=t.name;return typeof t!="function"&&e&&!(e instanceof RegExp)?e:null}}function Ws(t,e){if(typeof e=="function"){return e(t)}const n={};if(e.name){n.name=qs(e.name,t.name);if(!n.name){return null}}if(e.attributes){n.attributes=Ys(e.attributes,t);if(!n.attributes){return null}}if(e.classes){n.classes=Qs(e.classes,t);if(!n.classes){return false}}if(e.styles){n.styles=$s(e.styles,t);if(!n.styles){return false}}return n}function qs(t,e){if(t instanceof RegExp){return t.test(e)}return t===e}function Ys(t,e){const n=[];for(const o in t){const i=t[o];if(e.hasAttribute(o)){const t=e.getAttribute(o);if(i===true){n.push(o)}else if(i instanceof RegExp){if(i.test(t)){n.push(o)}else{return null}}else if(t===i){n.push(o)}else{return null}}else{return null}}return n}function Qs(t,e){const n=[];for(const o of t){if(o instanceof RegExp){const t=e.getClassNames();for(const e of t){if(o.test(e)){n.push(e)}}if(n.length===0){return null}}else if(e.hasClass(o)){n.push(o)}else{return null}}return n}function $s(t,e){const n=[];for(const o in t){const i=t[o];if(e.hasStyle(o)){const t=e.getStyle(o);if(i instanceof RegExp){if(i.test(t)){n.push(o)}else{return null}}else if(t===i){n.push(o)}else{return null}}else{return null}}return n}var Js="[object Symbol]";function Zs(t){return typeof t=="symbol"||D(t)&&C(t)==Js}var Xs=Zs;var ta=/\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,ea=/^\w*$/;function na(t,e){if(Qe(t)){return false}var n=typeof t;if(n=="number"||n=="symbol"||n=="boolean"||t==null||Xs(t)){return true}return ea.test(t)||!ta.test(t)||e!=null&&t in Object(e)}var oa=na;var ia="Expected a function";function ra(t,e){if(typeof t!="function"||e!=null&&typeof e!="function"){throw new TypeError(ia)}var n=function(){var o=arguments,i=e?e.apply(this,o):o[0],r=n.cache;if(r.has(i)){return r.get(i)}var s=t.apply(this,o);n.cache=r.set(i,s)||r;return s};n.cache=new(ra.Cache||Ce);return n}ra.Cache=Ce;var sa=ra;var aa=500;function ca(t){var e=sa(t,(function(t){if(n.size===aa){n.clear()}return t}));var n=e.cache;return e}var la=ca;var da=/[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g;var ua=/\\(\\)?/g;var ha=la((function(t){var e=[];if(t.charCodeAt(0)===46){e.push("")}t.replace(da,(function(t,n,o,i){e.push(o?i.replace(ua,"$1"):n||t)}));return e}));var fa=ha;function ma(t,e){var n=-1,o=t==null?0:t.length,i=Array(o);while(++ni?0:i+e}n=n>i?i:n;if(n<0){n+=i}i=e>n?0:n-e>>>0;e>>>=0;var r=Array(i);while(++o0){if(++e>=gc){return arguments[0]}}else{e=0}return t.apply(undefined,arguments)}}var wc=bc;var Cc=wc(mc);var Ac=Cc;function _c(t,e){return Ac(dc(t,e,rc),t+"")}var vc=_c;function yc(t,e,n){if(!ct(n)){return false}var o=typeof e;if(o=="number"?Zn(n)&&tn(e,n.length):o=="string"&&e in n){return R(n[e],t)}return false}var xc=yc;function Dc(t){return vc((function(e,n){var o=-1,i=n.length,r=i>1?n[i-1]:undefined,s=i>2?n[2]:undefined;r=t.length>3&&typeof r=="function"?(i--,r):undefined;if(s&&xc(n[0],n[1],s)){r=i<3?undefined:r;i=1}e=Object(e);while(++oe===t));return Array.isArray(n)}set(t,e){if(ct(t)){for(const[e,n]of Object.entries(t)){this._styleProcessor.toNormalizedForm(e,n,this._styles)}}else{this._styleProcessor.toNormalizedForm(t,e,this._styles)}}remove(t){const e=Oc(t);ja(this._styles,e);delete this._styles[t];this._cleanEmptyObjectsOnPath(e)}getNormalized(t){return this._styleProcessor.getNormalized(t,this._styles)}toString(){if(this.isEmpty){return""}return this._getStylesEntries().map((t=>t.join(":"))).sort().join(";")+";"}getAsString(t){if(this.isEmpty){return}if(this._styles[t]&&!ct(this._styles[t])){return this._styles[t]}const e=this._styleProcessor.getReducedForm(t,this._styles);const n=e.find((([e])=>e===t));if(Array.isArray(n)){return n[1]}}getStyleNames(){if(this.isEmpty){return[]}const t=this._getStylesEntries();return t.map((([t])=>t))}clear(){this._styles={}}_getStylesEntries(){const t=[];const e=Object.keys(this._styles);for(const n of e){t.push(...this._styleProcessor.getReducedForm(n,this._styles))}return t}_cleanEmptyObjectsOnPath(t){const e=t.split(".");const n=e.length>1;if(!n){return}const o=e.splice(0,e.length-1).join(".");const i=Va(this._styles,o);if(!i){return}const r=!Array.from(Object.keys(i)).length;if(r){this.remove(o)}}}class zc{constructor(){this._normalizers=new Map;this._extractors=new Map;this._reducers=new Map;this._consumables=new Map}toNormalizedForm(t,e,n){if(ct(e)){Rc(n,Oc(t),e);return}if(this._normalizers.has(t)){const o=this._normalizers.get(t);const{path:i,value:r}=o(e);Rc(n,i,r)}else{Rc(n,t,e)}}getNormalized(t,e){if(!t){return Tc({},e)}if(e[t]!==undefined){return e[t]}if(this._extractors.has(t)){const n=this._extractors.get(t);if(typeof n==="string"){return Va(e,n)}const o=n(t,e);if(o){return o}}return Va(e,Oc(t))}getReducedForm(t,e){const n=this.getNormalized(t,e);if(n===undefined){return[]}if(this._reducers.has(t)){const e=this._reducers.get(t);return e(n)}return[[t,n]]}getRelatedStyles(t){return this._consumables.get(t)||[]}setNormalizer(t,e){this._normalizers.set(t,e)}setExtractor(t,e){this._extractors.set(t,e)}setReducer(t,e){this._reducers.set(t,e)}setStyleRelation(t,e){this._mapStyleNames(t,e);for(const n of e){this._mapStyleNames(n,[t])}}_mapStyleNames(t,e){if(!this._consumables.has(t)){this._consumables.set(t,[])}this._consumables.get(t).push(...e)}}function Lc(t){let e=null;let n=0;let o=0;let i=null;const r=new Map;if(t===""){return r}if(t.charAt(t.length-1)!=";"){t=t+";"}for(let s=0;s0){yield"class"}if(!this._styles.isEmpty){yield"style"}yield*this._attrs.keys()}*getAttributes(){yield*this._attrs.entries();if(this._classes.size>0){yield["class",this.getAttribute("class")]}if(!this._styles.isEmpty){yield["style",this.getAttribute("style")]}}getAttribute(t){if(t=="class"){if(this._classes.size>0){return[...this._classes].join(" ")}return undefined}if(t=="style"){const t=this._styles.toString();return t==""?undefined:t}return this._attrs.get(t)}hasAttribute(t){if(t=="class"){return this._classes.size>0}if(t=="style"){return!this._styles.isEmpty}return this._attrs.has(t)}isSimilar(t){if(!(t instanceof jc)){return false}if(this===t){return true}if(this.name!=t.name){return false}if(this._attrs.size!==t._attrs.size||this._classes.size!==t._classes.size||this._styles.size!==t._styles.size){return false}for(const[e,n]of this._attrs){if(!t._attrs.has(e)||t._attrs.get(e)!==n){return false}}for(const e of this._classes){if(!t._classes.has(e)){return false}}for(const e of this._styles.getStyleNames()){if(!t._styles.has(e)||t._styles.getAsString(e)!==this._styles.getAsString(e)){return false}}return true}hasClass(...t){for(const e of t){if(!this._classes.has(e)){return false}}return true}getClassNames(){return this._classes.keys()}getStyle(t){return this._styles.getAsString(t)}getNormalizedStyle(t){return this._styles.getNormalized(t)}getStyleNames(){return this._styles.getStyleNames()}hasStyle(...t){for(const e of t){if(!this._styles.has(e)){return false}}return true}findAncestor(...t){const e=new Ks(...t);let n=this.parent;while(n){if(e.match(n)){return n}n=n.parent}return null}getCustomProperty(t){return this._customProperties.get(t)}*getCustomProperties(){yield*this._customProperties.entries()}getIdentity(){const t=Array.from(this._classes).sort().join(",");const e=this._styles.toString();const n=Array.from(this._attrs).map((t=>`${t[0]}="${t[1]}"`)).sort().join(" ");return this.name+(t==""?"":` class="${t}"`)+(!e?"":` style="${e}"`)+(n==""?"":` ${n}`)}_clone(t=false){const e=[];if(t){for(const n of this.getChildren()){e.push(n._clone(t))}}const n=new this.constructor(this.document,this.name,this._attrs,e);n._classes=new Set(this._classes);n._styles.set(this._styles.getNormalized());n._customProperties=new Map(this._customProperties);n.getFillerOffset=this.getFillerOffset;return n}_appendChild(t){return this._insertChild(this.childCount,t)}_insertChild(t,e){this._fireChange("children",this);let n=0;const o=Uc(this.document,e);for(const e of o){if(e.parent!==null){e._remove()}e.parent=this;e.document=this.document;this._children.splice(t,0,e);t++;n++}return n}_removeChildren(t,e=1){this._fireChange("children",this);for(let n=t;n0){this._classes.clear();return true}return false}if(t=="style"){if(!this._styles.isEmpty){this._styles.clear();return true}return false}return this._attrs.delete(t)}_addClass(t){this._fireChange("attributes",this);for(const e of xs(t)){this._classes.add(e)}}_removeClass(t){this._fireChange("attributes",this);for(const e of xs(t)){this._classes.delete(e)}}_setStyle(t,e){this._fireChange("attributes",this);this._styles.set(t,e)}_removeStyle(t){this._fireChange("attributes",this);for(const e of xs(t)){this._styles.remove(e)}}_setCustomProperty(t,e){this._customProperties.set(t,e)}_removeCustomProperty(t){return this._customProperties.delete(t)}}function Fc(t){t=Gs(t);for(const[e,n]of t){if(n===null){t.delete(e)}else if(typeof n!="string"){t.set(e,String(n))}}return t}function Vc(t,e){const n=e.split(/\s+/);t.clear();n.forEach((e=>t.add(e)))}function Uc(t,e){if(typeof e=="string"){return[new Vs(t,e)]}if(!As(e)){e=[e]}return Array.from(e).map((e=>{if(typeof e=="string"){return new Vs(t,e)}if(e instanceof Us){return new Vs(t,e.data)}return e}))}class Hc extends jc{constructor(t,e,n,o){super(t,e,n,o);this.getFillerOffset=Gc}is(t,e=null){if(!e){return t==="containerElement"||t==="view:containerElement"||t==="element"||t==="view:element"||t==="node"||t==="view:node"}else{return e===this.name&&(t==="containerElement"||t==="view:containerElement"||t==="element"||t==="view:element")}}}function Gc(){const t=[...this.getChildren()];const e=t[this.childCount-1];if(e&&e.is("element","br")){return this.childCount}for(const e of t){if(!e.is("uiElement")){return null}}return this.childCount}var Kc=Ec((function(t,e){Oe(e,uo(e),t)}));var Wc=Kc;const qc=Symbol("observableProperties");const Yc=Symbol("boundObservables");const Qc=Symbol("boundProperties");const $c={set(t,e){if(ct(t)){Object.keys(t).forEach((e=>{this.set(e,t[e])}),this);return}Zc(this);const n=this[qc];if(t in this&&!n.has(t)){throw new ss["a"]("observable-set-cannot-override",this)}Object.defineProperty(this,t,{enumerable:true,configurable:true,get(){return n.get(t)},set(e){const o=n.get(t);let i=this.fire("set:"+t,t,e,o);if(i===undefined){i=e}if(o!==i||!n.has(t)){n.set(t,i);this.fire("change:"+t,t,i,o)}}});this[t]=e},bind(...t){if(!t.length||!nl(t)){throw new ss["a"]("observable-bind-wrong-properties",this)}if(new Set(t).size!==t.length){throw new ss["a"]("observable-bind-duplicate-properties",this)}Zc(this);const e=this[Qc];t.forEach((t=>{if(e.has(t)){throw new ss["a"]("observable-bind-rebind",this)}}));const n=new Map;t.forEach((t=>{const o={property:t,to:[]};e.set(t,o);n.set(t,o)}));return{to:Xc,toMany:tl,_observable:this,_bindProperties:t,_to:[],_bindings:n}},unbind(...t){if(!this[qc]){return}const e=this[Qc];const n=this[Yc];if(t.length){if(!nl(t)){throw new ss["a"]("observable-unbind-wrong-properties",this)}t.forEach((t=>{const o=e.get(t);if(!o){return}let i,r,s,a;o.to.forEach((t=>{i=t[0];r=t[1];s=n.get(i);a=s[r];a.delete(o);if(!a.size){delete s[r]}if(!Object.keys(s).length){n.delete(i);this.stopListening(i,"change")}}));e.delete(t)}))}else{n.forEach(((t,e)=>{this.stopListening(e,"change")}));n.clear();e.clear()}},decorate(t){const e=this[t];if(!e){throw new ss["a"]("observablemixin-cannot-decorate-undefined",this,{object:this,methodName:t})}this.on(t,((t,n)=>{t.return=e.apply(this,n)}));this[t]=function(...e){return this.fire(t,e)}}};Wc($c,ds);var Jc=$c;function Zc(t){if(t[qc]){return}Object.defineProperty(t,qc,{value:new Map});Object.defineProperty(t,Yc,{value:new Map});Object.defineProperty(t,Qc,{value:new Map})}function Xc(...t){const e=ol(...t);const n=Array.from(this._bindings.keys());const o=n.length;if(!e.callback&&e.to.length>1){throw new ss["a"]("observable-bind-to-no-callback",this)}if(o>1&&e.callback){throw new ss["a"]("observable-bind-to-extra-callback",this)}e.to.forEach((t=>{if(t.properties.length&&t.properties.length!==o){throw new ss["a"]("observable-bind-to-properties-length",this)}if(!t.properties.length){t.properties=this._bindProperties}}));this._to=e.to;if(e.callback){this._bindings.get(n[0]).callback=e.callback}al(this._observable,this._to);rl(this);this._bindProperties.forEach((t=>{sl(this._observable,t)}))}function tl(t,e,n){if(this._bindings.size>1){throw new ss["a"]("observable-bind-to-many-not-one-binding",this)}this.to(...el(t,e),n)}function el(t,e){const n=t.map((t=>[t,e]));return Array.prototype.concat.apply([],n)}function nl(t){return t.every((t=>typeof t=="string"))}function ol(...t){if(!t.length){throw new ss["a"]("observable-bind-to-parse-error",null)}const e={to:[]};let n;if(typeof t[t.length-1]=="function"){e.callback=t.pop()}t.forEach((t=>{if(typeof t=="string"){n.properties.push(t)}else if(typeof t=="object"){n={observable:t,properties:[]};e.to.push(n)}else{throw new ss["a"]("observable-bind-to-parse-error",null)}}));return e}function il(t,e,n,o){const i=t[Yc];const r=i.get(n);const s=r||{};if(!s[o]){s[o]=new Set}s[o].add(e);if(!r){i.set(n,s)}}function rl(t){let e;t._bindings.forEach(((n,o)=>{t._to.forEach((i=>{e=i.properties[n.callback?0:t._bindProperties.indexOf(o)];n.to.push([i.observable,e]);il(t._observable,n,i.observable,e)}))}))}function sl(t,e){const n=t[Qc];const o=n.get(e);let i;if(o.callback){i=o.callback.apply(t,o.to.map((t=>t[0][t[1]])))}else{i=o.to[0];i=i[0][i[1]]}if(Object.prototype.hasOwnProperty.call(t,e)){t[e]=i}else{t.set(e,i)}}function al(t,e){e.forEach((e=>{const n=t[Yc];let o;if(!n.get(e.observable)){t.listenTo(e.observable,"change",((i,r)=>{o=n.get(e.observable)[r];if(o){o.forEach((e=>{sl(t,e.property)}))}}))}}))}class cl extends Hc{constructor(t,e,n,o){super(t,e,n,o);this.set("isReadOnly",false);this.set("isFocused",false);this.bind("isReadOnly").to(t);this.bind("isFocused").to(t,"isFocused",(e=>e&&t.selection.editableElement==this));this.listenTo(t.selection,"change",(()=>{this.isFocused=t.isFocused&&t.selection.editableElement==this}))}is(t,e=null){if(!e){return t==="editableElement"||t==="view:editableElement"||t==="containerElement"||t==="view:containerElement"||t==="element"||t==="view:element"||t==="node"||t==="view:node"}else{return e===this.name&&(t==="editableElement"||t==="view:editableElement"||t==="containerElement"||t==="view:containerElement"||t==="element"||t==="view:element")}}destroy(){this.stopListening()}}_s(cl,Jc);const ll=Symbol("rootName");class dl extends cl{constructor(t,e){super(t,e);this.rootName="main"}is(t,e=null){if(!e){return t==="rootElement"||t==="view:rootElement"||t==="editableElement"||t==="view:editableElement"||t==="containerElement"||t==="view:containerElement"||t==="element"||t==="view:element"||t==="node"||t==="view:node"}else{return e===this.name&&(t==="rootElement"||t==="view:rootElement"||t==="editableElement"||t==="view:editableElement"||t==="containerElement"||t==="view:containerElement"||t==="element"||t==="view:element")}}get rootName(){return this.getCustomProperty(ll)}set rootName(t){this._setCustomProperty(ll,t)}set _name(t){this.name=t}}class ul{constructor(t={}){if(!t.boundaries&&!t.startPosition){throw new ss["a"]("view-tree-walker-no-start-position",null)}if(t.direction&&t.direction!="forward"&&t.direction!="backward"){throw new ss["a"]("view-tree-walker-unknown-direction",t.startPosition,{direction:t.direction})}this.boundaries=t.boundaries||null;if(t.startPosition){this.position=hl._createAt(t.startPosition)}else{this.position=hl._createAt(t.boundaries[t.direction=="backward"?"end":"start"])}this.direction=t.direction||"forward";this.singleCharacters=!!t.singleCharacters;this.shallow=!!t.shallow;this.ignoreElementEnd=!!t.ignoreElementEnd;this._boundaryStartParent=this.boundaries?this.boundaries.start.parent:null;this._boundaryEndParent=this.boundaries?this.boundaries.end.parent:null}[Symbol.iterator](){return this}skip(t){let e,n,o;do{o=this.position;({done:e,value:n}=this.next())}while(!e&&t(n));if(!e){this.position=o}}next(){if(this.direction=="forward"){return this._next()}else{return this._previous()}}_next(){let t=this.position.clone();const e=this.position;const n=t.parent;if(n.parent===null&&t.offset===n.childCount){return{done:true}}if(n===this._boundaryEndParent&&t.offset==this.boundaries.end.offset){return{done:true}}let o;if(n instanceof Vs){if(t.isAtEnd){this.position=hl._createAfter(n);return this._next()}o=n.data[t.offset]}else{o=n.getChild(t.offset)}if(o instanceof jc){if(!this.shallow){t=new hl(o,0)}else{t.offset++}this.position=t;return this._formatReturnValue("elementStart",o,e,t,1)}else if(o instanceof Vs){if(this.singleCharacters){t=new hl(o,0);this.position=t;return this._next()}else{let n=o.data.length;let i;if(o==this._boundaryEndParent){n=this.boundaries.end.offset;i=new Us(o,0,n);t=hl._createAfter(i)}else{i=new Us(o,0,o.data.length);t.offset++}this.position=t;return this._formatReturnValue("text",i,e,t,n)}}else if(typeof o=="string"){let o;if(this.singleCharacters){o=1}else{const e=n===this._boundaryEndParent?this.boundaries.end.offset:n.data.length;o=e-t.offset}const i=new Us(n,t.offset,o);t.offset+=o;this.position=t;return this._formatReturnValue("text",i,e,t,o)}else{t=hl._createAfter(n);this.position=t;if(this.ignoreElementEnd){return this._next()}else{return this._formatReturnValue("elementEnd",n,e,t)}}}_previous(){let t=this.position.clone();const e=this.position;const n=t.parent;if(n.parent===null&&t.offset===0){return{done:true}}if(n==this._boundaryStartParent&&t.offset==this.boundaries.start.offset){return{done:true}}let o;if(n instanceof Vs){if(t.isAtStart){this.position=hl._createBefore(n);return this._previous()}o=n.data[t.offset-1]}else{o=n.getChild(t.offset-1)}if(o instanceof jc){if(!this.shallow){t=new hl(o,o.childCount);this.position=t;if(this.ignoreElementEnd){return this._previous()}else{return this._formatReturnValue("elementEnd",o,e,t)}}else{t.offset--;this.position=t;return this._formatReturnValue("elementStart",o,e,t,1)}}else if(o instanceof Vs){if(this.singleCharacters){t=new hl(o,o.data.length);this.position=t;return this._previous()}else{let n=o.data.length;let i;if(o==this._boundaryStartParent){const e=this.boundaries.start.offset;i=new Us(o,e,o.data.length-e);n=i.data.length;t=hl._createBefore(i)}else{i=new Us(o,0,o.data.length);t.offset--}this.position=t;return this._formatReturnValue("text",i,e,t,n)}}else if(typeof o=="string"){let o;if(!this.singleCharacters){const e=n===this._boundaryStartParent?this.boundaries.start.offset:0;o=t.offset-e}else{o=1}t.offset-=o;const i=new Us(n,t.offset,o);this.position=t;return this._formatReturnValue("text",i,e,t,o)}else{t=hl._createBefore(n);this.position=t;return this._formatReturnValue("elementStart",n,e,t,1)}}_formatReturnValue(t,e,n,o,i){if(e instanceof Us){if(e.offsetInText+e.data.length==e.textNode.data.length){if(this.direction=="forward"&&!(this.boundaries&&this.boundaries.end.isEqual(this.position))){o=hl._createAfter(e.textNode);this.position=o}else{n=hl._createAfter(e.textNode)}}if(e.offsetInText===0){if(this.direction=="backward"&&!(this.boundaries&&this.boundaries.start.isEqual(this.position))){o=hl._createBefore(e.textNode);this.position=o}else{n=hl._createBefore(e.textNode)}}}return{done:false,value:{type:t,item:e,previousPosition:n,nextPosition:o,length:i}}}}class hl{constructor(t,e){this.parent=t;this.offset=e}get nodeAfter(){if(this.parent.is("$text")){return null}return this.parent.getChild(this.offset)||null}get nodeBefore(){if(this.parent.is("$text")){return null}return this.parent.getChild(this.offset-1)||null}get isAtStart(){return this.offset===0}get isAtEnd(){const t=this.parent.is("$text")?this.parent.data.length:this.parent.childCount;return this.offset===t}get root(){return this.parent.root}get editableElement(){let t=this.parent;while(!(t instanceof cl)){if(t.parent){t=t.parent}else{return null}}return t}getShiftedBy(t){const e=hl._createAt(this);const n=e.offset+t;e.offset=n<0?0:n;return e}getLastMatchingPosition(t,e={}){e.startPosition=this;const n=new ul(e);n.skip(t);return n.position}getAncestors(){if(this.parent.is("documentFragment")){return[this.parent]}else{return this.parent.getAncestors({includeSelf:true})}}getCommonAncestor(t){const e=this.getAncestors();const n=t.getAncestors();let o=0;while(e[o]==n[o]&&e[o]){o++}return o===0?null:e[o-1]}is(t){return t==="position"||t==="view:position"}isEqual(t){return this.parent==t.parent&&this.offset==t.offset}isBefore(t){return this.compareWith(t)=="before"}isAfter(t){return this.compareWith(t)=="after"}compareWith(t){if(this.root!==t.root){return"different"}if(this.isEqual(t)){return"same"}const e=this.parent.is("node")?this.parent.getPath():[];const n=t.parent.is("node")?t.parent.getPath():[];e.push(this.offset);n.push(t.offset);const o=Ls(e,n);switch(o){case"prefix":return"before";case"extension":return"after";default:return e[o]0?new this(n,o):new this(o,n)}static _createIn(t){return this._createFromParentsAndOffsets(t,0,t,t.childCount)}static _createOn(t){const e=t.is("$textProxy")?t.offsetSize:1;return this._createFromPositionAndShift(hl._createBefore(t),e)}}function ml(t){if(t.item.is("attributeElement")||t.item.is("uiElement")){return true}return false}function gl(t){let e=0;for(const n of t){e++}return e}class pl{constructor(t=null,e,n){this._ranges=[];this._lastRangeBackward=false;this._isFake=false;this._fakeSelectionLabel="";this.setTo(t,e,n)}get isFake(){return this._isFake}get fakeSelectionLabel(){return this._fakeSelectionLabel}get anchor(){if(!this._ranges.length){return null}const t=this._ranges[this._ranges.length-1];const e=this._lastRangeBackward?t.end:t.start;return e.clone()}get focus(){if(!this._ranges.length){return null}const t=this._ranges[this._ranges.length-1];const e=this._lastRangeBackward?t.start:t.end;return e.clone()}get isCollapsed(){return this.rangeCount===1&&this._ranges[0].isCollapsed}get rangeCount(){return this._ranges.length}get isBackward(){return!this.isCollapsed&&this._lastRangeBackward}get editableElement(){if(this.anchor){return this.anchor.editableElement}return null}*getRanges(){for(const t of this._ranges){yield t.clone()}}getFirstRange(){let t=null;for(const e of this._ranges){if(!t||e.start.isBefore(t.start)){t=e}}return t?t.clone():null}getLastRange(){let t=null;for(const e of this._ranges){if(!t||e.end.isAfter(t.end)){t=e}}return t?t.clone():null}getFirstPosition(){const t=this.getFirstRange();return t?t.start.clone():null}getLastPosition(){const t=this.getLastRange();return t?t.end.clone():null}isEqual(t){if(this.isFake!=t.isFake){return false}if(this.isFake&&this.fakeSelectionLabel!=t.fakeSelectionLabel){return false}if(this.rangeCount!=t.rangeCount){return false}else if(this.rangeCount===0){return true}if(!this.anchor.isEqual(t.anchor)||!this.focus.isEqual(t.focus)){return false}for(const e of this._ranges){let n=false;for(const o of t._ranges){if(e.isEqual(o)){n=true;break}}if(!n){return false}}return true}isSimilar(t){if(this.isBackward!=t.isBackward){return false}const e=gl(this.getRanges());const n=gl(t.getRanges());if(e!=n){return false}if(e==0){return true}for(let e of this.getRanges()){e=e.getTrimmed();let n=false;for(let o of t.getRanges()){o=o.getTrimmed();if(e.start.isEqual(o.start)&&e.end.isEqual(o.end)){n=true;break}}if(!n){return false}}return true}getSelectedElement(){if(this.rangeCount!==1){return null}return this.getFirstRange().getContainedElement()}setTo(t,e,n){if(t===null){this._setRanges([]);this._setFakeOptions(e)}else if(t instanceof pl||t instanceof kl){this._setRanges(t.getRanges(),t.isBackward);this._setFakeOptions({fake:t.isFake,label:t.fakeSelectionLabel})}else if(t instanceof fl){this._setRanges([t],e&&e.backward);this._setFakeOptions(e)}else if(t instanceof hl){this._setRanges([new fl(t)]);this._setFakeOptions(e)}else if(t instanceof Fs){const o=!!n&&!!n.backward;let i;if(e===undefined){throw new ss["a"]("view-selection-setto-required-second-parameter",this)}else if(e=="in"){i=fl._createIn(t)}else if(e=="on"){i=fl._createOn(t)}else{i=new fl(hl._createAt(t,e))}this._setRanges([i],o);this._setFakeOptions(n)}else if(As(t)){this._setRanges(t,e&&e.backward);this._setFakeOptions(e)}else{throw new ss["a"]("view-selection-setto-not-selectable",this)}this.fire("change")}setFocus(t,e){if(this.anchor===null){throw new ss["a"]("view-selection-setfocus-no-ranges",this)}const n=hl._createAt(t,e);if(n.compareWith(this.focus)=="same"){return}const o=this.anchor;this._ranges.pop();if(n.compareWith(o)=="before"){this._addRange(new fl(n,o),true)}else{this._addRange(new fl(o,n))}this.fire("change")}is(t){return t==="selection"||t==="view:selection"}_setRanges(t,e=false){t=Array.from(t);this._ranges=[];for(const e of t){this._addRange(e)}this._lastRangeBackward=!!e}_setFakeOptions(t={}){this._isFake=!!t.fake;this._fakeSelectionLabel=t.fake?t.label||"":""}_addRange(t,e=false){if(!(t instanceof fl)){throw new ss["a"]("view-selection-add-range-not-range",this)}this._pushRange(t);this._lastRangeBackward=!!e}_pushRange(t){for(const e of this._ranges){if(t.isIntersecting(e)){throw new ss["a"]("view-selection-range-intersects",this,{addedRange:t,intersectingRange:e})}}this._ranges.push(new fl(t.start,t.end))}}_s(pl,ds);class kl{constructor(t=null,e,n){this._selection=new pl;this._selection.delegate("change").to(this);this._selection.setTo(t,e,n)}get isFake(){return this._selection.isFake}get fakeSelectionLabel(){return this._selection.fakeSelectionLabel}get anchor(){return this._selection.anchor}get focus(){return this._selection.focus}get isCollapsed(){return this._selection.isCollapsed}get rangeCount(){return this._selection.rangeCount}get isBackward(){return this._selection.isBackward}get editableElement(){return this._selection.editableElement}get _ranges(){return this._selection._ranges}*getRanges(){yield*this._selection.getRanges()}getFirstRange(){return this._selection.getFirstRange()}getLastRange(){return this._selection.getLastRange()}getFirstPosition(){return this._selection.getFirstPosition()}getLastPosition(){return this._selection.getLastPosition()}getSelectedElement(){return this._selection.getSelectedElement()}isEqual(t){return this._selection.isEqual(t)}isSimilar(t){return this._selection.isSimilar(t)}is(t){return t==="selection"||t=="documentSelection"||t=="view:selection"||t=="view:documentSelection"}_setTo(t,e,n){this._selection.setTo(t,e,n)}_setFocus(t,e){this._selection.setFocus(t,e)}}_s(kl,ds);class bl{constructor(t){this.selection=new kl;this.roots=new vs({idProperty:"rootName"});this.stylesProcessor=t;this.set("isReadOnly",false);this.set("isFocused",false);this.set("isComposing",false);this._postFixers=new Set}getRoot(t="main"){return this.roots.get(t)}registerPostFixer(t){this._postFixers.add(t)}destroy(){this.roots.map((t=>t.destroy()));this.stopListening()}_callPostFixers(t){let e=false;do{for(const n of this._postFixers){e=n(t);if(e){break}}}while(e)}}_s(bl,Jc);const wl=10;class Cl extends jc{constructor(t,e,n,o){super(t,e,n,o);this.getFillerOffset=Al;this._priority=wl;this._id=null;this._clonesGroup=null}get priority(){return this._priority}get id(){return this._id}getElementsWithSameId(){if(this.id===null){throw new ss["a"]("attribute-element-get-elements-with-same-id-no-id",this)}return new Set(this._clonesGroup)}is(t,e=null){if(!e){return t==="attributeElement"||t==="view:attributeElement"||t==="element"||t==="view:element"||t==="node"||t==="view:node"}else{return e===this.name&&(t==="attributeElement"||t==="view:attributeElement"||t==="element"||t==="view:element")}}isSimilar(t){if(this.id!==null||t.id!==null){return this.id===t.id}return super.isSimilar(t)&&this.priority==t.priority}_clone(t){const e=super._clone(t);e._priority=this._priority;e._id=this._id;return e}}Cl.DEFAULT_PRIORITY=wl;function Al(){if(_l(this)){return null}let t=this.parent;while(t&&t.is("attributeElement")){if(_l(t)>1){return null}t=t.parent}if(!t||_l(t)>1){return null}return this.childCount}function _l(t){return Array.from(t.getChildren()).filter((t=>!t.is("uiElement"))).length}class vl extends jc{constructor(t,e,n,o){super(t,e,n,o);this.getFillerOffset=yl}is(t,e=null){if(!e){return t==="emptyElement"||t==="view:emptyElement"||t==="element"||t==="view:element"||t==="node"||t==="view:node"}else{return e===this.name&&(t==="emptyElement"||t==="view:emptyElement"||t==="element"||t==="view:element")}}_insertChild(t,e){if(e&&(e instanceof Fs||Array.from(e).length>0)){throw new ss["a"]("view-emptyelement-cannot-add",[this,e])}}}function yl(){return null}const xl=navigator.userAgent.toLowerCase();const Dl={isMac:Ml(xl),isGecko:Tl(xl),isSafari:Sl(xl),isAndroid:Il(xl),isBlink:Nl(xl),features:{isRegExpUnicodePropertySupported:Bl()}};var El=Dl;function Ml(t){return t.indexOf("macintosh")>-1}function Tl(t){return!!t.match(/gecko\/\d+/)}function Sl(t){return t.indexOf(" applewebkit/")>-1&&t.indexOf("chrome")===-1}function Il(t){return t.indexOf("android")>-1}function Nl(t){return t.indexOf("chrome/")>-1&&t.indexOf("edge/")<0}function Bl(){let t=false;try{t="ć".search(new RegExp("[\\p{L}]","u"))===0}catch(t){}return t}const Pl={"⌘":"ctrl","⇧":"shift","⌥":"alt"};const zl={ctrl:"⌘",shift:"⇧",alt:"⌥"};const Ll=Hl();function Ol(t){let e;if(typeof t=="string"){e=Ll[t.toLowerCase()];if(!e){throw new ss["a"]("keyboard-unknown-key",null,{key:t})}}else{e=t.keyCode+(t.altKey?Ll.alt:0)+(t.ctrlKey?Ll.ctrl:0)+(t.shiftKey?Ll.shift:0)}return e}function Rl(t){if(typeof t=="string"){t=Gl(t)}return t.map((t=>typeof t=="string"?Ol(t):t)).reduce(((t,e)=>e+t),0)}function jl(t){if(!El.isMac){return t}return Gl(t).map((t=>zl[t.toLowerCase()]||t)).reduce(((t,e)=>{if(t.slice(-1)in Pl){return t+e}else{return t+"+"+e}}))}function Fl(t){return t==Ll.arrowright||t==Ll.arrowleft||t==Ll.arrowup||t==Ll.arrowdown}function Vl(t,e){const n=e==="ltr";switch(t){case Ll.arrowleft:return n?"left":"right";case Ll.arrowright:return n?"right":"left";case Ll.arrowup:return"up";case Ll.arrowdown:return"down"}}function Ul(t,e){const n=Vl(t,e);return n==="down"||n==="right"}function Hl(){const t={arrowleft:37,arrowup:38,arrowright:39,arrowdown:40,backspace:8,delete:46,enter:13,space:32,esc:27,tab:9,ctrl:1114112,cmd:1114112,shift:2228224,alt:4456448};for(let e=65;e<=90;e++){const n=String.fromCharCode(e);t[n.toLowerCase()]=e}for(let e=48;e<=57;e++){t[e-48]=e}for(let e=112;e<=123;e++){t["f"+(e-111)]=e}return t}function Gl(t){return t.split(/\s*\+\s*/)}class Kl extends jc{constructor(t,e,n,o){super(t,e,n,o);this.getFillerOffset=ql}is(t,e=null){if(!e){return t==="uiElement"||t==="view:uiElement"||t==="element"||t==="view:element"||t==="node"||t==="view:node"}else{return e===this.name&&(t==="uiElement"||t==="view:uiElement"||t==="element"||t==="view:element")}}_insertChild(t,e){if(e&&(e instanceof Fs||Array.from(e).length>0)){throw new ss["a"]("view-uielement-cannot-add",this)}}render(t){return this.toDomElement(t)}toDomElement(t){const e=t.createElement(this.name);for(const t of this.getAttributeKeys()){e.setAttribute(t,this.getAttribute(t))}return e}}function Wl(t){t.document.on("keydown",((e,n)=>Yl(e,n,t.domConverter)))}function ql(){return null}function Yl(t,e,n){if(e.keyCode==Ll.arrowright){const t=e.domTarget.ownerDocument.defaultView.getSelection();const o=t.rangeCount==1&&t.getRangeAt(0).collapsed;if(o||e.shiftKey){const e=t.focusNode;const i=t.focusOffset;const r=n.domPositionToView(e,i);if(r===null){return}let s=false;const a=r.getLastMatchingPosition((t=>{if(t.item.is("uiElement")){s=true}if(t.item.is("uiElement")||t.item.is("attributeElement")){return true}return false}));if(s){const e=n.viewPositionToDom(a);if(o){t.collapse(e.parent,e.offset)}else{t.extend(e.parent,e.offset)}}}}}class Ql extends jc{constructor(t,e,n,o){super(t,e,n,o);this.getFillerOffset=$l}is(t,e=null){if(!e){return t==="rawElement"||t==="view:rawElement"||t===this.name||t==="view:"+this.name||t==="element"||t==="view:element"||t==="node"||t==="view:node"}else{return e===this.name&&(t==="rawElement"||t==="view:rawElement"||t==="element"||t==="view:element")}}_insertChild(t,e){if(e&&(e instanceof Fs||Array.from(e).length>0)){throw new ss["a"]("view-rawelement-cannot-add",[this,e])}}}function $l(){return null}class Jl{constructor(t,e){this.document=t;this._children=[];if(e){this._insertChild(0,e)}}[Symbol.iterator](){return this._children[Symbol.iterator]()}get childCount(){return this._children.length}get isEmpty(){return this.childCount===0}get root(){return this}get parent(){return null}is(t){return t==="documentFragment"||t==="view:documentFragment"}_appendChild(t){return this._insertChild(this.childCount,t)}getChild(t){return this._children[t]}getChildIndex(t){return this._children.indexOf(t)}getChildren(){return this._children[Symbol.iterator]()}_insertChild(t,e){this._fireChange("children",this);let n=0;const o=Zl(this.document,e);for(const e of o){if(e.parent!==null){e._remove()}e.parent=this;this._children.splice(t,0,e);t++;n++}return n}_removeChildren(t,e=1){this._fireChange("children",this);for(let n=t;n{if(typeof e=="string"){return new Vs(t,e)}if(e instanceof Us){return new Vs(t,e.data)}return e}))}class Xl{constructor(t){this.document=t;this._cloneGroups=new Map}setSelection(t,e,n){this.document.selection._setTo(t,e,n)}setSelectionFocus(t,e){this.document.selection._setFocus(t,e)}createText(t){return new Vs(this.document,t)}createAttributeElement(t,e,n={}){const o=new Cl(this.document,t,e);if(n.priority){o._priority=n.priority}if(n.id){o._id=n.id}return o}createContainerElement(t,e){return new Hc(this.document,t,e)}createEditableElement(t,e){const n=new cl(this.document,t,e);n._document=this.document;return n}createEmptyElement(t,e){return new vl(this.document,t,e)}createUIElement(t,e,n){const o=new Kl(this.document,t,e);if(n){o.render=n}return o}createRawElement(t,e,n){const o=new Ql(this.document,t,e);o.render=n||(()=>{});return o}setAttribute(t,e,n){n._setAttribute(t,e)}removeAttribute(t,e){e._removeAttribute(t)}addClass(t,e){e._addClass(t)}removeClass(t,e){e._removeClass(t)}setStyle(t,e,n){if(P(t)&&n===undefined){n=e}n._setStyle(t,e)}removeStyle(t,e){e._removeStyle(t)}setCustomProperty(t,e,n){n._setCustomProperty(t,e)}removeCustomProperty(t,e){return e._removeCustomProperty(t)}breakAttributes(t){if(t instanceof hl){return this._breakAttributes(t)}else{return this._breakAttributesRange(t)}}breakContainer(t){const e=t.parent;if(!e.is("containerElement")){throw new ss["a"]("view-writer-break-non-container-element",this.document)}if(!e.parent){throw new ss["a"]("view-writer-break-root",this.document)}if(t.isAtStart){return hl._createBefore(e)}else if(!t.isAtEnd){const n=e._clone(false);this.insert(hl._createAfter(e),n);const o=new fl(t,hl._createAt(e,"end"));const i=new hl(n,0);this.move(o,i)}return hl._createAfter(e)}mergeAttributes(t){const e=t.offset;const n=t.parent;if(n.is("$text")){return t}if(n.is("attributeElement")&&n.childCount===0){const t=n.parent;const e=n.index;n._remove();this._removeFromClonedElementsGroup(n);return this.mergeAttributes(new hl(t,e))}const o=n.getChild(e-1);const i=n.getChild(e);if(!o||!i){return t}if(o.is("$text")&&i.is("$text")){return rd(o,i)}else if(o.is("attributeElement")&&i.is("attributeElement")&&o.isSimilar(i)){const t=o.childCount;o._appendChild(i.getChildren());i._remove();this._removeFromClonedElementsGroup(i);return this.mergeAttributes(new hl(o,t))}return t}mergeContainers(t){const e=t.nodeBefore;const n=t.nodeAfter;if(!e||!n||!e.is("containerElement")||!n.is("containerElement")){throw new ss["a"]("view-writer-merge-containers-invalid-position",this.document)}const o=e.getChild(e.childCount-1);const i=o instanceof Vs?hl._createAt(o,"end"):hl._createAt(e,"end");this.move(fl._createIn(n),hl._createAt(e,"end"));this.remove(fl._createOn(n));return i}insert(t,e){e=As(e)?[...e]:[e];sd(e,this.document);const n=ed(t);if(!n){throw new ss["a"]("view-writer-invalid-position-container",this.document)}const o=this._breakAttributes(t,true);const i=n._insertChild(o.offset,e);for(const t of e){this._addToClonedElementsGroup(t)}const r=o.getShiftedBy(i);const s=this.mergeAttributes(o);if(i===0){return new fl(s,s)}else{if(!s.isEqual(o)){r.offset--}const t=this.mergeAttributes(r);return new fl(s,t)}}remove(t){const e=t instanceof fl?t:fl._createOn(t);ld(e,this.document);if(e.isCollapsed){return new Jl(this.document)}const{start:n,end:o}=this._breakAttributesRange(e,true);const i=n.parent;const r=o.offset-n.offset;const s=i._removeChildren(n.offset,r);for(const t of s){this._removeFromClonedElementsGroup(t)}const a=this.mergeAttributes(n);e.start=a;e.end=a.clone();return new Jl(this.document,s)}clear(t,e){ld(t,this.document);const n=t.getWalker({direction:"backward",ignoreElementEnd:true});for(const o of n){const n=o.item;let i;if(n.is("element")&&e.isSimilar(n)){i=fl._createOn(n)}else if(!o.nextPosition.isAfter(t.start)&&n.is("$textProxy")){const t=n.getAncestors().find((t=>t.is("element")&&e.isSimilar(t)));if(t){i=fl._createIn(t)}}if(i){if(i.end.isAfter(t.end)){i.end=t.end}if(i.start.isBefore(t.start)){i.start=t.start}this.remove(i)}}}move(t,e){let n;if(e.isAfter(t.end)){e=this._breakAttributes(e,true);const o=e.parent;const i=o.childCount;t=this._breakAttributesRange(t,true);n=this.remove(t);e.offset+=o.childCount-i}else{n=this.remove(t)}return this.insert(e,n)}wrap(t,e){if(!(e instanceof Cl)){throw new ss["a"]("view-writer-wrap-invalid-attribute",this.document)}ld(t,this.document);if(!t.isCollapsed){return this._wrapRange(t,e)}else{let n=t.start;if(n.parent.is("element")&&!td(n.parent)){n=n.getLastMatchingPosition((t=>t.item.is("uiElement")))}n=this._wrapPosition(n,e);const o=this.document.selection;if(o.isCollapsed&&o.getFirstPosition().isEqual(t.start)){this.setSelection(n)}return new fl(n)}}unwrap(t,e){if(!(e instanceof Cl)){throw new ss["a"]("view-writer-unwrap-invalid-attribute",this.document)}ld(t,this.document);if(t.isCollapsed){return t}const{start:n,end:o}=this._breakAttributesRange(t,true);const i=n.parent;const r=this._unwrapChildren(i,n.offset,o.offset,e);const s=this.mergeAttributes(r.start);if(!s.isEqual(r.start)){r.end.offset--}const a=this.mergeAttributes(r.end);return new fl(s,a)}rename(t,e){const n=new Hc(this.document,t,e.getAttributes());this.insert(hl._createAfter(e),n);this.move(fl._createIn(e),hl._createAt(n,0));this.remove(fl._createOn(e));return n}clearClonedElementsGroup(t){this._cloneGroups.delete(t)}createPositionAt(t,e){return hl._createAt(t,e)}createPositionAfter(t){return hl._createAfter(t)}createPositionBefore(t){return hl._createBefore(t)}createRange(t,e){return new fl(t,e)}createRangeOn(t){return fl._createOn(t)}createRangeIn(t){return fl._createIn(t)}createSelection(t,e,n){return new pl(t,e,n)}_wrapChildren(t,e,n,o){let i=e;const r=[];while(ifalse;t.parent._insertChild(t.offset,n);const o=new fl(t,t.getShiftedBy(1));this.wrap(o,e);const i=new hl(n.parent,n.index);n._remove();const r=i.nodeBefore;const s=i.nodeAfter;if(r instanceof Vs&&s instanceof Vs){return rd(r,s)}return od(i)}_wrapAttributeElement(t,e){if(!dd(t,e)){return false}if(t.name!==e.name||t.priority!==e.priority){return false}for(const n of t.getAttributeKeys()){if(n==="class"||n==="style"){continue}if(e.hasAttribute(n)&&e.getAttribute(n)!==t.getAttribute(n)){return false}}for(const n of t.getStyleNames()){if(e.hasStyle(n)&&e.getStyle(n)!==t.getStyle(n)){return false}}for(const n of t.getAttributeKeys()){if(n==="class"||n==="style"){continue}if(!e.hasAttribute(n)){this.setAttribute(n,t.getAttribute(n),e)}}for(const n of t.getStyleNames()){if(!e.hasStyle(n)){this.setStyle(n,t.getStyle(n),e)}}for(const n of t.getClassNames()){if(!e.hasClass(n)){this.addClass(n,e)}}return true}_unwrapAttributeElement(t,e){if(!dd(t,e)){return false}if(t.name!==e.name||t.priority!==e.priority){return false}for(const n of t.getAttributeKeys()){if(n==="class"||n==="style"){continue}if(!e.hasAttribute(n)||e.getAttribute(n)!==t.getAttribute(n)){return false}}if(!e.hasClass(...t.getClassNames())){return false}for(const n of t.getStyleNames()){if(!e.hasStyle(n)||e.getStyle(n)!==t.getStyle(n)){return false}}for(const n of t.getAttributeKeys()){if(n==="class"||n==="style"){continue}this.removeAttribute(n,e)}this.removeClass(Array.from(t.getClassNames()),e);this.removeStyle(Array.from(t.getStyleNames()),e);return true}_breakAttributesRange(t,e=false){const n=t.start;const o=t.end;ld(t,this.document);if(t.isCollapsed){const n=this._breakAttributes(t.start,e);return new fl(n,n)}const i=this._breakAttributes(o,e);const r=i.parent.childCount;const s=this._breakAttributes(n,e);i.offset+=i.parent.childCount-r;return new fl(s,i)}_breakAttributes(t,e=false){const n=t.offset;const o=t.parent;if(t.parent.is("emptyElement")){throw new ss["a"]("view-writer-cannot-break-empty-element",this.document)}if(t.parent.is("uiElement")){throw new ss["a"]("view-writer-cannot-break-ui-element",this.document)}if(t.parent.is("rawElement")){throw new ss["a"]("view-writer-cannot-break-raw-element",this.document)}if(!e&&o.is("$text")&&cd(o.parent)){return t.clone()}if(cd(o)){return t.clone()}if(o.is("$text")){return this._breakAttributes(id(t),e)}const i=o.childCount;if(n==i){const t=new hl(o.parent,o.index+1);return this._breakAttributes(t,e)}else{if(n===0){const t=new hl(o.parent,o.index);return this._breakAttributes(t,e)}else{const t=o.index+1;const i=o._clone();o.parent._insertChild(t,i);this._addToClonedElementsGroup(i);const r=o.childCount-n;const s=o._removeChildren(n,r);i._appendChild(s);const a=new hl(o.parent,t);return this._breakAttributes(a,e)}}}_addToClonedElementsGroup(t){if(!t.root.is("rootElement")){return}if(t.is("element")){for(const e of t.getChildren()){this._addToClonedElementsGroup(e)}}const e=t.id;if(!e){return}let n=this._cloneGroups.get(e);if(!n){n=new Set;this._cloneGroups.set(e,n)}n.add(t);t._clonesGroup=n}_removeFromClonedElementsGroup(t){if(t.is("element")){for(const e of t.getChildren()){this._removeFromClonedElementsGroup(e)}}const e=t.id;if(!e){return}const n=this._cloneGroups.get(e);if(!n){return}n.delete(t)}}function td(t){return Array.from(t.getChildren()).some((t=>!t.is("uiElement")))}function ed(t){let e=t.parent;while(!cd(e)){if(!e){return undefined}e=e.parent}return e}function nd(t,e){if(t.prioritye.priority){return false}return t.getIdentity()n instanceof t))){throw new ss["a"]("view-writer-insert-invalid-node-type",e)}if(!n.is("$text")){sd(n.getChildren(),e)}}}const ad=[Vs,Cl,Hc,vl,Ql,Kl];function cd(t){return t&&(t.is("containerElement")||t.is("documentFragment"))}function ld(t,e){const n=ed(t.start);const o=ed(t.end);if(!n||!o||n!==o){throw new ss["a"]("view-writer-invalid-range-container",e)}}function dd(t,e){return t.id===null&&e.id===null}function ud(t){return Object.prototype.toString.call(t)=="[object Text]"}const hd=t=>t.createTextNode(" ");const fd=t=>{const e=t.createElement("br");e.dataset.ckeFiller=true;return e};const md=7;const gd=(()=>{let t="";for(let e=0;e0){n.push({index:o,type:"insert",values:t.slice(o,r)})}if(i-o>0){n.push({index:o+(r-o),type:"delete",howMany:i-o})}return n}function Dd(t,e){const{firstIndex:n,lastIndexOld:o,lastIndexNew:i}=t;if(n===-1){return Array(e).fill("equal")}let r=[];if(n>0){r=r.concat(Array(n).fill("equal"))}if(i-n>0){r=r.concat(Array(i-n).fill("insert"))}if(o-n>0){r=r.concat(Array(o-n).fill("delete"))}if(i200||i>200||o+i>300){return Ed.fastDiff(t,e,n,true)}let r,s;if(il?-1:1;if(d[o+h]){d[o]=d[o+h].slice(0)}if(!d[o]){d[o]=[]}d[o].push(i>l?r:s);let f=Math.max(i,l);let m=f-o;while(ml;m--){u[m]=h(m)}u[l]=h(l);f++}while(u[l]!==c);return d[l].slice(1)}Ed.fastDiff=Ad;function Md(t,e,n){t.insertBefore(n,t.childNodes[e]||null)}function Td(t){const e=t.parentNode;if(e){e.removeChild(t)}}function Sd(t){if(t){if(t.defaultView){return t instanceof t.defaultView.Document}else if(t.ownerDocument&&t.ownerDocument.defaultView){return t instanceof t.ownerDocument.defaultView.Node}}return false}class Id{constructor(t,e){this.domDocuments=new Set;this.domConverter=t;this.markedAttributes=new Set;this.markedChildren=new Set;this.markedTexts=new Set;this.selection=e;this.isFocused=false;this._inlineFiller=null;this._fakeSelectionContainer=null}markToSync(t,e){if(t==="text"){if(this.domConverter.mapViewToDom(e.parent)){this.markedTexts.add(e)}}else{if(!this.domConverter.mapViewToDom(e)){return}if(t==="attributes"){this.markedAttributes.add(e)}else if(t==="children"){this.markedChildren.add(e)}else{throw new ss["a"]("view-renderer-unknown-type",this)}}}render(){let t;for(const t of this.markedChildren){this._updateChildrenMappings(t)}if(this._inlineFiller&&!this._isSelectionInInlineFiller()){this._removeInlineFiller()}if(this._inlineFiller){t=this._getInlineFillerPosition()}else if(this._needsInlineFillerAtSelection()){t=this.selection.getFirstPosition();this.markedChildren.add(t.parent)}for(const t of this.markedAttributes){this._updateAttrs(t)}for(const e of this.markedChildren){this._updateChildren(e,{inlineFillerPosition:t})}for(const e of this.markedTexts){if(!this.markedChildren.has(e.parent)&&this.domConverter.mapViewToDom(e.parent)){this._updateText(e,{inlineFillerPosition:t})}}if(t){const e=this.domConverter.viewPositionToDom(t);const n=e.parent.ownerDocument;if(!pd(e.parent)){this._inlineFiller=Bd(n,e.parent,e.offset)}else{this._inlineFiller=e.parent}}else{this._inlineFiller=null}this._updateSelection();this._updateFocus();this.markedTexts.clear();this.markedAttributes.clear();this.markedChildren.clear()}_updateChildrenMappings(t){const e=this.domConverter.mapViewToDom(t);if(!e){return}const n=this.domConverter.mapViewToDom(t).childNodes;const o=Array.from(this.domConverter.viewChildrenToDom(t,e.ownerDocument,{withChildren:false}));const i=this._diffNodeLists(n,o);const r=this._findReplaceActions(i,n,o);if(r.indexOf("replace")!==-1){const e={equal:0,insert:0,delete:0};for(const i of r){if(i==="replace"){const i=e.equal+e.insert;const r=e.equal+e.delete;const s=t.getChild(i);if(s&&!(s.is("uiElement")||s.is("rawElement"))){this._updateElementMappings(s,n[r])}Td(o[i]);e.equal++}else{e[i]++}}}}_updateElementMappings(t,e){this.domConverter.unbindDomElement(e);this.domConverter.bindElements(e,t);this.markedChildren.add(t);this.markedAttributes.add(t)}_getInlineFillerPosition(){const t=this.selection.getFirstPosition();if(t.parent.is("$text")){return hl._createBefore(this.selection.getFirstPosition().parent)}else{return t}}_isSelectionInInlineFiller(){if(this.selection.rangeCount!=1||!this.selection.isCollapsed){return false}const t=this.selection.getFirstPosition();const e=this.domConverter.viewPositionToDom(t);if(e&&ud(e.parent)&&pd(e.parent)){return true}return false}_removeInlineFiller(){const t=this._inlineFiller;if(!pd(t)){throw new ss["a"]("view-renderer-filler-was-lost",this)}if(kd(t)){t.parentNode.removeChild(t)}else{t.data=t.data.substr(md)}this._inlineFiller=null}_needsInlineFillerAtSelection(){if(this.selection.rangeCount!=1||!this.selection.isCollapsed){return false}const t=this.selection.getFirstPosition();const e=t.parent;const n=t.offset;if(!this.domConverter.mapViewToDom(e.root)){return false}if(!e.is("element")){return false}if(!Nd(e)){return false}if(n===e.getFillerOffset()){return false}const o=t.nodeBefore;const i=t.nodeAfter;if(o instanceof Vs||i instanceof Vs){return false}return true}_updateText(t,e){const n=this.domConverter.findCorrespondingDomText(t);const o=this.domConverter.viewToDom(t,n.ownerDocument);const i=n.data;let r=o.data;const s=e.inlineFillerPosition;if(s&&s.parent==t.parent&&s.offset==t.index){r=gd+r}if(i!=r){const t=Ad(i,r);for(const e of t){if(e.type==="insert"){n.insertData(e.index,e.values.join(""))}else{n.deleteData(e.index,e.howMany)}}}}_updateAttrs(t){const e=this.domConverter.mapViewToDom(t);if(!e){return}const n=Array.from(e.attributes).map((t=>t.name));const o=t.getAttributeKeys();for(const n of o){e.setAttribute(n,t.getAttribute(n))}for(const o of n){if(!t.hasAttribute(o)){e.removeAttribute(o)}}}_updateChildren(t,e){const n=this.domConverter.mapViewToDom(t);if(!n){return}const o=e.inlineFillerPosition;const i=this.domConverter.mapViewToDom(t).childNodes;const r=Array.from(this.domConverter.viewChildrenToDom(t,n.ownerDocument,{bind:true,inlineFillerPosition:o}));if(o&&o.parent===t){Bd(n.ownerDocument,r,o.offset)}const s=this._diffNodeLists(i,r);let a=0;const c=new Set;for(const t of s){if(t==="delete"){c.add(i[a]);Td(i[a])}else if(t==="equal"){a++}}a=0;for(const t of s){if(t==="insert"){Md(n,a,r[a]);a++}else if(t==="equal"){this._markDescendantTextToSync(this.domConverter.domToView(r[a]));a++}}for(const t of c){if(!t.parentNode){this.domConverter.unbindDomElement(t)}}}_diffNodeLists(t,e){t=Od(t,this._fakeSelectionContainer);return Ed(t,e,zd.bind(null,this.domConverter))}_findReplaceActions(t,e,n){if(t.indexOf("insert")===-1||t.indexOf("delete")===-1){return t}let o=[];let i=[];let r=[];const s={equal:0,insert:0,delete:0};for(const a of t){if(a==="insert"){r.push(n[s.equal+s.insert])}else if(a==="delete"){i.push(e[s.equal+s.delete])}else{o=o.concat(Ed(i,r,Pd).map((t=>t==="equal"?"replace":t)));o.push("equal");i=[];r=[]}s[a]++}return o.concat(Ed(i,r,Pd).map((t=>t==="equal"?"replace":t)))}_markDescendantTextToSync(t){if(!t){return}if(t.is("$text")){this.markedTexts.add(t)}else if(t.is("element")){for(const e of t.getChildren()){this._markDescendantTextToSync(e)}}}_updateSelection(){if(this.selection.rangeCount===0){this._removeDomSelection();this._removeFakeSelection();return}const t=this.domConverter.mapViewToDom(this.selection.editableElement);if(!this.isFocused||!t){return}if(this.selection.isFake){this._updateFakeSelection(t)}else{this._removeFakeSelection();this._updateDomSelection(t)}}_updateFakeSelection(t){const e=t.ownerDocument;if(!this._fakeSelectionContainer){this._fakeSelectionContainer=Rd(e)}const n=this._fakeSelectionContainer;this.domConverter.bindFakeSelection(n,this.selection);if(!this._fakeSelectionNeedsUpdate(t)){return}if(!n.parentElement||n.parentElement!=t){t.appendChild(n)}n.textContent=this.selection.fakeSelectionLabel||" ";const o=e.getSelection();const i=e.createRange();o.removeAllRanges();i.selectNodeContents(n);o.addRange(i)}_updateDomSelection(t){const e=t.ownerDocument.defaultView.getSelection();if(!this._domSelectionNeedsUpdate(e)){return}const n=this.domConverter.viewPositionToDom(this.selection.anchor);const o=this.domConverter.viewPositionToDom(this.selection.focus);t.focus();e.collapse(n.parent,n.offset);e.extend(o.parent,o.offset);if(El.isGecko){Ld(o,e)}}_domSelectionNeedsUpdate(t){if(!this.domConverter.isDomSelectionCorrect(t)){return true}const e=t&&this.domConverter.domSelectionToView(t);if(e&&this.selection.isEqual(e)){return false}if(!this.selection.isCollapsed&&this.selection.isSimilar(e)){return false}return true}_fakeSelectionNeedsUpdate(t){const e=this._fakeSelectionContainer;const n=t.ownerDocument.getSelection();if(!e||e.parentElement!==t){return true}if(n.anchorNode!==e&&!e.contains(n.anchorNode)){return true}return e.textContent!==this.selection.fakeSelectionLabel}_removeDomSelection(){for(const t of this.domDocuments){const e=t.getSelection();if(e.rangeCount){const e=t.activeElement;const n=this.domConverter.mapDomToView(e);if(e&&n){t.getSelection().removeAllRanges()}}}}_removeFakeSelection(){const t=this._fakeSelectionContainer;if(t){t.remove()}}_updateFocus(){if(this.isFocused){const t=this.selection.editableElement;if(t){this.domConverter.focus(t)}}}}_s(Id,Jc);function Nd(t){if(t.getAttribute("contenteditable")=="false"){return false}const e=t.findAncestor((t=>t.hasAttribute("contenteditable")));return!e||e.getAttribute("contenteditable")=="true"}function Bd(t,e,n){const o=e instanceof Array?e:e.childNodes;const i=o[n];if(ud(i)){i.data=gd+i.data;return i}else{const i=t.createTextNode(gd);if(Array.isArray(e)){o.splice(n,0,i)}else{Md(e,n,i)}return i}}function Pd(t,e){return Sd(t)&&Sd(e)&&!ud(t)&&!ud(e)&&t.nodeType!==Node.COMMENT_NODE&&e.nodeType!==Node.COMMENT_NODE&&t.tagName.toLowerCase()===e.tagName.toLowerCase()}function zd(t,e,n){if(e===n){return true}else if(ud(e)&&ud(n)){return e.data===n.data}else if(t.isBlockFiller(e)&&t.isBlockFiller(n)){return true}return false}function Ld(t,e){const n=t.parent;if(n.nodeType!=Node.ELEMENT_NODE||t.offset!=n.childNodes.length-1){return}const o=n.childNodes[t.offset];if(o&&o.tagName=="BR"){e.addRange(e.getRangeAt(0))}}function Od(t,e){const n=Array.from(t);if(n.length==0||!e){return n}const o=n[n.length-1];if(o==e){n.pop()}return n}function Rd(t){const e=t.createElement("div");e.className="ck-fake-selection-container";Object.assign(e.style,{position:"fixed",top:0,left:"-9999px",width:"42px"});e.textContent=" ";return e}var jd={window:window,document:document};function Fd(t){let e=0;while(t.previousSibling){t=t.previousSibling;e++}return e}function Vd(t){const e=[];while(t&&t.nodeType!=Node.DOCUMENT_NODE){e.unshift(t);t=t.parentNode}return e}function Ud(t,e){const n=Vd(t);const o=Vd(e);let i=0;while(n[i]==o[i]&&n[i]){i++}return i===0?null:n[i-1]}const Hd=fd(document);class Gd{constructor(t,e={}){this.document=t;this.blockFillerMode=e.blockFillerMode||"br";this.preElements=["pre"];this.blockElements=["p","div","h1","h2","h3","h4","h5","h6","li","dd","dt","figcaption","td","th"];this._blockFiller=this.blockFillerMode=="br"?fd:hd;this._domToViewMapping=new WeakMap;this._viewToDomMapping=new WeakMap;this._fakeSelectionMapping=new WeakMap;this._rawContentElementMatcher=new Ks;this._encounteredRawContentDomNodes=new WeakSet}bindFakeSelection(t,e){this._fakeSelectionMapping.set(t,new pl(e))}fakeSelectionToView(t){return this._fakeSelectionMapping.get(t)}bindElements(t,e){this._domToViewMapping.set(t,e);this._viewToDomMapping.set(e,t)}unbindDomElement(t){const e=this._domToViewMapping.get(t);if(e){this._domToViewMapping.delete(t);this._viewToDomMapping.delete(e);for(const e of t.childNodes){this.unbindDomElement(e)}}}bindDocumentFragments(t,e){this._domToViewMapping.set(t,e);this._viewToDomMapping.set(e,t)}viewToDom(t,e,n={}){if(t.is("$text")){const n=this._processDataFromViewText(t);return e.createTextNode(n)}else{if(this.mapViewToDom(t)){return this.mapViewToDom(t)}let o;if(t.is("documentFragment")){o=e.createDocumentFragment();if(n.bind){this.bindDocumentFragments(o,t)}}else if(t.is("uiElement")){o=t.render(e);if(n.bind){this.bindElements(o,t)}return o}else{if(t.hasAttribute("xmlns")){o=e.createElementNS(t.getAttribute("xmlns"),t.name)}else{o=e.createElement(t.name)}if(t.is("rawElement")){t.render(o)}if(n.bind){this.bindElements(o,t)}for(const e of t.getAttributeKeys()){o.setAttribute(e,t.getAttribute(e))}}if(n.withChildren!==false){for(const i of this.viewChildrenToDom(t,e,n)){o.appendChild(i)}}return o}}*viewChildrenToDom(t,e,n={}){const o=t.getFillerOffset&&t.getFillerOffset();let i=0;for(const r of t.getChildren()){if(o===i){yield this._blockFiller(e)}yield this.viewToDom(r,e,n);i++}if(o===i){yield this._blockFiller(e)}}viewRangeToDom(t){const e=this.viewPositionToDom(t.start);const n=this.viewPositionToDom(t.end);const o=document.createRange();o.setStart(e.parent,e.offset);o.setEnd(n.parent,n.offset);return o}viewPositionToDom(t){const e=t.parent;if(e.is("$text")){const n=this.findCorrespondingDomText(e);if(!n){return null}let o=t.offset;if(pd(n)){o+=md}return{parent:n,offset:o}}else{let n,o,i;if(t.offset===0){n=this.mapViewToDom(e);if(!n){return null}i=n.childNodes[0]}else{const e=t.nodeBefore;o=e.is("$text")?this.findCorrespondingDomText(e):this.mapViewToDom(t.nodeBefore);if(!o){return null}n=o.parentNode;i=o.nextSibling}if(ud(i)&&pd(i)){return{parent:i,offset:md}}const r=o?Fd(o)+1:0;return{parent:n,offset:r}}}domToView(t,e={}){if(this.isBlockFiller(t,this.blockFillerMode)){return null}const n=this.getHostViewElement(t);if(n){return n}if(ud(t)){if(kd(t)){return null}else{const e=this._processDataFromDomText(t);return e===""?null:new Vs(this.document,e)}}else if(this.isComment(t)){return null}else{if(this.mapDomToView(t)){return this.mapDomToView(t)}let n;if(this.isDocumentFragment(t)){n=new Jl(this.document);if(e.bind){this.bindDocumentFragments(t,n)}}else{const o=e.keepOriginalCase?t.tagName:t.tagName.toLowerCase();n=new jc(this.document,o);if(e.bind){this.bindElements(t,n)}const i=t.attributes;for(let t=i.length-1;t>=0;t--){n._setAttribute(i[t].name,i[t].value)}if(e.withChildren!==false&&this._rawContentElementMatcher.match(n)){n._setCustomProperty("$rawContent",t.innerHTML);this._encounteredRawContentDomNodes.add(t);return n}}if(e.withChildren!==false){for(const o of this.domChildrenToView(t,e)){n._appendChild(o)}}return n}}*domChildrenToView(t,e={}){for(let n=0;n{const{scrollLeft:e,scrollTop:n}=t;o.push([e,n])}));e.focus();Wd(e,(t=>{const[e,n]=o.shift();t.scrollLeft=e;t.scrollTop=n}));jd.window.scrollTo(t,n)}}isElement(t){return t&&t.nodeType==Node.ELEMENT_NODE}isDocumentFragment(t){return t&&t.nodeType==Node.DOCUMENT_FRAGMENT_NODE}isComment(t){return t&&t.nodeType==Node.COMMENT_NODE}isBlockFiller(t){if(this.blockFillerMode=="br"){return t.isEqualNode(Hd)}if(t.tagName==="BR"&&Yd(t,this.blockElements)&&t.parentNode.childNodes.length===1){return true}return qd(t,this.blockElements)}isDomSelectionBackward(t){if(t.isCollapsed){return false}const e=document.createRange();e.setStart(t.anchorNode,t.anchorOffset);e.setEnd(t.focusNode,t.focusOffset);const n=e.collapsed;e.detach();return n}getHostViewElement(t){const e=Vd(t);e.pop();while(e.length){const t=e.pop();const n=this._domToViewMapping.get(t);if(n&&(n.is("uiElement")||n.is("rawElement"))){return n}}return null}isDomSelectionCorrect(t){return this._isDomSelectionPositionCorrect(t.anchorNode,t.anchorOffset)&&this._isDomSelectionPositionCorrect(t.focusNode,t.focusOffset)}registerRawContentMatcher(t){this._rawContentElementMatcher.add(t)}_isDomSelectionPositionCorrect(t,e){if(ud(t)&&pd(t)&&ethis.preElements.includes(t.name)))){return e}if(e.charAt(0)==" "){const n=this._getTouchingViewTextNode(t,false);const o=n&&this._nodeEndsWithSpace(n);if(o||!n){e=" "+e.substr(1)}}if(e.charAt(e.length-1)==" "){const n=this._getTouchingViewTextNode(t,true);if(e.charAt(e.length-2)==" "||!n||n.data.charAt(0)==" "){e=e.substr(0,e.length-1)+" "}}return e.replace(/ {2}/g,"  ")}_nodeEndsWithSpace(t){if(t.getAncestors().some((t=>this.preElements.includes(t.name)))){return false}const e=this._processDataFromViewText(t);return e.charAt(e.length-1)==" "}_processDataFromDomText(t){let e=t.data;if(Kd(t,this.preElements)){return bd(t)}e=e.replace(/[ \n\t\r]{1,}/g," ");const n=this._getTouchingInlineDomNode(t,false);const o=this._getTouchingInlineDomNode(t,true);const i=this._checkShouldLeftTrimDomText(t,n);const r=this._checkShouldRightTrimDomText(t,o);if(i){e=e.replace(/^ /,"")}if(r){e=e.replace(/ $/,"")}e=bd(new Text(e));e=e.replace(/ \u00A0/g," ");if(/( |\u00A0)\u00A0$/.test(e)||!o||o.data&&o.data.charAt(0)==" "){e=e.replace(/\u00A0$/," ")}if(i){e=e.replace(/^\u00A0/," ")}return e}_checkShouldLeftTrimDomText(t,e){if(!e){return true}if(Yr(e)){return true}if(this._encounteredRawContentDomNodes.has(t.previousSibling)){return false}return/[^\S\u00A0]/.test(e.data.charAt(e.data.length-1))}_checkShouldRightTrimDomText(t,e){if(e){return false}return!pd(t)}_getTouchingViewTextNode(t,e){const n=new ul({startPosition:e?hl._createAfter(t):hl._createBefore(t),direction:e?"forward":"backward"});for(const t of n){if(t.item.is("containerElement")){return null}else if(t.item.is("element","br")){return null}else if(t.item.is("$textProxy")){return t.item}}return null}_getTouchingInlineDomNode(t,e){if(!t.parentNode){return null}const n=e?"nextNode":"previousNode";const o=t.ownerDocument;const i=Vd(t)[0];const r=o.createTreeWalker(i,NodeFilter.SHOW_TEXT|NodeFilter.SHOW_ELEMENT,{acceptNode(t){if(ud(t)){return NodeFilter.FILTER_ACCEPT}if(t.tagName=="BR"){return NodeFilter.FILTER_ACCEPT}return NodeFilter.FILTER_SKIP}});r.currentNode=t;const s=r[n]();if(s!==null){const e=Ud(t,s);if(e&&!Kd(t,this.blockElements,e)&&!Kd(s,this.blockElements,e)){return s}}return null}}function Kd(t,e,n){let o=Vd(t);if(n){o=o.slice(o.indexOf(n)+1)}return o.some((t=>t.tagName&&e.includes(t.tagName.toLowerCase())))}function Wd(t,e){while(t&&t!=jd.document){e(t);t=t.parentNode}}function qd(t,e){const n=ud(t)&&t.data==" ";return n&&Yd(t,e)&&t.parentNode.childNodes.length===1}function Yd(t,e){const n=t.parentNode;return n&&n.tagName&&e.includes(n.tagName.toLowerCase())}function Qd(t){const e=Object.prototype.toString.apply(t);if(e=="[object Window]"){return true}if(e=="[object global]"){return true}return false}const $d=Wc({},ds,{listenTo(t,...e){if(Sd(t)||Qd(t)){const n=this._getProxyEmitter(t)||new Zd(t);n.attach(...e);t=n}ds.listenTo.call(this,t,...e)},stopListening(t,e,n){if(Sd(t)||Qd(t)){const e=this._getProxyEmitter(t);if(!e){return}t=e}ds.stopListening.call(this,t,e,n);if(t instanceof Zd){t.detach(e)}},_getProxyEmitter(t){return us(this,Xd(t))}});var Jd=$d;class Zd{constructor(t){hs(this,Xd(t));this._domNode=t}}Wc(Zd.prototype,ds,{attach(t,e,n={}){if(this._domListeners&&this._domListeners[t]){return}const o={capture:!!n.useCapture,passive:!!n.usePassive};const i=this._createDomListener(t,o);this._domNode.addEventListener(t,i,o);if(!this._domListeners){this._domListeners={}}this._domListeners[t]=i},detach(t){let e;if(this._domListeners[t]&&(!(e=this._events[t])||!e.callbacks.length)){this._domListeners[t].removeListener()}},_createDomListener(t,e){const n=e=>{this.fire(t,e)};n.removeListener=()=>{this._domNode.removeEventListener(t,n,e);delete this._domListeners[t]};return n}});function Xd(t){return t["data-ck-expando"]||(t["data-ck-expando"]=ns())}class tu{constructor(t){this.view=t;this.document=t.document;this.isEnabled=false}enable(){this.isEnabled=true}disable(){this.isEnabled=false}destroy(){this.disable();this.stopListening()}checkShouldIgnoreEventFromTarget(t){if(t&&t.nodeType===3){t=t.parentNode}if(!t||t.nodeType!==1){return false}return t.matches("[data-cke-ignore-events], [data-cke-ignore-events] *")}}_s(tu,Jd);var eu="__lodash_hash_undefined__";function nu(t){this.__data__.set(t,eu);return this}var ou=nu;function iu(t){return this.__data__.has(t)}var ru=iu;function su(t){var e=-1,n=t==null?0:t.length;this.__data__=new Ce;while(++ea)){return false}var l=r.get(t);if(l&&r.get(e)){return l==e}var d=-1,u=true,h=n&fu?new au:undefined;r.set(t,e);r.set(e,t);while(++d{this.listenTo(t,e,((t,e)=>{if(this.isEnabled&&!this.checkShouldIgnoreEventFromTarget(e.target)){this.onDomEvent(e)}}),{useCapture:this.useCapture})}))}fire(t,e,n){if(this.isEnabled){this.document.fire(t,new eh(this.view,e,n))}}}class oh extends nh{constructor(t){super(t);this.domEventType=["keydown","keyup"]}onDomEvent(t){this.fire(t.type,t,{keyCode:t.keyCode,altKey:t.altKey,ctrlKey:t.ctrlKey||t.metaKey,shiftKey:t.shiftKey,get keystroke(){return Ol(this)}})}}var ih=function(){return o["a"].Date.now()};var rh=ih;var sh=0/0;var ah=/^\s+|\s+$/g;var ch=/^[-+]0x[0-9a-f]+$/i;var lh=/^0b[01]+$/i;var dh=/^0o[0-7]+$/i;var uh=parseInt;function hh(t){if(typeof t=="number"){return t}if(Xs(t)){return sh}if(ct(t)){var e=typeof t.valueOf=="function"?t.valueOf():t;t=ct(e)?e+"":e}if(typeof t!="string"){return t===0?t:+t}t=t.replace(ah,"");var n=lh.test(t);return n||dh.test(t)?uh(t.slice(2),n?2:8):ch.test(t)?sh:+t}var fh=hh;var mh="Expected a function";var gh=Math.max,ph=Math.min;function kh(t,e,n){var o,i,r,s,a,c,l=0,d=false,u=false,h=true;if(typeof t!="function"){throw new TypeError(mh)}e=fh(e)||0;if(ct(n)){d=!!n.leading;u="maxWait"in n;r=u?gh(fh(n.maxWait)||0,e):r;h="trailing"in n?!!n.trailing:h}function f(e){var n=o,r=i;o=i=undefined;l=e;s=t.apply(r,n);return s}function m(t){l=t;a=setTimeout(k,e);return d?f(t):s}function g(t){var n=t-c,o=t-l,i=e-n;return u?ph(i,r-o):i}function p(t){var n=t-c,o=t-l;return c===undefined||n>=e||n<0||u&&o>=r}function k(){var t=rh();if(p(t)){return b(t)}a=setTimeout(k,g(t))}function b(t){a=undefined;if(h&&o){return f(t)}o=i=undefined;return s}function w(){if(a!==undefined){clearTimeout(a)}l=0;o=c=i=a=undefined}function C(){return a===undefined?s:b(rh())}function A(){var t=rh(),n=p(t);o=arguments;i=this;c=t;if(n){if(a===undefined){return m(c)}if(u){clearTimeout(a);a=setTimeout(k,e);return f(c)}}if(a===undefined){a=setTimeout(k,e)}return s}A.cancel=w;A.flush=C;return A}var bh=kh;class wh extends tu{constructor(t){super(t);this._fireSelectionChangeDoneDebounced=bh((t=>this.document.fire("selectionChangeDone",t)),200)}observe(){const t=this.document;t.on("keydown",((e,n)=>{const o=t.selection;if(o.isFake&&Fl(n.keyCode)&&this.isEnabled){n.preventDefault();this._handleSelectionMove(n.keyCode)}}),{priority:"lowest"})}destroy(){super.destroy();this._fireSelectionChangeDoneDebounced.cancel()}_handleSelectionMove(t){const e=this.document.selection;const n=new pl(e.getRanges(),{backward:e.isBackward,fake:false});if(t==Ll.arrowleft||t==Ll.arrowup){n.setTo(n.getFirstPosition())}if(t==Ll.arrowright||t==Ll.arrowdown){n.setTo(n.getLastPosition())}const o={oldSelection:e,newSelection:n,domSelection:null};this.document.fire("selectionChange",o);this._fireSelectionChangeDoneDebounced(o)}}class Ch extends tu{constructor(t){super(t);this.mutationObserver=t.getObserver(th);this.selection=this.document.selection;this.domConverter=t.domConverter;this._documents=new WeakSet;this._fireSelectionChangeDoneDebounced=bh((t=>this.document.fire("selectionChangeDone",t)),200);this._clearInfiniteLoopInterval=setInterval((()=>this._clearInfiniteLoop()),1e3);this._loopbackCounter=0}observe(t){const e=t.ownerDocument;if(this._documents.has(e)){return}this.listenTo(e,"selectionchange",((t,n)=>{this._handleSelectionChange(n,e)}));this._documents.add(e)}destroy(){super.destroy();clearInterval(this._clearInfiniteLoopInterval);this._fireSelectionChangeDoneDebounced.cancel()}_handleSelectionChange(t,e){if(!this.isEnabled){return}const n=e.defaultView.getSelection();if(this.checkShouldIgnoreEventFromTarget(n.anchorNode)){return}this.mutationObserver.flush();const o=this.domConverter.domSelectionToView(n);if(o.rangeCount==0){this.view.hasDomSelection=false;return}this.view.hasDomSelection=true;if(this.selection.isEqual(o)&&this.domConverter.isDomSelectionCorrect(n)){return}if(++this._loopbackCounter>60){return}if(this.selection.isSimilar(o)){this.view.forceRender()}else{const t={oldSelection:this.selection,newSelection:o,domSelection:n};this.document.fire("selectionChange",t);this._fireSelectionChangeDoneDebounced(t)}}_clearInfiniteLoop(){this._loopbackCounter=0}}class Ah extends nh{constructor(t){super(t);this.domEventType=["focus","blur"];this.useCapture=true;const e=this.document;e.on("focus",(()=>{e.isFocused=true;this._renderTimeoutId=setTimeout((()=>t.forceRender()),50)}));e.on("blur",((n,o)=>{const i=e.selection.editableElement;if(i===null||i===o.target){e.isFocused=false;t.forceRender()}}))}onDomEvent(t){this.fire(t.type,t)}destroy(){if(this._renderTimeoutId){clearTimeout(this._renderTimeoutId)}super.destroy()}}class _h extends nh{constructor(t){super(t);this.domEventType=["compositionstart","compositionupdate","compositionend"];const e=this.document;e.on("compositionstart",(()=>{e.isComposing=true}));e.on("compositionend",(()=>{e.isComposing=false}))}onDomEvent(t){this.fire(t.type,t)}}class vh extends nh{constructor(t){super(t);this.domEventType=["beforeinput"]}onDomEvent(t){this.fire(t.type,t)}}function yh(t){return Object.prototype.toString.apply(t)=="[object Range]"}function xh(t){const e=t.ownerDocument.defaultView.getComputedStyle(t);return{top:parseInt(e.borderTopWidth,10),right:parseInt(e.borderRightWidth,10),bottom:parseInt(e.borderBottomWidth,10),left:parseInt(e.borderLeftWidth,10)}}const Dh=["top","right","bottom","left","width","height"];class Eh{constructor(t){const e=yh(t);Object.defineProperty(this,"_source",{value:t._source||t,writable:true,enumerable:false});if(Yr(t)||e){if(e){const e=Eh.getDomRangeRects(t);Mh(this,Eh.getBoundingRect(e))}else{Mh(this,t.getBoundingClientRect())}}else if(Qd(t)){const{innerWidth:e,innerHeight:n}=t;Mh(this,{top:0,right:e,bottom:n,left:0,width:e,height:n})}else{Mh(this,t)}}clone(){return new Eh(this)}moveTo(t,e){this.top=e;this.right=t+this.width;this.bottom=e+this.height;this.left=t;return this}moveBy(t,e){this.top+=e;this.right+=t;this.left+=t;this.bottom+=e;return this}getIntersection(t){const e={top:Math.max(this.top,t.top),right:Math.min(this.right,t.right),bottom:Math.min(this.bottom,t.bottom),left:Math.max(this.left,t.left)};e.width=e.right-e.left;e.height=e.bottom-e.top;if(e.width<0||e.height<0){return null}else{return new Eh(e)}}getIntersectionArea(t){const e=this.getIntersection(t);if(e){return e.getArea()}else{return 0}}getArea(){return this.width*this.height}getVisible(){const t=this._source;let e=this.clone();if(!Th(t)){let n=t.parentNode||t.commonAncestorContainer;while(n&&!Th(n)){const t=new Eh(n);const o=e.getIntersection(t);if(o){if(o.getArea()Vh(t,o)));const s=Vh(t,o);Bh(o,s,e);if(o.parent!=o){i=o.frameElement;o=o.parent;if(!i){return}}else{o=null}}}function Nh(t){const e=Fh(t);Ph(e,(()=>new Eh(t)))}Object.assign(Sh,{scrollViewportToShowTarget:Ih,scrollAncestorsToShowTarget:Nh});function Bh(t,e,n){const o=e.clone().moveBy(0,n);const i=e.clone().moveBy(0,-n);const r=new Eh(t).excludeScrollbarsAndBorders();const s=[i,o];if(!s.every((t=>r.contains(t)))){let{scrollX:s,scrollY:a}=t;if(Lh(i,r)){a-=r.top-e.top+n}else if(zh(o,r)){a+=e.bottom-r.bottom+n}if(Oh(e,r)){s-=r.left-e.left+n}else if(Rh(e,r)){s+=e.right-r.right+n}t.scrollTo(s,a)}}function Ph(t,e){const n=jh(t);let o,i;while(t!=n.document.body){i=e();o=new Eh(t).excludeScrollbarsAndBorders();if(!o.contains(i)){if(Lh(i,o)){t.scrollTop-=o.top-i.top}else if(zh(i,o)){t.scrollTop+=i.bottom-o.bottom}if(Oh(i,o)){t.scrollLeft-=o.left-i.left}else if(Rh(i,o)){t.scrollLeft+=i.right-o.right}}t=t.parentNode}}function zh(t,e){return t.bottom>e.bottom}function Lh(t,e){return t.tope.right}function jh(t){if(yh(t)){return t.startContainer.ownerDocument.defaultView}else{return t.ownerDocument.defaultView}}function Fh(t){if(yh(t)){let e=t.commonAncestorContainer;if(ud(e)){e=e.parentNode}return e}else{return t.parentNode}}function Vh(t,e){const n=jh(t);const o=new Eh(t);if(n===e){return o}else{let t=n;while(t!=e){const e=t.frameElement;const n=new Eh(e).excludeScrollbarsAndBorders();o.moveBy(n.left,n.top);t=t.parent}}return o}class Uh{constructor(t){this.document=new bl(t);this.domConverter=new Gd(this.document);this.domRoots=new Map;this.set("isRenderingInProgress",false);this.set("hasDomSelection",false);this._renderer=new Id(this.domConverter,this.document.selection);this._renderer.bind("isFocused").to(this.document);this._initialDomRootAttributes=new WeakMap;this._observers=new Map;this._ongoingChange=false;this._postFixersInProgress=false;this._renderingDisabled=false;this._hasChangedSinceTheLastRendering=false;this._writer=new Xl(this.document);this.addObserver(th);this.addObserver(Ch);this.addObserver(Ah);this.addObserver(oh);this.addObserver(wh);this.addObserver(_h);if(El.isAndroid){this.addObserver(vh)}wd(this);Wl(this);this.on("render",(()=>{this._render();this.document.fire("layoutChanged");this._hasChangedSinceTheLastRendering=false}));this.listenTo(this.document.selection,"change",(()=>{this._hasChangedSinceTheLastRendering=true}))}attachDomRoot(t,e="main"){const n=this.document.getRoot(e);n._name=t.tagName.toLowerCase();const o={};for(const{name:e,value:i}of Array.from(t.attributes)){o[e]=i;if(e==="class"){this._writer.addClass(i.split(" "),n)}else{this._writer.setAttribute(e,i,n)}}this._initialDomRootAttributes.set(t,o);const i=()=>{this._writer.setAttribute("contenteditable",!n.isReadOnly,n);if(n.isReadOnly){this._writer.addClass("ck-read-only",n)}else{this._writer.removeClass("ck-read-only",n)}};i();this.domRoots.set(e,t);this.domConverter.bindElements(t,n);this._renderer.markToSync("children",n);this._renderer.markToSync("attributes",n);this._renderer.domDocuments.add(t.ownerDocument);n.on("change:children",((t,e)=>this._renderer.markToSync("children",e)));n.on("change:attributes",((t,e)=>this._renderer.markToSync("attributes",e)));n.on("change:text",((t,e)=>this._renderer.markToSync("text",e)));n.on("change:isReadOnly",(()=>this.change(i)));n.on("change",(()=>{this._hasChangedSinceTheLastRendering=true}));for(const n of this._observers.values()){n.observe(t,e)}}detachDomRoot(t){const e=this.domRoots.get(t);Array.from(e.attributes).forEach((({name:t})=>e.removeAttribute(t)));const n=this._initialDomRootAttributes.get(e);for(const t in n){e.setAttribute(t,n[t])}this.domRoots.delete(t);this.domConverter.unbindDomElement(e)}getDomRoot(t="main"){return this.domRoots.get(t)}addObserver(t){let e=this._observers.get(t);if(e){return e}e=new t(this);this._observers.set(t,e);for(const[t,n]of this.domRoots){e.observe(n,t)}e.enable();return e}getObserver(t){return this._observers.get(t)}disableObservers(){for(const t of this._observers.values()){t.disable()}}enableObservers(){for(const t of this._observers.values()){t.enable()}}scrollToTheSelection(){const t=this.document.selection.getFirstRange();if(t){Ih({target:this.domConverter.viewRangeToDom(t),viewportOffset:20})}}focus(){if(!this.document.isFocused){const t=this.document.selection.editableElement;if(t){this.domConverter.focus(t);this.forceRender()}else{}}}change(t){if(this.isRenderingInProgress||this._postFixersInProgress){throw new ss["a"]("cannot-change-view-tree",this)}try{if(this._ongoingChange){return t(this._writer)}this._ongoingChange=true;const e=t(this._writer);this._ongoingChange=false;if(!this._renderingDisabled&&this._hasChangedSinceTheLastRendering){this._postFixersInProgress=true;this.document._callPostFixers(this._writer);this._postFixersInProgress=false;this.fire("render")}return e}catch(t){ss["a"].rethrowUnexpectedError(t,this)}}forceRender(){this._hasChangedSinceTheLastRendering=true;this.change((()=>{}))}destroy(){for(const t of this._observers.values()){t.destroy()}this.document.destroy();this.stopListening()}createPositionAt(t,e){return hl._createAt(t,e)}createPositionAfter(t){return hl._createAfter(t)}createPositionBefore(t){return hl._createBefore(t)}createRange(t,e){return new fl(t,e)}createRangeOn(t){return fl._createOn(t)}createRangeIn(t){return fl._createIn(t)}createSelection(t,e,n){return new pl(t,e,n)}_disableRendering(t){this._renderingDisabled=t;if(t==false){this.change((()=>{}))}}_render(){this.isRenderingInProgress=true;this.disableObservers();this._renderer.render();this.enableObservers();this.isRenderingInProgress=false}}_s(Uh,Jc);class Hh{constructor(t){this.parent=null;this._attrs=Gs(t)}get index(){let t;if(!this.parent){return null}if((t=this.parent.getChildIndex(this))===null){throw new ss["a"]("model-node-not-found-in-parent",this)}return t}get startOffset(){let t;if(!this.parent){return null}if((t=this.parent.getChildStartOffset(this))===null){throw new ss["a"]("model-node-not-found-in-parent",this)}return t}get offsetSize(){return 1}get endOffset(){if(!this.parent){return null}return this.startOffset+this.offsetSize}get nextSibling(){const t=this.index;return t!==null&&this.parent.getChild(t+1)||null}get previousSibling(){const t=this.index;return t!==null&&this.parent.getChild(t-1)||null}get root(){let t=this;while(t.parent){t=t.parent}return t}isAttached(){return this.root.is("rootElement")}getPath(){const t=[];let e=this;while(e.parent){t.unshift(e.startOffset);e=e.parent}return t}getAncestors(t={includeSelf:false,parentFirst:false}){const e=[];let n=t.includeSelf?this:this.parent;while(n){e[t.parentFirst?"push":"unshift"](n);n=n.parent}return e}getCommonAncestor(t,e={}){const n=this.getAncestors(e);const o=t.getAncestors(e);let i=0;while(n[i]==o[i]&&n[i]){i++}return i===0?null:n[i-1]}isBefore(t){if(this==t){return false}if(this.root!==t.root){return false}const e=this.getPath();const n=t.getPath();const o=Ls(e,n);switch(o){case"prefix":return true;case"extension":return false;default:return e[o]{t[e[0]]=e[1];return t}),{})}return t}is(t){return t==="node"||t==="model:node"}_clone(){return new Hh(this._attrs)}_remove(){this.parent._removeChildren(this.index)}_setAttribute(t,e){this._attrs.set(t,e)}_setAttributesTo(t){this._attrs=Gs(t)}_removeAttribute(t){return this._attrs.delete(t)}_clearAttributes(){this._attrs.clear()}}class Gh extends Hh{constructor(t,e){super(e);this._data=t||""}get offsetSize(){return this.data.length}get data(){return this._data}is(t){return t==="$text"||t==="model:$text"||t==="text"||t==="model:text"||t==="node"||t==="model:node"}toJSON(){const t=super.toJSON();t.data=this.data;return t}_clone(){return new Gh(this.data,this.getAttributes())}static fromJSON(t){return new Gh(t.data,t.attributes)}}class Kh{constructor(t,e,n){this.textNode=t;if(e<0||e>t.offsetSize){throw new ss["a"]("model-textproxy-wrong-offsetintext",this)}if(n<0||e+n>t.offsetSize){throw new ss["a"]("model-textproxy-wrong-length",this)}this.data=t.data.substring(e,e+n);this.offsetInText=e}get startOffset(){return this.textNode.startOffset!==null?this.textNode.startOffset+this.offsetInText:null}get offsetSize(){return this.data.length}get endOffset(){return this.startOffset!==null?this.startOffset+this.offsetSize:null}get isPartial(){return this.offsetSize!==this.textNode.offsetSize}get parent(){return this.textNode.parent}get root(){return this.textNode.root}is(t){return t==="$textProxy"||t==="model:$textProxy"||t==="textProxy"||t==="model:textProxy"}getPath(){const t=this.textNode.getPath();if(t.length>0){t[t.length-1]+=this.offsetInText}return t}getAncestors(t={includeSelf:false,parentFirst:false}){const e=[];let n=t.includeSelf?this:this.parent;while(n){e[t.parentFirst?"push":"unshift"](n);n=n.parent}return e}hasAttribute(t){return this.textNode.hasAttribute(t)}getAttribute(t){return this.textNode.getAttribute(t)}getAttributes(){return this.textNode.getAttributes()}getAttributeKeys(){return this.textNode.getAttributeKeys()}}class Wh{constructor(t){this._nodes=[];if(t){this._insertNodes(0,t)}}[Symbol.iterator](){return this._nodes[Symbol.iterator]()}get length(){return this._nodes.length}get maxOffset(){return this._nodes.reduce(((t,e)=>t+e.offsetSize),0)}getNode(t){return this._nodes[t]||null}getNodeIndex(t){const e=this._nodes.indexOf(t);return e==-1?null:e}getNodeStartOffset(t){const e=this.getNodeIndex(t);return e===null?null:this._nodes.slice(0,e).reduce(((t,e)=>t+e.offsetSize),0)}indexToOffset(t){if(t==this._nodes.length){return this.maxOffset}const e=this._nodes[t];if(!e){throw new ss["a"]("model-nodelist-index-out-of-bounds",this)}return this.getNodeStartOffset(e)}offsetToIndex(t){let e=0;for(const n of this._nodes){if(t>=e&&tt.toJSON()))}}class qh extends Hh{constructor(t,e,n){super(e);this.name=t;this._children=new Wh;if(n){this._insertChild(0,n)}}get childCount(){return this._children.length}get maxOffset(){return this._children.maxOffset}get isEmpty(){return this.childCount===0}is(t,e=null){if(!e){return t==="element"||t==="model:element"||t==="node"||t==="model:node"}return e===this.name&&(t==="element"||t==="model:element")}getChild(t){return this._children.getNode(t)}getChildren(){return this._children[Symbol.iterator]()}getChildIndex(t){return this._children.getNodeIndex(t)}getChildStartOffset(t){return this._children.getNodeStartOffset(t)}offsetToIndex(t){return this._children.offsetToIndex(t)}getNodeByPath(t){let e=this;for(const n of t){e=e.getChild(e.offsetToIndex(n))}return e}findAncestor(t,e={includeSelf:false}){let n=e.includeSelf?this:this.parent;while(n){if(n.name===t){return n}n=n.parent}return null}toJSON(){const t=super.toJSON();t.name=this.name;if(this._children.length>0){t.children=[];for(const e of this._children){t.children.push(e.toJSON())}}return t}_clone(t=false){const e=t?Array.from(this._children).map((t=>t._clone(true))):null;return new qh(this.name,this.getAttributes(),e)}_appendChild(t){this._insertChild(this.childCount,t)}_insertChild(t,e){const n=Yh(e);for(const t of n){if(t.parent!==null){t._remove()}t.parent=this}this._children._insertNodes(t,n)}_removeChildren(t,e=1){const n=this._children._removeNodes(t,e);for(const t of n){t.parent=null}return n}static fromJSON(t){let e=null;if(t.children){e=[];for(const n of t.children){if(n.name){e.push(qh.fromJSON(n))}else{e.push(Gh.fromJSON(n))}}}return new qh(t.name,t.attributes,e)}}function Yh(t){if(typeof t=="string"){return[new Gh(t)]}if(!As(t)){t=[t]}return Array.from(t).map((t=>{if(typeof t=="string"){return new Gh(t)}if(t instanceof Kh){return new Gh(t.data,t.getAttributes())}return t}))}class Qh{constructor(t={}){if(!t.boundaries&&!t.startPosition){throw new ss["a"]("model-tree-walker-no-start-position",null)}const e=t.direction||"forward";if(e!="forward"&&e!="backward"){throw new ss["a"]("model-tree-walker-unknown-direction",t,{direction:e})}this.direction=e;this.boundaries=t.boundaries||null;if(t.startPosition){this.position=t.startPosition.clone()}else{this.position=Jh._createAt(this.boundaries[this.direction=="backward"?"end":"start"])}this.position.stickiness="toNone";this.singleCharacters=!!t.singleCharacters;this.shallow=!!t.shallow;this.ignoreElementEnd=!!t.ignoreElementEnd;this._boundaryStartParent=this.boundaries?this.boundaries.start.parent:null;this._boundaryEndParent=this.boundaries?this.boundaries.end.parent:null;this._visitedParent=this.position.parent}[Symbol.iterator](){return this}skip(t){let e,n,o,i;do{o=this.position;i=this._visitedParent;({done:e,value:n}=this.next())}while(!e&&t(n));if(!e){this.position=o;this._visitedParent=i}}next(){if(this.direction=="forward"){return this._next()}else{return this._previous()}}_next(){const t=this.position;const e=this.position.clone();const n=this._visitedParent;if(n.parent===null&&e.offset===n.maxOffset){return{done:true}}if(n===this._boundaryEndParent&&e.offset==this.boundaries.end.offset){return{done:true}}const o=e.parent;const i=Zh(e,o);const r=i?i:Xh(e,o,i);if(r instanceof qh){if(!this.shallow){e.path.push(0);this._visitedParent=r}else{e.offset++}this.position=e;return $h("elementStart",r,t,e,1)}else if(r instanceof Gh){let o;if(this.singleCharacters){o=1}else{let t=r.endOffset;if(this._boundaryEndParent==n&&this.boundaries.end.offsett){t=this.boundaries.start.offset}o=e.offset-t}const i=e.offset-r.startOffset;const s=new Kh(r,i-o,o);e.offset-=o;this.position=e;return $h("text",s,t,e,o)}else{e.path.pop();this.position=e;this._visitedParent=n.parent;return $h("elementStart",n,t,e,1)}}}function $h(t,e,n,o,i){return{done:false,value:{type:t,item:e,previousPosition:n,nextPosition:o,length:i}}}class Jh{constructor(t,e,n="toNone"){if(!t.is("element")&&!t.is("documentFragment")){throw new ss["a"]("model-position-root-invalid",t)}if(!(e instanceof Array)||e.length===0){throw new ss["a"]("model-position-path-incorrect-format",t,{path:e})}if(t.is("rootElement")){e=e.slice()}else{e=[...t.getPath(),...e];t=t.root}this.root=t;this.path=e;this.stickiness=n}get offset(){return this.path[this.path.length-1]}set offset(t){this.path[this.path.length-1]=t}get parent(){let t=this.root;for(let e=0;en.path.length){if(e.offset!==i.maxOffset){return false}e.path=e.path.slice(0,-1);i=i.parent;e.offset++}else{if(n.offset!==0){return false}n.path=n.path.slice(0,-1)}}}is(t){return t==="position"||t==="model:position"}hasSameParentAs(t){if(this.root!==t.root){return false}const e=this.getParentPath();const n=t.getParentPath();return Ls(e,n)=="same"}getTransformedByOperation(t){let e;switch(t.type){case"insert":e=this._getTransformedByInsertOperation(t);break;case"move":case"remove":case"reinsert":e=this._getTransformedByMoveOperation(t);break;case"split":e=this._getTransformedBySplitOperation(t);break;case"merge":e=this._getTransformedByMergeOperation(t);break;default:e=Jh._createAt(this);break}return e}_getTransformedByInsertOperation(t){return this._getTransformedByInsertion(t.position,t.howMany)}_getTransformedByMoveOperation(t){return this._getTransformedByMove(t.sourcePosition,t.targetPosition,t.howMany)}_getTransformedBySplitOperation(t){const e=t.movedRange;const n=e.containsPosition(this)||e.start.isEqual(this)&&this.stickiness=="toNext";if(n){return this._getCombined(t.splitPosition,t.moveTargetPosition)}else{if(t.graveyardPosition){return this._getTransformedByMove(t.graveyardPosition,t.insertionPosition,1)}else{return this._getTransformedByInsertion(t.insertionPosition,1)}}}_getTransformedByMergeOperation(t){const e=t.movedRange;const n=e.containsPosition(this)||e.start.isEqual(this);let o;if(n){o=this._getCombined(t.sourcePosition,t.targetPosition);if(t.sourcePosition.isBefore(t.targetPosition)){o=o._getTransformedByDeletion(t.deletionPosition,1)}}else if(this.isEqual(t.deletionPosition)){o=Jh._createAt(t.deletionPosition)}else{o=this._getTransformedByMove(t.deletionPosition,t.graveyardPosition,1)}return o}_getTransformedByDeletion(t,e){const n=Jh._createAt(this);if(this.root!=t.root){return n}if(Ls(t.getParentPath(),this.getParentPath())=="same"){if(t.offsetthis.offset){return null}else{n.offset-=e}}}else if(Ls(t.getParentPath(),this.getParentPath())=="prefix"){const o=t.path.length-1;if(t.offset<=this.path[o]){if(t.offset+e>this.path[o]){return null}else{n.path[o]-=e}}}return n}_getTransformedByInsertion(t,e){const n=Jh._createAt(this);if(this.root!=t.root){return n}if(Ls(t.getParentPath(),this.getParentPath())=="same"){if(t.offsete+1){const e=o.maxOffset-n.offset;if(e!==0){t.push(new ef(n,n.getShiftedBy(e)))}n.path=n.path.slice(0,-1);n.offset++;o=o.parent}while(n.path.length<=this.end.path.length){const e=this.end.path[n.path.length-1];const o=e-n.offset;if(o!==0){t.push(new ef(n,n.getShiftedBy(o)))}n.offset=e;n.path.push(0)}return t}getWalker(t={}){t.boundaries=this;return new Qh(t)}*getItems(t={}){t.boundaries=this;t.ignoreElementEnd=true;const e=new Qh(t);for(const t of e){yield t.item}}*getPositions(t={}){t.boundaries=this;const e=new Qh(t);yield e.position;for(const t of e){yield t.nextPosition}}getTransformedByOperation(t){switch(t.type){case"insert":return this._getTransformedByInsertOperation(t);case"move":case"remove":case"reinsert":return this._getTransformedByMoveOperation(t);case"split":return[this._getTransformedBySplitOperation(t)];case"merge":return[this._getTransformedByMergeOperation(t)]}return[new ef(this.start,this.end)]}getTransformedByOperations(t){const e=[new ef(this.start,this.end)];for(const n of t){for(let t=0;t0?new this(n,o):new this(o,n)}static _createIn(t){return new this(Jh._createAt(t,0),Jh._createAt(t,t.maxOffset))}static _createOn(t){return this._createFromPositionAndShift(Jh._createBefore(t),t.offsetSize)}static _createFromRanges(t){if(t.length===0){throw new ss["a"]("range-create-from-ranges-empty-array",null)}else if(t.length==1){return t[0].clone()}const e=t[0];t.sort(((t,e)=>t.start.isAfter(e.start)?1:-1));const n=t.indexOf(e);const o=new this(e.start,e.end);if(n>0){for(let e=n-1;true;e++){if(t[e].end.isEqual(o.start)){o.start=Jh._createAt(t[e].start)}else{break}}}for(let e=n+1;e{if(e.viewPosition){return}const n=this._modelToViewMapping.get(e.modelPosition.parent);e.viewPosition=this.findPositionIn(n,e.modelPosition.offset)}),{priority:"low"});this.on("viewToModelPosition",((t,e)=>{if(e.modelPosition){return}const n=this.findMappedViewAncestor(e.viewPosition);const o=this._viewToModelMapping.get(n);const i=this._toModelOffset(e.viewPosition.parent,e.viewPosition.offset,n);e.modelPosition=Jh._createAt(o,i)}),{priority:"low"})}bindElements(t,e){this._modelToViewMapping.set(t,e);this._viewToModelMapping.set(e,t)}unbindViewElement(t){const e=this.toModelElement(t);this._viewToModelMapping.delete(t);if(this._elementToMarkerNames.has(t)){for(const e of this._elementToMarkerNames.get(t)){this._unboundMarkerNames.add(e)}}if(this._modelToViewMapping.get(e)==t){this._modelToViewMapping.delete(e)}}unbindModelElement(t){const e=this.toViewElement(t);this._modelToViewMapping.delete(t);if(this._viewToModelMapping.get(e)==t){this._viewToModelMapping.delete(e)}}bindElementToMarker(t,e){const n=this._markerNameToElements.get(e)||new Set;n.add(t);const o=this._elementToMarkerNames.get(t)||new Set;o.add(e);this._markerNameToElements.set(e,n);this._elementToMarkerNames.set(t,o)}unbindElementFromMarkerName(t,e){const n=this._markerNameToElements.get(e);if(n){n.delete(t);if(n.size==0){this._markerNameToElements.delete(e)}}const o=this._elementToMarkerNames.get(t);if(o){o.delete(e);if(o.size==0){this._elementToMarkerNames.delete(t)}}}flushUnboundMarkerNames(){const t=Array.from(this._unboundMarkerNames);this._unboundMarkerNames.clear();return t}clearBindings(){this._modelToViewMapping=new WeakMap;this._viewToModelMapping=new WeakMap;this._markerNameToElements=new Map;this._elementToMarkerNames=new Map;this._unboundMarkerNames=new Set}toModelElement(t){return this._viewToModelMapping.get(t)}toViewElement(t){return this._modelToViewMapping.get(t)}toModelRange(t){return new ef(this.toModelPosition(t.start),this.toModelPosition(t.end))}toViewRange(t){return new fl(this.toViewPosition(t.start),this.toViewPosition(t.end))}toModelPosition(t){const e={viewPosition:t,mapper:this};this.fire("viewToModelPosition",e);return e.modelPosition}toViewPosition(t,e={isPhantom:false}){const n={modelPosition:t,mapper:this,isPhantom:e.isPhantom};this.fire("modelToViewPosition",n);return n.viewPosition}markerNameToElements(t){const e=this._markerNameToElements.get(t);if(!e){return null}const n=new Set;for(const t of e){if(t.is("attributeElement")){for(const e of t.getElementsWithSameId()){n.add(e)}}else{n.add(t)}}return n}registerViewToModelLength(t,e){this._viewToModelLengthCallbacks.set(t,e)}findMappedViewAncestor(t){let e=t.parent;while(!this._viewToModelMapping.has(e)){e=e.parent}return e}_toModelOffset(t,e,n){if(n!=t){const o=this._toModelOffset(t.parent,t.index,n);const i=this._toModelOffset(t,e,t);return o+i}if(t.is("$text")){return e}let o=0;for(let n=0;n1?e[0]+":"+e[1]:e[0]}class sf{constructor(t){this.conversionApi=Object.assign({dispatcher:this},t);this._reconversionEventsMapping=new Map}convertChanges(t,e,n){for(const e of t.getMarkersToRemove()){this.convertMarkerRemove(e.name,e.range,n)}const o=this._mapChangesWithAutomaticReconversion(t);for(const t of o){if(t.type==="insert"){this.convertInsert(ef._createFromPositionAndShift(t.position,t.length),n)}else if(t.type==="remove"){this.convertRemove(t.position,t.length,t.name,n)}else if(t.type==="reconvert"){this.reconvertElement(t.element,n)}else{this.convertAttribute(t.range,t.attributeKey,t.attributeOldValue,t.attributeNewValue,n)}}for(const t of this.conversionApi.mapper.flushUnboundMarkerNames()){const o=e.get(t).getRange();this.convertMarkerRemove(t,o,n);this.convertMarkerAdd(t,o,n)}for(const e of t.getMarkersToAdd()){this.convertMarkerAdd(e.name,e.range,n)}}convertInsert(t,e){this.conversionApi.writer=e;this.conversionApi.consumable=this._createInsertConsumable(t);for(const e of Array.from(t).map(lf)){this._convertInsertWithAttributes(e)}this._clearConversionApi()}convertRemove(t,e,n,o){this.conversionApi.writer=o;this.fire("remove:"+n,{position:t,length:e},this.conversionApi);this._clearConversionApi()}convertAttribute(t,e,n,o,i){this.conversionApi.writer=i;this.conversionApi.consumable=this._createConsumableForRange(t,`attribute:${e}`);for(const i of t){const t=i.item;const r=ef._createFromPositionAndShift(i.previousPosition,i.length);const s={item:t,range:r,attributeKey:e,attributeOldValue:n,attributeNewValue:o};this._testAndFire(`attribute:${e}`,s)}this._clearConversionApi()}reconvertElement(t,e){const n=ef._createOn(t);this.conversionApi.writer=e;this.conversionApi.consumable=this._createInsertConsumable(n);const o=this.conversionApi.mapper;const i=o.toViewElement(t);e.remove(i);this._convertInsertWithAttributes({item:t,range:n});const r=o.toViewElement(t);for(const n of ef._createIn(t)){const{item:t}=n;const i=df(t,o);if(i){if(i.root!==r.root){e.move(e.createRangeOn(i),o.toViewPosition(Jh._createBefore(t)))}}else{this._convertInsertWithAttributes(lf(n))}}o.unbindViewElement(i);this._clearConversionApi()}convertSelection(t,e,n){const o=Array.from(e.getMarkersAtPosition(t.getFirstPosition()));this.conversionApi.writer=n;this.conversionApi.consumable=this._createSelectionConsumable(t,o);this.fire("selection",{selection:t},this.conversionApi);if(!t.isCollapsed){return}for(const e of o){const n=e.getRange();if(!af(t.getFirstPosition(),e,this.conversionApi.mapper)){continue}const o={item:t,markerName:e.name,markerRange:n};if(this.conversionApi.consumable.test(t,"addMarker:"+e.name)){this.fire("addMarker:"+e.name,o,this.conversionApi)}}for(const e of t.getAttributeKeys()){const n={item:t,range:t.getFirstRange(),attributeKey:e,attributeOldValue:null,attributeNewValue:t.getAttribute(e)};if(this.conversionApi.consumable.test(t,"attribute:"+n.attributeKey)){this.fire("attribute:"+n.attributeKey+":$text",n,this.conversionApi)}}this._clearConversionApi()}convertMarkerAdd(t,e,n){if(!e.root.document||e.root.rootName=="$graveyard"){return}this.conversionApi.writer=n;const o="addMarker:"+t;const i=new of;i.add(e,o);this.conversionApi.consumable=i;this.fire(o,{markerName:t,markerRange:e},this.conversionApi);if(!i.test(e,o)){return}this.conversionApi.consumable=this._createConsumableForRange(e,o);for(const n of e.getItems()){if(!this.conversionApi.consumable.test(n,o)){continue}const i={item:n,range:ef._createOn(n),markerName:t,markerRange:e};this.fire(o,i,this.conversionApi)}this._clearConversionApi()}convertMarkerRemove(t,e,n){if(!e.root.document||e.root.rootName=="$graveyard"){return}this.conversionApi.writer=n;this.fire("removeMarker:"+t,{markerName:t,markerRange:e},this.conversionApi);this._clearConversionApi()}_mapReconversionTriggerEvent(t,e){this._reconversionEventsMapping.set(e,t)}_createInsertConsumable(t){const e=new of;for(const n of t){const t=n.item;e.add(t,"insert");for(const n of t.getAttributeKeys()){e.add(t,"attribute:"+n)}}return e}_createConsumableForRange(t,e){const n=new of;for(const o of t.getItems()){n.add(o,e)}return n}_createSelectionConsumable(t,e){const n=new of;n.add(t,"selection");for(const o of e){n.add(t,"addMarker:"+o.name)}for(const e of t.getAttributeKeys()){n.add(t,"attribute:"+e)}return n}_testAndFire(t,e){if(!this.conversionApi.consumable.test(e.item,t)){return}this.fire(cf(t,e),e,this.conversionApi)}_clearConversionApi(){delete this.conversionApi.writer;delete this.conversionApi.consumable}_convertInsertWithAttributes(t){this._testAndFire("insert",t);for(const e of t.item.getAttributeKeys()){t.attributeKey=e;t.attributeOldValue=null;t.attributeNewValue=t.item.getAttribute(e);this._testAndFire(`attribute:${e}`,t)}}_mapChangesWithAutomaticReconversion(t){const e=new Set;const n=[];for(const o of t.getChanges()){const t=o.position||o.range.start;const i=t.parent;const r=Zh(t,i);if(r){n.push(o);continue}const s=o.type==="attribute"?Xh(t,i,null):i;if(s.is("$text")){n.push(o);continue}let a;if(o.type==="attribute"){a=`attribute:${o.attributeKey}:${s.name}`}else{a=`${o.type}:${o.name}`}if(this._isReconvertTriggerEvent(a,s.name)){if(e.has(s)){continue}e.add(s);n.push({type:"reconvert",element:s})}else{n.push(o)}}return n}_isReconvertTriggerEvent(t,e){return this._reconversionEventsMapping.get(t)===e}}_s(sf,ds);function af(t,e,n){const o=e.getRange();const i=Array.from(t.getAncestors());i.shift();i.reverse();const r=i.some((t=>{if(o.containsItem(t)){const e=n.toViewElement(t);return!!e.getCustomProperty("addHighlight")}}));return!r}function cf(t,e){const n=e.item.name||"$text";return`${t}:${n}`}function lf(t){const e=t.item;const n=ef._createFromPositionAndShift(t.previousPosition,t.length);return{item:e,range:n}}function df(t,e){if(t.is("textProxy")){const n=e.toViewPosition(Jh._createBefore(t));const o=n.parent;return o.is("$text")?o:null}return e.toViewElement(t)}class uf{constructor(t,e,n){this._lastRangeBackward=false;this._ranges=[];this._attrs=new Map;if(t){this.setTo(t,e,n)}}get anchor(){if(this._ranges.length>0){const t=this._ranges[this._ranges.length-1];return this._lastRangeBackward?t.end:t.start}return null}get focus(){if(this._ranges.length>0){const t=this._ranges[this._ranges.length-1];return this._lastRangeBackward?t.start:t.end}return null}get isCollapsed(){const t=this._ranges.length;if(t===1){return this._ranges[0].isCollapsed}else{return false}}get rangeCount(){return this._ranges.length}get isBackward(){return!this.isCollapsed&&this._lastRangeBackward}isEqual(t){if(this.rangeCount!=t.rangeCount){return false}else if(this.rangeCount===0){return true}if(!this.anchor.isEqual(t.anchor)||!this.focus.isEqual(t.focus)){return false}for(const e of this._ranges){let n=false;for(const o of t._ranges){if(e.isEqual(o)){n=true;break}}if(!n){return false}}return true}*getRanges(){for(const t of this._ranges){yield new ef(t.start,t.end)}}getFirstRange(){let t=null;for(const e of this._ranges){if(!t||e.start.isBefore(t.start)){t=e}}return t?new ef(t.start,t.end):null}getLastRange(){let t=null;for(const e of this._ranges){if(!t||e.end.isAfter(t.end)){t=e}}return t?new ef(t.start,t.end):null}getFirstPosition(){const t=this.getFirstRange();return t?t.start.clone():null}getLastPosition(){const t=this.getLastRange();return t?t.end.clone():null}setTo(t,e,n){if(t===null){this._setRanges([])}else if(t instanceof uf){this._setRanges(t.getRanges(),t.isBackward)}else if(t&&typeof t.getRanges=="function"){this._setRanges(t.getRanges(),t.isBackward)}else if(t instanceof ef){this._setRanges([t],!!e&&!!e.backward)}else if(t instanceof Jh){this._setRanges([new ef(t)])}else if(t instanceof Hh){const o=!!n&&!!n.backward;let i;if(e=="in"){i=ef._createIn(t)}else if(e=="on"){i=ef._createOn(t)}else if(e!==undefined){i=new ef(Jh._createAt(t,e))}else{throw new ss["a"]("model-selection-setto-required-second-parameter",[this,t])}this._setRanges([i],o)}else if(As(t)){this._setRanges(t,e&&!!e.backward)}else{throw new ss["a"]("model-selection-setto-not-selectable",[this,t])}}_setRanges(t,e=false){t=Array.from(t);const n=t.some((e=>{if(!(e instanceof ef)){throw new ss["a"]("model-selection-set-ranges-not-range",[this,t])}return this._ranges.every((t=>!t.isEqual(e)))}));if(t.length===this._ranges.length&&!n){return}this._removeAllRanges();for(const e of t){this._pushRange(e)}this._lastRangeBackward=!!e;this.fire("change:range",{directChange:true})}setFocus(t,e){if(this.anchor===null){throw new ss["a"]("model-selection-setfocus-no-ranges",[this,t])}const n=Jh._createAt(t,e);if(n.compareWith(this.focus)=="same"){return}const o=this.anchor;if(this._ranges.length){this._popRange()}if(n.compareWith(o)=="before"){this._pushRange(new ef(n,o));this._lastRangeBackward=true}else{this._pushRange(new ef(o,n));this._lastRangeBackward=false}this.fire("change:range",{directChange:true})}getAttribute(t){return this._attrs.get(t)}getAttributes(){return this._attrs.entries()}getAttributeKeys(){return this._attrs.keys()}hasAttribute(t){return this._attrs.has(t)}removeAttribute(t){if(this.hasAttribute(t)){this._attrs.delete(t);this.fire("change:attribute",{attributeKeys:[t],directChange:true})}}setAttribute(t,e){if(this.getAttribute(t)!==e){this._attrs.set(t,e);this.fire("change:attribute",{attributeKeys:[t],directChange:true})}}getSelectedElement(){if(this.rangeCount!==1){return null}return this.getFirstRange().getContainedElement()}is(t){return t==="selection"||t==="model:selection"}*getSelectedBlocks(){const t=new WeakSet;for(const e of this.getRanges()){const n=mf(e.start,t);if(n&&gf(n,e)){yield n}for(const n of e.getWalker()){const o=n.item;if(n.type=="elementEnd"&&ff(o,t,e)){yield o}}const o=mf(e.end,t);if(o&&!e.end.isTouching(Jh._createAt(o,0))&&gf(o,e)){yield o}}}containsEntireContent(t=this.anchor.root){const e=Jh._createAt(t,0);const n=Jh._createAt(t,"end");return e.isTouching(this.getFirstPosition())&&n.isTouching(this.getLastPosition())}_pushRange(t){this._checkRange(t);this._ranges.push(new ef(t.start,t.end))}_checkRange(t){for(let e=0;e0){this._popRange()}}_popRange(){this._ranges.pop()}}_s(uf,ds);function hf(t,e){if(e.has(t)){return false}e.add(t);return t.root.document.model.schema.isBlock(t)&&t.parent}function ff(t,e,n){return hf(t,e)&&gf(t,n)}function mf(t,e){const n=t.parent;const o=n.root.document.model.schema;const i=t.parent.getAncestors({parentFirst:true,includeSelf:true});let r=false;const s=i.find((t=>{if(r){return false}r=o.isLimit(t);return!r&&hf(t,e)}));i.forEach((t=>e.add(t)));return s}function gf(t,e){const n=pf(t);if(!n){return true}const o=e.containsRange(ef._createOn(n),true);return!o}function pf(t){const e=t.root.document.model.schema;let n=t.parent;while(n){if(e.isBlock(n)){return n}n=n.parent}}class kf extends ef{constructor(t,e){super(t,e);bf.call(this)}detach(){this.stopListening()}is(t){return t==="liveRange"||t==="model:liveRange"||t=="range"||t==="model:range"}toRange(){return new ef(this.start,this.end)}static fromRange(t){return new kf(t.start,t.end)}}function bf(){this.listenTo(this.root.document.model,"applyOperation",((t,e)=>{const n=e[0];if(!n.isDocumentOperation){return}wf.call(this,n)}),{priority:"low"})}function wf(t){const e=this.getTransformedByOperation(t);const n=ef._createFromRanges(e);const o=!n.isEqual(this);const i=Cf(this,t);let r=null;if(o){if(n.root.rootName=="$graveyard"){if(t.type=="remove"){r=t.sourcePosition}else{r=t.deletionPosition}}const e=this.toRange();this.start=n.start;this.end=n.end;this.fire("change:range",e,{deletionPosition:r})}else if(i){this.fire("change:content",this.toRange(),{deletionPosition:r})}}function Cf(t,e){switch(e.type){case"insert":return t.containsPosition(e.position);case"move":case"remove":case"reinsert":case"merge":return t.containsPosition(e.sourcePosition)||t.start.isEqual(e.sourcePosition)||t.containsPosition(e.targetPosition);case"split":return t.containsPosition(e.splitPosition)||t.containsPosition(e.insertionPosition)}return false}_s(kf,ds);const Af="selection:";class _f{constructor(t){this._selection=new vf(t);this._selection.delegate("change:range").to(this);this._selection.delegate("change:attribute").to(this);this._selection.delegate("change:marker").to(this)}get isCollapsed(){return this._selection.isCollapsed}get anchor(){return this._selection.anchor}get focus(){return this._selection.focus}get rangeCount(){return this._selection.rangeCount}get hasOwnRange(){return this._selection.hasOwnRange}get isBackward(){return this._selection.isBackward}get isGravityOverridden(){return this._selection.isGravityOverridden}get markers(){return this._selection.markers}get _ranges(){return this._selection._ranges}getRanges(){return this._selection.getRanges()}getFirstPosition(){return this._selection.getFirstPosition()}getLastPosition(){return this._selection.getLastPosition()}getFirstRange(){return this._selection.getFirstRange()}getLastRange(){return this._selection.getLastRange()}getSelectedBlocks(){return this._selection.getSelectedBlocks()}getSelectedElement(){return this._selection.getSelectedElement()}containsEntireContent(t){return this._selection.containsEntireContent(t)}destroy(){this._selection.destroy()}getAttributeKeys(){return this._selection.getAttributeKeys()}getAttributes(){return this._selection.getAttributes()}getAttribute(t){return this._selection.getAttribute(t)}hasAttribute(t){return this._selection.hasAttribute(t)}refresh(){this._selection._updateMarkers();this._selection._updateAttributes(false)}observeMarkers(t){this._selection.observeMarkers(t)}is(t){return t==="selection"||t=="model:selection"||t=="documentSelection"||t=="model:documentSelection"}_setFocus(t,e){this._selection.setFocus(t,e)}_setTo(t,e,n){this._selection.setTo(t,e,n)}_setAttribute(t,e){this._selection.setAttribute(t,e)}_removeAttribute(t){this._selection.removeAttribute(t)}_getStoredAttributes(){return this._selection._getStoredAttributes()}_overrideGravity(){return this._selection.overrideGravity()}_restoreGravity(t){this._selection.restoreGravity(t)}static _getStoreAttributeKey(t){return Af+t}static _isStoreAttributeKey(t){return t.startsWith(Af)}}_s(_f,ds);class vf extends uf{constructor(t){super();this.markers=new vs({idProperty:"name"});this._model=t.model;this._document=t;this._attributePriority=new Map;this._selectionRestorePosition=null;this._hasChangedRange=false;this._overriddenGravityRegister=new Set;this._observedMarkers=new Set;this.listenTo(this._model,"applyOperation",((t,e)=>{const n=e[0];if(!n.isDocumentOperation||n.type=="marker"||n.type=="rename"||n.type=="noop"){return}if(this._ranges.length==0&&this._selectionRestorePosition){this._fixGraveyardSelection(this._selectionRestorePosition)}this._selectionRestorePosition=null;if(this._hasChangedRange){this._hasChangedRange=false;this.fire("change:range",{directChange:false})}}),{priority:"lowest"});this.on("change:range",(()=>{for(const t of this.getRanges()){if(!this._document._validateSelectionRange(t)){throw new ss["a"]("document-selection-wrong-position",this,{range:t})}}}));this.listenTo(this._model.markers,"update",((t,e,n,o)=>{this._updateMarker(e,o)}));this.listenTo(this._document,"change",((t,e)=>{xf(this._model,e)}))}get isCollapsed(){const t=this._ranges.length;return t===0?this._document._getDefaultRange().isCollapsed:super.isCollapsed}get anchor(){return super.anchor||this._document._getDefaultRange().start}get focus(){return super.focus||this._document._getDefaultRange().end}get rangeCount(){return this._ranges.length?this._ranges.length:1}get hasOwnRange(){return this._ranges.length>0}get isGravityOverridden(){return!!this._overriddenGravityRegister.size}destroy(){for(let t=0;t{this._hasChangedRange=true;if(e.root==this._document.graveyard){this._selectionRestorePosition=o.deletionPosition;const t=this._ranges.indexOf(e);this._ranges.splice(t,1);e.detach()}}));return e}_updateMarkers(){if(!this._observedMarkers.size){return}const t=[];let e=false;for(const e of this._model.markers){const n=e.name.split(":",1)[0];if(!this._observedMarkers.has(n)){continue}const o=e.getRange();for(const n of this.getRanges()){if(o.containsRange(n,!n.isCollapsed)){t.push(e)}}}const n=Array.from(this.markers);for(const n of t){if(!this.markers.has(n)){this.markers.add(n);e=true}}for(const n of Array.from(this.markers)){if(!t.includes(n)){this.markers.remove(n);e=true}}if(e){this.fire("change:marker",{oldMarkers:n,directChange:false})}}_updateMarker(t,e){const n=t.name.split(":",1)[0];if(!this._observedMarkers.has(n)){return}let o=false;const i=Array.from(this.markers);const r=this.markers.has(t);if(!e){if(r){this.markers.remove(t);o=true}}else{let n=false;for(const t of this.getRanges()){if(e.containsRange(t,!t.isCollapsed)){n=true;break}}if(n&&!r){this.markers.add(t);o=true}else if(!n&&r){this.markers.remove(t);o=true}}if(o){this.fire("change:marker",{oldMarkers:i,directChange:false})}}_updateAttributes(t){const e=Gs(this._getSurroundingAttributes());const n=Gs(this.getAttributes());if(t){this._attributePriority=new Map;this._attrs=new Map}else{for(const[t,e]of this._attributePriority){if(e=="low"){this._attrs.delete(t);this._attributePriority.delete(t)}}}this._setAttributesTo(e);const o=[];for(const[t,e]of this.getAttributes()){if(!n.has(t)||n.get(t)!==e){o.push(t)}}for(const[t]of n){if(!this.hasAttribute(t)){o.push(t)}}if(o.length>0){this.fire("change:attribute",{attributeKeys:o,directChange:false})}}_setAttribute(t,e,n=true){const o=n?"normal":"low";if(o=="low"&&this._attributePriority.get(t)=="normal"){return false}const i=super.getAttribute(t);if(i===e){return false}this._attrs.set(t,e);this._attributePriority.set(t,o);return true}_removeAttribute(t,e=true){const n=e?"normal":"low";if(n=="low"&&this._attributePriority.get(t)=="normal"){return false}this._attributePriority.set(t,n);if(!super.hasAttribute(t)){return false}this._attrs.delete(t);return true}_setAttributesTo(t){const e=new Set;for(const[e,n]of this.getAttributes()){if(t.get(e)===n){continue}this._removeAttribute(e,false)}for(const[n,o]of t){const t=this._setAttribute(n,o,false);if(t){e.add(n)}}return e}*_getStoredAttributes(){const t=this.getFirstPosition().parent;if(this.isCollapsed&&t.isEmpty){for(const e of t.getAttributeKeys()){if(e.startsWith(Af)){const n=e.substr(Af.length);yield[n,t.getAttribute(e)]}}}}_getSurroundingAttributes(){const t=this.getFirstPosition();const e=this._model.schema;let n=null;if(!this.isCollapsed){const t=this.getFirstRange();for(const o of t){if(o.item.is("element")&&e.isObject(o.item)){break}if(o.type=="text"){n=o.item.getAttributes();break}}}else{const o=t.textNode?t.textNode:t.nodeBefore;const i=t.textNode?t.textNode:t.nodeAfter;if(!this.isGravityOverridden){n=yf(o)}if(!n){n=yf(i)}if(!this.isGravityOverridden&&!n){let t=o;while(t&&!e.isInline(t)&&!n){t=t.previousSibling;n=yf(t)}}if(!n){let t=i;while(t&&!e.isInline(t)&&!n){t=t.nextSibling;n=yf(t)}}if(!n){n=this._getStoredAttributes()}}return n}_fixGraveyardSelection(t){const e=this._model.schema.getNearestSelectionRange(t);if(e){this._pushRange(e)}}}function yf(t){if(t instanceof Kh||t instanceof Gh){return t.getAttributes()}return null}function xf(t,e){const n=t.document.differ;for(const o of n.getChanges()){if(o.type!="insert"){continue}const n=o.position.parent;const i=o.length===n.maxOffset;if(i){t.enqueueChange(e,(t=>{const e=Array.from(n.getAttributeKeys()).filter((t=>t.startsWith(Af)));for(const o of e){t.removeAttribute(o,n)}}))}}}class Df{constructor(t){this._dispatchers=t}add(t){for(const e of this._dispatchers){t(e)}return this}}var Ef=1,Mf=4;function Tf(t){return Ur(t,Ef|Mf)}var Sf=Tf;class If extends Df{elementToElement(t){return this.add(Jf(t))}attributeToElement(t){return this.add(Zf(t))}attributeToAttribute(t){return this.add(Xf(t))}markerToElement(t){return this.add(tm(t))}markerToHighlight(t){return this.add(nm(t))}markerToData(t){return this.add(em(t))}}function Nf(){return(t,e,n)=>{if(!n.consumable.consume(e.item,"insert")){return}const o=n.writer;const i=n.mapper.toViewPosition(e.range.start);const r=o.createText(e.item.data);o.insert(i,r)}}function Bf(){return(t,e,n)=>{const o=n.mapper.toViewPosition(e.position);const i=e.position.getShiftedBy(e.length);const r=n.mapper.toViewPosition(i,{isPhantom:true});const s=n.writer.createRange(o,r);const a=n.writer.remove(s.getTrimmed());for(const t of n.writer.createRangeIn(a).getItems()){n.mapper.unbindViewElement(t)}}}function Pf(t,e){const n=t.createAttributeElement("span",e.attributes);if(e.classes){n._addClass(e.classes)}if(e.priority){n._priority=e.priority}n._id=e.id;return n}function zf(){return(t,e,n)=>{const o=e.selection;if(o.isCollapsed){return}if(!n.consumable.consume(o,"selection")){return}const i=[];for(const t of o.getRanges()){const e=n.mapper.toViewRange(t);i.push(e)}n.writer.setSelection(i,{backward:o.isBackward})}}function Lf(){return(t,e,n)=>{const o=e.selection;if(!o.isCollapsed){return}if(!n.consumable.consume(o,"selection")){return}const i=n.writer;const r=o.getFirstPosition();const s=n.mapper.toViewPosition(r);const a=i.breakAttributes(s);i.setSelection(a)}}function Of(){return(t,e,n)=>{const o=n.writer;const i=o.document.selection;for(const t of i.getRanges()){if(t.isCollapsed){if(t.end.parent.isAttached()){n.writer.mergeAttributes(t.start)}}}o.setSelection(null)}}function Rf(t){return(e,n,o)=>{const i=t(n.attributeOldValue,o);const r=t(n.attributeNewValue,o);if(!i&&!r){return}if(!o.consumable.consume(n.item,e.name)){return}const s=o.writer;const a=s.document.selection;if(n.item instanceof uf||n.item instanceof _f){s.wrap(a.getFirstRange(),r)}else{let t=o.mapper.toViewRange(n.range);if(n.attributeOldValue!==null&&i){t=s.unwrap(t,i)}if(n.attributeNewValue!==null&&r){s.wrap(t,r)}}}}function jf(t){return(e,n,o)=>{const i=t(n.item,o);if(!i){return}if(!o.consumable.consume(n.item,"insert")){return}const r=o.mapper.toViewPosition(n.range.start);o.mapper.bindElements(n.item,i);o.writer.insert(r,i)}}function Ff(t){return(e,n,o)=>{n.isOpening=true;const i=t(n,o);n.isOpening=false;const r=t(n,o);if(!i||!r){return}const s=n.markerRange;if(s.isCollapsed&&!o.consumable.consume(s,e.name)){return}for(const t of s){if(!o.consumable.consume(t.item,e.name)){return}}const a=o.mapper;const c=o.writer;c.insert(a.toViewPosition(s.start),i);o.mapper.bindElementToMarker(i,n.markerName);if(!s.isCollapsed){c.insert(a.toViewPosition(s.end),r);o.mapper.bindElementToMarker(r,n.markerName)}e.stop()}}function Vf(){return(t,e,n)=>{const o=n.mapper.markerNameToElements(e.markerName);if(!o){return}for(const t of o){n.mapper.unbindElementFromMarkerName(t,e.markerName);n.writer.clear(n.writer.createRangeOn(t),t)}n.writer.clearClonedElementsGroup(e.markerName);t.stop()}}function Uf(t){return(e,n,o)=>{const i=t(n.markerName,o);if(!i){return}const r=n.markerRange;if(!o.consumable.consume(r,e.name)){return}Hf(r,false,o,n,i);Hf(r,true,o,n,i);e.stop()}}function Hf(t,e,n,o,i){const r=e?t.start:t.end;const s=n.schema.checkChild(r,"$text");if(s){const t=n.mapper.toViewPosition(r);Kf(t,e,n,o,i)}else{let t;let s;if(e&&r.nodeAfter||!e&&!r.nodeBefore){t=r.nodeAfter;s=true}else{t=r.nodeBefore;s=false}const a=n.mapper.toViewElement(t);Gf(a,e,s,n,o,i)}}function Gf(t,e,n,o,i,r){const s=`data-${r.group}-${e?"start":"end"}-${n?"before":"after"}`;const a=t.hasAttribute(s)?t.getAttribute(s).split(","):[];a.unshift(r.name);o.writer.setAttribute(s,a.join(","),t);o.mapper.bindElementToMarker(t,i.markerName)}function Kf(t,e,n,o,i){const r=`${i.group}-${e?"start":"end"}`;const s=i.name?{name:i.name}:null;const a=n.writer.createUIElement(r,s);n.writer.insert(t,a);n.mapper.bindElementToMarker(a,o.markerName)}function Wf(t){return(e,n,o)=>{const i=t(n.markerName,o);if(!i){return}const r=o.mapper.markerNameToElements(n.markerName);if(!r){return}for(const t of r){o.mapper.unbindElementFromMarkerName(t,n.markerName);if(t.is("containerElement")){s(`data-${i.group}-start-before`,t);s(`data-${i.group}-start-after`,t);s(`data-${i.group}-end-before`,t);s(`data-${i.group}-end-after`,t)}else{o.writer.clear(o.writer.createRangeOn(t),t)}}o.writer.clearClonedElementsGroup(n.markerName);e.stop();function s(t,e){if(e.hasAttribute(t)){const n=new Set(e.getAttribute(t).split(","));n.delete(i.name);if(n.size==0){o.writer.removeAttribute(t,e)}else{o.writer.setAttribute(t,Array.from(n).join(","),e)}}}}}function qf(t){return(e,n,o)=>{const i=t(n.attributeOldValue,o);const r=t(n.attributeNewValue,o);if(!i&&!r){return}if(!o.consumable.consume(n.item,e.name)){return}const s=o.mapper.toViewElement(n.item);const a=o.writer;if(!s){throw new ss["a"]("conversion-attribute-to-attribute-on-text",[n,o])}if(n.attributeOldValue!==null&&i){if(i.key=="class"){const t=xs(i.value);for(const e of t){a.removeClass(e,s)}}else if(i.key=="style"){const t=Object.keys(i.value);for(const e of t){a.removeStyle(e,s)}}else{a.removeAttribute(i.key,s)}}if(n.attributeNewValue!==null&&r){if(r.key=="class"){const t=xs(r.value);for(const e of t){a.addClass(e,s)}}else if(r.key=="style"){const t=Object.keys(r.value);for(const e of t){a.setStyle(e,r.value[e],s)}}else{a.setAttribute(r.key,r.value,s)}}}}function Yf(t){return(e,n,o)=>{if(!n.item){return}if(!(n.item instanceof uf||n.item instanceof _f)&&!n.item.is("$textProxy")){return}const i=am(t,n,o);if(!i){return}if(!o.consumable.consume(n.item,e.name)){return}const r=o.writer;const s=Pf(r,i);const a=r.document.selection;if(n.item instanceof uf||n.item instanceof _f){r.wrap(a.getFirstRange(),s,a)}else{const t=o.mapper.toViewRange(n.range);const e=r.wrap(t,s);for(const t of e.getItems()){if(t.is("attributeElement")&&t.isSimilar(s)){o.mapper.bindElementToMarker(t,n.markerName);break}}}}}function Qf(t){return(e,n,o)=>{if(!n.item){return}if(!(n.item instanceof qh)){return}const i=am(t,n,o);if(!i){return}if(!o.consumable.test(n.item,e.name)){return}const r=o.mapper.toViewElement(n.item);if(r&&r.getCustomProperty("addHighlight")){o.consumable.consume(n.item,e.name);for(const t of ef._createIn(n.item)){o.consumable.consume(t.item,e.name)}r.getCustomProperty("addHighlight")(r,i,o.writer);o.mapper.bindElementToMarker(r,n.markerName)}}}function $f(t){return(e,n,o)=>{if(n.markerRange.isCollapsed){return}const i=am(t,n,o);if(!i){return}const r=Pf(o.writer,i);const s=o.mapper.markerNameToElements(n.markerName);if(!s){return}for(const t of s){o.mapper.unbindElementFromMarkerName(t,n.markerName);if(t.is("attributeElement")){o.writer.unwrap(o.writer.createRangeOn(t),r)}else{t.getCustomProperty("removeHighlight")(t,i.id,o.writer)}}o.writer.clearClonedElementsGroup(n.markerName);e.stop()}}function Jf(t){t=Sf(t);t.view=om(t.view,"container");return e=>{e.on("insert:"+t.model,jf(t.view),{priority:t.converterPriority||"normal"});if(t.triggerBy){if(t.triggerBy.attributes){for(const n of t.triggerBy.attributes){e._mapReconversionTriggerEvent(t.model,`attribute:${n}:${t.model}`)}}if(t.triggerBy.children){for(const n of t.triggerBy.children){e._mapReconversionTriggerEvent(t.model,`insert:${n}`);e._mapReconversionTriggerEvent(t.model,`remove:${n}`)}}}}}function Zf(t){t=Sf(t);const e=t.model.key?t.model.key:t.model;let n="attribute:"+e;if(t.model.name){n+=":"+t.model.name}if(t.model.values){for(const e of t.model.values){t.view[e]=om(t.view[e],"attribute")}}else{t.view=om(t.view,"attribute")}const o=rm(t);return e=>{e.on(n,Rf(o),{priority:t.converterPriority||"normal"})}}function Xf(t){t=Sf(t);const e=t.model.key?t.model.key:t.model;let n="attribute:"+e;if(t.model.name){n+=":"+t.model.name}if(t.model.values){for(const e of t.model.values){t.view[e]=sm(t.view[e])}}else{t.view=sm(t.view)}const o=rm(t);return e=>{e.on(n,qf(o),{priority:t.converterPriority||"normal"})}}function tm(t){t=Sf(t);t.view=om(t.view,"ui");return e=>{e.on("addMarker:"+t.model,Ff(t.view),{priority:t.converterPriority||"normal"});e.on("removeMarker:"+t.model,Vf(t.view),{priority:t.converterPriority||"normal"})}}function em(t){t=Sf(t);const e=t.model;if(!t.view){t.view=n=>({group:e,name:n.substr(t.model.length+1)})}return n=>{n.on("addMarker:"+e,Uf(t.view),{priority:t.converterPriority||"normal"});n.on("removeMarker:"+e,Wf(t.view),{priority:t.converterPriority||"normal"})}}function nm(t){return e=>{e.on("addMarker:"+t.model,Yf(t.view),{priority:t.converterPriority||"normal"});e.on("addMarker:"+t.model,Qf(t.view),{priority:t.converterPriority||"normal"});e.on("removeMarker:"+t.model,$f(t.view),{priority:t.converterPriority||"normal"})}}function om(t,e){if(typeof t=="function"){return t}return(n,o)=>im(t,o,e)}function im(t,e,n){if(typeof t=="string"){t={name:t}}let o;const i=e.writer;const r=Object.assign({},t.attributes);if(n=="container"){o=i.createContainerElement(t.name,r)}else if(n=="attribute"){const e={priority:t.priority||Cl.DEFAULT_PRIORITY};o=i.createAttributeElement(t.name,r,e)}else{o=i.createUIElement(t.name,r)}if(t.styles){const e=Object.keys(t.styles);for(const n of e){i.setStyle(n,t.styles[n],o)}}if(t.classes){const e=t.classes;if(typeof e=="string"){i.addClass(e,o)}else{for(const t of e){i.addClass(t,o)}}}return o}function rm(t){if(t.model.values){return(e,n)=>{const o=t.view[e];if(o){return o(e,n)}return null}}else{return t.view}}function sm(t){if(typeof t=="string"){return e=>({key:t,value:e})}else if(typeof t=="object"){if(t.value){return()=>t}else{return e=>({key:t.key,value:e})}}else{return t}}function am(t,e,n){const o=typeof t=="function"?t(e,n):t;if(!o){return null}if(!o.priority){o.priority=10}if(!o.id){o.id=e.markerName}return o}function cm(t){const{schema:e,document:n}=t.model;for(const o of n.getRootNames()){const i=n.getRoot(o);if(i.isEmpty&&!e.checkChild(i,"$text")){if(e.checkChild(i,"paragraph")){t.insertElement("paragraph",i);return true}}}return false}function lm(t,e,n){const o=n.createContext(t);if(!n.checkChild(o,"paragraph")){return false}if(!n.checkChild(o.push("paragraph"),e)){return false}return true}function dm(t,e){const n=e.createElement("paragraph");e.insert(n,t);return e.createPositionAt(n,0)}class um extends Df{elementToElement(t){return this.add(gm(t))}elementToAttribute(t){return this.add(pm(t))}attributeToAttribute(t){return this.add(km(t))}elementToMarker(t){Object(ss["c"])("upcast-helpers-element-to-marker-deprecated");return this.add(bm(t))}dataToMarker(t){return this.add(wm(t))}}function hm(){return(t,e,n)=>{if(!e.modelRange&&n.consumable.consume(e.viewItem,{name:true})){const{modelRange:t,modelCursor:o}=n.convertChildren(e.viewItem,e.modelCursor);e.modelRange=t;e.modelCursor=o}}}function fm(){return(t,e,{schema:n,consumable:o,writer:i})=>{let r=e.modelCursor;if(!o.test(e.viewItem)){return}if(!n.checkChild(r,"$text")){if(!lm(r,"$text",n)){return}r=dm(r,i)}o.consume(e.viewItem);const s=i.createText(e.viewItem.data);i.insert(s,r);e.modelRange=i.createRange(r,r.getShiftedBy(s.offsetSize));e.modelCursor=e.modelRange.end}}function mm(t,e){return(n,o)=>{const i=o.newSelection;const r=[];for(const t of i.getRanges()){r.push(e.toModelRange(t))}const s=t.createSelection(r,{backward:i.isBackward});if(!s.isEqual(t.document.selection)){t.change((t=>{t.setSelection(s)}))}}}function gm(t){t=Sf(t);const e=_m(t);const n=Am(t.view);const o=n?"element:"+n:"element";return n=>{n.on(o,e,{priority:t.converterPriority||"normal"})}}function pm(t){t=Sf(t);xm(t);const e=Dm(t,false);const n=Am(t.view);const o=n?"element:"+n:"element";return n=>{n.on(o,e,{priority:t.converterPriority||"low"})}}function km(t){t=Sf(t);let e=null;if(typeof t.view=="string"||t.view.key){e=ym(t)}xm(t,e);const n=Dm(t,true);return e=>{e.on("element",n,{priority:t.converterPriority||"low"})}}function bm(t){t=Sf(t);Tm(t);return gm(t)}function wm(t){t=Sf(t);if(!t.model){t.model=e=>e?t.view+":"+e:t.view}const e=_m(Sm(t,"start"));const n=_m(Sm(t,"end"));return o=>{o.on("element:"+t.view+"-start",e,{priority:t.converterPriority||"normal"});o.on("element:"+t.view+"-end",n,{priority:t.converterPriority||"normal"});const i=is.get("low");const r=is.get("highest");const s=is.get(t.converterPriority)/r;o.on("element",Cm(t),{priority:i+s})}}function Cm(t){return(e,n,o)=>{const i=`data-${t.view}`;if(!n.modelRange){n=Object.assign(n,o.convertChildren(n.viewItem,n.modelCursor))}if(o.consumable.consume(n.viewItem,{attributes:i+"-end-after"})){r(n.modelRange.end,n.viewItem.getAttribute(i+"-end-after").split(","))}if(o.consumable.consume(n.viewItem,{attributes:i+"-start-after"})){r(n.modelRange.end,n.viewItem.getAttribute(i+"-start-after").split(","))}if(o.consumable.consume(n.viewItem,{attributes:i+"-end-before"})){r(n.modelRange.start,n.viewItem.getAttribute(i+"-end-before").split(","))}if(o.consumable.consume(n.viewItem,{attributes:i+"-start-before"})){r(n.modelRange.start,n.viewItem.getAttribute(i+"-start-before").split(","))}function r(e,i){for(const r of i){const i=t.model(r,o);const s=o.writer.createElement("$marker",{"data-name":i});o.writer.insert(s,e);if(n.modelCursor.isEqual(e)){n.modelCursor=n.modelCursor.getShiftedBy(1)}else{n.modelCursor=n.modelCursor._getTransformedByInsertion(e,1)}n.modelRange=n.modelRange._getTransformedByInsertion(e,1)[0]}}}}function Am(t){if(typeof t=="string"){return t}if(typeof t=="object"&&typeof t.name=="string"){return t.name}return null}function _m(t){const e=new Ks(t.view);return(n,o,i)=>{const r=e.match(o.viewItem);if(!r){return}const s=r.match;s.name=true;if(!i.consumable.test(o.viewItem,s)){return}const a=vm(t.model,o.viewItem,i);if(!a){return}if(!i.safeInsert(a,o.modelCursor)){return}i.consumable.consume(o.viewItem,s);i.convertChildren(o.viewItem,a);i.updateConversionResult(a,o)}}function vm(t,e,n){if(t instanceof Function){return t(e,n)}else{return n.writer.createElement(t)}}function ym(t){if(typeof t.view=="string"){t.view={key:t.view}}const e=t.view.key;let n;if(e=="class"||e=="style"){const o=e=="class"?"classes":"styles";n={[o]:t.view.value}}else{const o=typeof t.view.value=="undefined"?/[\s\S]*/:t.view.value;n={attributes:{[e]:o}}}if(t.view.name){n.name=t.view.name}t.view=n;return e}function xm(t,e=null){const n=e===null?true:t=>t.getAttribute(e);const o=typeof t.model!="object"?t.model:t.model.key;const i=typeof t.model!="object"||typeof t.model.value=="undefined"?n:t.model.value;t.model={key:o,value:i}}function Dm(t,e){const n=new Ks(t.view);return(o,i,r)=>{const s=n.match(i.viewItem);if(!s){return}const a=t.model.key;const c=typeof t.model.value=="function"?t.model.value(i.viewItem,r):t.model.value;if(c===null){return}if(Em(t.view,i.viewItem)){s.match.name=true}else{delete s.match.name}if(!r.consumable.test(i.viewItem,s.match)){return}if(!i.modelRange){i=Object.assign(i,r.convertChildren(i.viewItem,i.modelCursor))}const l=Mm(i.modelRange,{key:a,value:c},e,r);if(l){r.consumable.consume(i.viewItem,s.match)}}}function Em(t,e){const n=typeof t=="function"?t(e):t;if(typeof n=="object"&&!Am(n)){return false}return!n.classes&&!n.attributes&&!n.styles}function Mm(t,e,n,o){let i=false;for(const r of Array.from(t.getItems({shallow:n}))){if(o.schema.checkAttribute(r,e.key)){o.writer.setAttribute(e.key,e.value,r);i=true}}return i}function Tm(t){const e=t.model;t.model=(t,n)=>{const o=typeof e=="string"?e:e(t,n);return n.writer.createElement("$marker",{"data-name":o})}}function Sm(t,e){const n={};n.view=t.view+"-"+e;n.model=(e,n)=>{const o=e.getAttribute("name");const i=t.model(o,n);return n.writer.createElement("$marker",{"data-name":i})};return n}class Im{constructor(t,e){this.model=t;this.view=new Uh(e);this.mapper=new nf;this.downcastDispatcher=new sf({mapper:this.mapper,schema:t.schema});const n=this.model.document;const o=n.selection;const i=this.model.markers;this.listenTo(this.model,"_beforeChanges",(()=>{this.view._disableRendering(true)}),{priority:"highest"});this.listenTo(this.model,"_afterChanges",(()=>{this.view._disableRendering(false)}),{priority:"lowest"});this.listenTo(n,"change",(()=>{this.view.change((t=>{this.downcastDispatcher.convertChanges(n.differ,i,t);this.downcastDispatcher.convertSelection(o,i,t)}))}),{priority:"low"});this.listenTo(this.view.document,"selectionChange",mm(this.model,this.mapper));this.downcastDispatcher.on("insert:$text",Nf(),{priority:"lowest"});this.downcastDispatcher.on("remove",Bf(),{priority:"low"});this.downcastDispatcher.on("selection",Of(),{priority:"low"});this.downcastDispatcher.on("selection",zf(),{priority:"low"});this.downcastDispatcher.on("selection",Lf(),{priority:"low"});this.view.document.roots.bindTo(this.model.document.roots).using((t=>{if(t.rootName=="$graveyard"){return null}const e=new dl(this.view.document,t.name);e.rootName=t.rootName;this.mapper.bindElements(t,e);return e}))}destroy(){this.view.destroy();this.stopListening()}}_s(Im,Jc);class Nm{constructor(){this._commands=new Map}add(t,e){this._commands.set(t,e)}get(t){return this._commands.get(t)}execute(t,...e){const n=this.get(t);if(!n){throw new ss["a"]("commandcollection-command-not-found",this,{commandName:t})}return n.execute(...e)}*names(){yield*this._commands.keys()}*commands(){yield*this._commands.values()}[Symbol.iterator](){return this._commands[Symbol.iterator]()}destroy(){for(const t of this.commands()){t.destroy()}}}class Bm{constructor(){this._consumables=new Map}add(t,e){let n;if(t.is("$text")||t.is("documentFragment")){this._consumables.set(t,true);return}if(!this._consumables.has(t)){n=new Pm(t);this._consumables.set(t,n)}else{n=this._consumables.get(t)}n.add(e)}test(t,e){const n=this._consumables.get(t);if(n===undefined){return null}if(t.is("$text")||t.is("documentFragment")){return n}return n.test(e)}consume(t,e){if(this.test(t,e)){if(t.is("$text")||t.is("documentFragment")){this._consumables.set(t,false)}else{this._consumables.get(t).consume(e)}return true}return false}revert(t,e){const n=this._consumables.get(t);if(n!==undefined){if(t.is("$text")||t.is("documentFragment")){this._consumables.set(t,true)}else{n.revert(e)}}}static consumablesFromElement(t){const e={element:t,name:true,attributes:[],classes:[],styles:[]};const n=t.getAttributeKeys();for(const t of n){if(t=="style"||t=="class"){continue}e.attributes.push(t)}const o=t.getClassNames();for(const t of o){e.classes.push(t)}const i=t.getStyleNames();for(const t of i){e.styles.push(t)}return e}static createFrom(t,e){if(!e){e=new Bm(t)}if(t.is("$text")){e.add(t);return e}if(t.is("element")){e.add(t,Bm.consumablesFromElement(t))}if(t.is("documentFragment")){e.add(t)}for(const n of t.getChildren()){e=Bm.createFrom(n,e)}return e}}class Pm{constructor(t){this.element=t;this._canConsumeName=null;this._consumables={attributes:new Map,styles:new Map,classes:new Map}}add(t){if(t.name){this._canConsumeName=true}for(const e in this._consumables){if(e in t){this._add(e,t[e])}}}test(t){if(t.name&&!this._canConsumeName){return this._canConsumeName}for(const e in this._consumables){if(e in t){const n=this._test(e,t[e]);if(n!==true){return n}}}return true}consume(t){if(t.name){this._canConsumeName=false}for(const e in this._consumables){if(e in t){this._consume(e,t[e])}}}revert(t){if(t.name){this._canConsumeName=true}for(const e in this._consumables){if(e in t){this._revert(e,t[e])}}}_add(t,e){const n=Qe(e)?e:[e];const o=this._consumables[t];for(const e of n){if(t==="attributes"&&(e==="class"||e==="style")){throw new ss["a"]("viewconsumable-invalid-attribute",this)}o.set(e,true);if(t==="styles"){for(const t of this.element.document.stylesProcessor.getRelatedStyles(e)){o.set(t,true)}}}}_test(t,e){const n=Qe(e)?e:[e];const o=this._consumables[t];for(const e of n){if(t==="attributes"&&(e==="class"||e==="style")){const t=e=="class"?"classes":"styles";const n=this._test(t,[...this._consumables[t].keys()]);if(n!==true){return n}}else{const t=o.get(e);if(t===undefined){return null}if(!t){return false}}}return true}_consume(t,e){const n=Qe(e)?e:[e];const o=this._consumables[t];for(const e of n){if(t==="attributes"&&(e==="class"||e==="style")){const t=e=="class"?"classes":"styles";this._consume(t,[...this._consumables[t].keys()])}else{o.set(e,false);if(t=="styles"){for(const t of this.element.document.stylesProcessor.getRelatedStyles(e)){o.set(t,false)}}}}}_revert(t,e){const n=Qe(e)?e:[e];const o=this._consumables[t];for(const e of n){if(t==="attributes"&&(e==="class"||e==="style")){const t=e=="class"?"classes":"styles";this._revert(t,[...this._consumables[t].keys()])}else{const t=o.get(e);if(t===false){o.set(e,true)}}}}}class zm{constructor(){this._sourceDefinitions={};this._attributeProperties={};this.decorate("checkChild");this.decorate("checkAttribute");this.on("checkAttribute",((t,e)=>{e[0]=new Lm(e[0])}),{priority:"highest"});this.on("checkChild",((t,e)=>{e[0]=new Lm(e[0]);e[1]=this.getDefinition(e[1])}),{priority:"highest"})}register(t,e){if(this._sourceDefinitions[t]){throw new ss["a"]("schema-cannot-register-item-twice",this,{itemName:t})}this._sourceDefinitions[t]=[Object.assign({},e)];this._clearCache()}extend(t,e){if(!this._sourceDefinitions[t]){throw new ss["a"]("schema-cannot-extend-missing-item",this,{itemName:t})}this._sourceDefinitions[t].push(Object.assign({},e));this._clearCache()}getDefinitions(){if(!this._compiledDefinitions){this._compile()}return this._compiledDefinitions}getDefinition(t){let e;if(typeof t=="string"){e=t}else if(t.is&&(t.is("$text")||t.is("$textProxy"))){e="$text"}else{e=t.name}return this.getDefinitions()[e]}isRegistered(t){return!!this.getDefinition(t)}isBlock(t){const e=this.getDefinition(t);return!!(e&&e.isBlock)}isLimit(t){const e=this.getDefinition(t);if(!e){return false}return!!(e.isLimit||e.isObject)}isObject(t){const e=this.getDefinition(t);if(!e){return false}return!!(e.isObject||e.isLimit&&e.isSelectable&&e.isContent)}isInline(t){const e=this.getDefinition(t);return!!(e&&e.isInline)}isSelectable(t){const e=this.getDefinition(t);if(!e){return false}return!!(e.isSelectable||e.isObject)}isContent(t){const e=this.getDefinition(t);if(!e){return false}return!!(e.isContent||e.isObject)}checkChild(t,e){if(!e){return false}return this._checkContextMatch(e,t)}checkAttribute(t,e){const n=this.getDefinition(t.last);if(!n){return false}return n.allowAttributes.includes(e)}checkMerge(t,e=null){if(t instanceof Jh){const e=t.nodeBefore;const n=t.nodeAfter;if(!(e instanceof qh)){throw new ss["a"]("schema-check-merge-no-element-before",this)}if(!(n instanceof qh)){throw new ss["a"]("schema-check-merge-no-element-after",this)}return this.checkMerge(e,n)}for(const n of e.getChildren()){if(!this.checkChild(t,n)){return false}}return true}addChildCheck(t){this.on("checkChild",((e,[n,o])=>{if(!o){return}const i=t(n,o);if(typeof i=="boolean"){e.stop();e.return=i}}),{priority:"high"})}addAttributeCheck(t){this.on("checkAttribute",((e,[n,o])=>{const i=t(n,o);if(typeof i=="boolean"){e.stop();e.return=i}}),{priority:"high"})}setAttributeProperties(t,e){this._attributeProperties[t]=Object.assign(this.getAttributeProperties(t),e)}getAttributeProperties(t){return this._attributeProperties[t]||{}}getLimitElement(t){let e;if(t instanceof Jh){e=t.parent}else{const n=t instanceof ef?[t]:Array.from(t.getRanges());e=n.reduce(((t,e)=>{const n=e.getCommonAncestor();if(!t){return n}return t.getCommonAncestor(n,{includeSelf:true})}),null)}while(!this.isLimit(e)){if(e.parent){e=e.parent}else{break}}return e}checkAttributeInSelection(t,e){if(t.isCollapsed){const n=t.getFirstPosition();const o=[...n.getAncestors(),new Gh("",t.getAttributes())];return this.checkAttribute(o,e)}else{const n=t.getRanges();for(const t of n){for(const n of t){if(this.checkAttribute(n.item,e)){return true}}}}return false}*getValidRanges(t,e){t=Jm(t);for(const n of t){yield*this._getValidRangesForRange(n,e)}}getNearestSelectionRange(t,e="both"){if(this.checkChild(t,"$text")){return new ef(t)}let n,o;const i=t.getAncestors().reverse().find((t=>this.isLimit(t)))||t.root;if(e=="both"||e=="backward"){n=new Qh({boundaries:ef._createIn(i),startPosition:t,direction:"backward"})}if(e=="both"||e=="forward"){o=new Qh({boundaries:ef._createIn(i),startPosition:t})}for(const t of $m(n,o)){const e=t.walker==n?"elementEnd":"elementStart";const o=t.value;if(o.type==e&&this.isObject(o.item)){return ef._createOn(o.item)}if(this.checkChild(o.nextPosition,"$text")){return new ef(o.nextPosition)}}return null}findAllowedParent(t,e){let n=t.parent;while(n){if(this.checkChild(n,e)){return n}if(this.isLimit(n)){return null}n=n.parent}return null}removeDisallowedAttributes(t,e){for(const n of t){if(n.is("$text")){Zm(this,n,e)}else{const t=ef._createIn(n);const o=t.getPositions();for(const t of o){const n=t.nodeBefore||t.parent;Zm(this,n,e)}}}}createContext(t){return new Lm(t)}_clearCache(){this._compiledDefinitions=null}_compile(){const t={};const e=this._sourceDefinitions;const n=Object.keys(e);for(const o of n){t[o]=Om(e[o],o)}for(const e of n){Rm(t,e)}for(const e of n){jm(t,e)}for(const e of n){Fm(t,e);Vm(t,e)}for(const e of n){Um(t,e);Hm(t,e)}this._compiledDefinitions=t}_checkContextMatch(t,e,n=e.length-1){const o=e.getItem(n);if(t.allowIn.includes(o.name)){if(n==0){return true}else{const t=this.getDefinition(o);return this._checkContextMatch(t,e,n-1)}}else{return false}}*_getValidRangesForRange(t,e){let n=t.start;let o=t.start;for(const i of t.getItems({shallow:true})){if(i.is("element")){yield*this._getValidRangesForRange(ef._createIn(i),e)}if(!this.checkAttribute(i,e)){if(!n.isEqual(o)){yield new ef(n,o)}n=Jh._createAfter(i)}o=Jh._createAfter(i)}if(!n.isEqual(o)){yield new ef(n,o)}}}_s(zm,Jc);class Lm{constructor(t){if(t instanceof Lm){return t}if(typeof t=="string"){t=[t]}else if(!Array.isArray(t)){t=t.getAncestors({includeSelf:true})}if(t[0]&&typeof t[0]!="string"&&t[0].is("documentFragment")){t.shift()}this._items=t.map(Qm)}get length(){return this._items.length}get last(){return this._items[this._items.length-1]}[Symbol.iterator](){return this._items[Symbol.iterator]()}push(t){const e=new Lm([t]);e._items=[...this._items,...e._items];return e}getItem(t){return this._items[t]}*getNames(){yield*this._items.map((t=>t.name))}endsWith(t){return Array.from(this.getNames()).join(" ").endsWith(t)}startsWith(t){return Array.from(this.getNames()).join(" ").startsWith(t)}}function Om(t,e){const n={name:e,allowIn:[],allowContentOf:[],allowWhere:[],allowAttributes:[],allowAttributesOf:[],inheritTypesFrom:[]};Gm(t,n);Km(t,n,"allowIn");Km(t,n,"allowContentOf");Km(t,n,"allowWhere");Km(t,n,"allowAttributes");Km(t,n,"allowAttributesOf");Km(t,n,"inheritTypesFrom");Wm(t,n);return n}function Rm(t,e){for(const n of t[e].allowContentOf){if(t[n]){const o=qm(t,n);o.forEach((t=>{t.allowIn.push(e)}))}}delete t[e].allowContentOf}function jm(t,e){for(const n of t[e].allowWhere){const o=t[n];if(o){const n=o.allowIn;t[e].allowIn.push(...n)}}delete t[e].allowWhere}function Fm(t,e){for(const n of t[e].allowAttributesOf){const o=t[n];if(o){const n=o.allowAttributes;t[e].allowAttributes.push(...n)}}delete t[e].allowAttributesOf}function Vm(t,e){const n=t[e];for(const e of n.inheritTypesFrom){const o=t[e];if(o){const t=Object.keys(o).filter((t=>t.startsWith("is")));for(const e of t){if(!(e in n)){n[e]=o[e]}}}}delete n.inheritTypesFrom}function Um(t,e){const n=t[e];const o=n.allowIn.filter((e=>t[e]));n.allowIn=Array.from(new Set(o))}function Hm(t,e){const n=t[e];n.allowAttributes=Array.from(new Set(n.allowAttributes))}function Gm(t,e){for(const n of t){const t=Object.keys(n).filter((t=>t.startsWith("is")));for(const o of t){e[o]=n[o]}}}function Km(t,e,n){for(const o of t){if(typeof o[n]=="string"){e[n].push(o[n])}else if(Array.isArray(o[n])){e[n].push(...o[n])}}}function Wm(t,e){for(const n of t){const t=n.inheritAllFrom;if(t){e.allowContentOf.push(t);e.allowWhere.push(t);e.allowAttributesOf.push(t);e.inheritTypesFrom.push(t)}}}function qm(t,e){const n=t[e];return Ym(t).filter((t=>t.allowIn.includes(n.name)))}function Ym(t){return Object.keys(t).map((e=>t[e]))}function Qm(t){if(typeof t=="string"){return{name:t,*getAttributeKeys(){},getAttribute(){}}}else{return{name:t.is("element")?t.name:"$text",*getAttributeKeys(){yield*t.getAttributeKeys()},getAttribute(e){return t.getAttribute(e)}}}}function*$m(t,e){let n=false;while(!n){n=true;if(t){const e=t.next();if(!e.done){n=false;yield{walker:t,value:e.value}}}if(e){const t=e.next();if(!t.done){n=false;yield{walker:e,value:t.value}}}}}function*Jm(t){for(const e of t){yield*e.getMinimalFlatRanges()}}function Zm(t,e,n){for(const o of e.getAttributeKeys()){if(!t.checkAttribute(e,o)){n.removeAttribute(o,e)}}}class Xm{constructor(t={}){this._splitParts=new Map;this._cursorParents=new Map;this._modelCursor=null;this.conversionApi=Object.assign({},t);this.conversionApi.convertItem=this._convertItem.bind(this);this.conversionApi.convertChildren=this._convertChildren.bind(this);this.conversionApi.safeInsert=this._safeInsert.bind(this);this.conversionApi.updateConversionResult=this._updateConversionResult.bind(this);this.conversionApi.splitToAllowedParent=this._splitToAllowedParent.bind(this);this.conversionApi.getSplitParts=this._getSplitParts.bind(this)}convert(t,e,n=["$root"]){this.fire("viewCleanup",t);this._modelCursor=eg(n,e);this.conversionApi.writer=e;this.conversionApi.consumable=Bm.createFrom(t);this.conversionApi.store={};const{modelRange:o}=this._convertItem(t,this._modelCursor);const i=e.createDocumentFragment();if(o){this._removeEmptyElements();for(const t of Array.from(this._modelCursor.parent.getChildren())){e.append(t,i)}i.markers=tg(i,e)}this._modelCursor=null;this._splitParts.clear();this._cursorParents.clear();this.conversionApi.writer=null;this.conversionApi.store=null;return i}_convertItem(t,e){const n=Object.assign({viewItem:t,modelCursor:e,modelRange:null});if(t.is("element")){this.fire("element:"+t.name,n,this.conversionApi)}else if(t.is("$text")){this.fire("text",n,this.conversionApi)}else{this.fire("documentFragment",n,this.conversionApi)}if(n.modelRange&&!(n.modelRange instanceof ef)){throw new ss["a"]("view-conversion-dispatcher-incorrect-result",this)}return{modelRange:n.modelRange,modelCursor:n.modelCursor}}_convertChildren(t,e){let n=e.is("position")?e:Jh._createAt(e,0);const o=new ef(n);for(const e of Array.from(t.getChildren())){const t=this._convertItem(e,n);if(t.modelRange instanceof ef){o.end=t.modelRange.end;n=t.modelCursor}}return{modelRange:o,modelCursor:n}}_safeInsert(t,e){const n=this._splitToAllowedParent(t,e);if(!n){return false}this.conversionApi.writer.insert(t,n.position);return true}_updateConversionResult(t,e){const n=this._getSplitParts(t);const o=this.conversionApi.writer;if(!e.modelRange){e.modelRange=o.createRange(o.createPositionBefore(t),o.createPositionAfter(n[n.length-1]))}const i=this._cursorParents.get(t);if(i){e.modelCursor=o.createPositionAt(i,0)}else{e.modelCursor=e.modelRange.end}}_splitToAllowedParent(t,e){const{schema:n,writer:o}=this.conversionApi;let i=n.findAllowedParent(e,t);if(i){if(i===e.parent){return{position:e}}if(this._modelCursor.parent.getAncestors().includes(i)){i=null}}if(!i){if(!lm(e,t,n)){return null}return{position:dm(e,o)}}const r=this.conversionApi.writer.split(e,i);const s=[];for(const t of r.range.getWalker()){if(t.type=="elementEnd"){s.push(t.item)}else{const e=s.pop();const n=t.item;this._registerSplitPair(e,n)}}const a=r.range.end.parent;this._cursorParents.set(t,a);return{position:r.position,cursorParent:a}}_registerSplitPair(t,e){if(!this._splitParts.has(t)){this._splitParts.set(t,[t])}const n=this._splitParts.get(t);this._splitParts.set(e,n);n.push(e)}_getSplitParts(t){let e;if(!this._splitParts.has(t)){e=[t]}else{e=this._splitParts.get(t)}return e}_removeEmptyElements(){let t=false;for(const e of this._splitParts.keys()){if(e.isEmpty){this.conversionApi.writer.remove(e);this._splitParts.delete(e);t=true}}if(t){this._removeEmptyElements()}}}_s(Xm,ds);function tg(t,e){const n=new Set;const o=new Map;const i=ef._createIn(t).getItems();for(const t of i){if(t.name=="$marker"){n.add(t)}}for(const t of n){const n=t.getAttribute("data-name");const i=e.createPositionBefore(t);if(!o.has(n)){o.set(n,new ef(i.clone()))}else{o.get(n).end=i.clone()}e.remove(t)}return o}function eg(t,e){let n;for(const o of new Lm(t)){const t={};for(const e of o.getAttributeKeys()){t[e]=o.getAttribute(e)}const i=e.createElement(o.name,t);if(n){e.append(i,n)}n=Jh._createAt(i,0)}return n}class ng{constructor(t,e){this.model=t;this.stylesProcessor=e;this.processor=undefined;this.mapper=new nf;this.downcastDispatcher=new sf({mapper:this.mapper,schema:t.schema});this.downcastDispatcher.on("insert:$text",Nf(),{priority:"lowest"});this.upcastDispatcher=new Xm({schema:t.schema});this.viewDocument=new bl(e);this._viewWriter=new Xl(this.viewDocument);this.upcastDispatcher.on("text",fm(),{priority:"lowest"});this.upcastDispatcher.on("element",hm(),{priority:"lowest"});this.upcastDispatcher.on("documentFragment",hm(),{priority:"lowest"});this.decorate("init");this.decorate("set");this.on("init",(()=>{this.fire("ready")}),{priority:"lowest"});this.on("ready",(()=>{this.model.enqueueChange("transparent",cm)}),{priority:"lowest"})}get(t={}){const{rootName:e="main",trim:n="empty"}=t;if(!this._checkIfRootsExists([e])){throw new ss["a"]("datacontroller-get-non-existent-root",this)}const o=this.model.document.getRoot(e);if(n==="empty"&&!this.model.hasContent(o,{ignoreWhitespaces:true})){return""}return this.stringify(o,t)}stringify(t,e){const n=this.toView(t,e);return this.processor.toData(n)}toView(t,e){const n=this.viewDocument;const o=this._viewWriter;this.mapper.clearBindings();const i=ef._createIn(t);const r=new Jl(n);this.mapper.bindElements(t,r);this.downcastDispatcher.conversionApi.options=e;this.downcastDispatcher.convertInsert(i,o);if(!t.is("documentFragment")){const e=og(t);for(const[t,n]of e){this.downcastDispatcher.convertMarkerAdd(t,n,o)}}delete this.downcastDispatcher.conversionApi.options;return r}init(t){if(this.model.document.version){throw new ss["a"]("datacontroller-init-document-not-empty",this)}let e={};if(typeof t==="string"){e.main=t}else{e=t}if(!this._checkIfRootsExists(Object.keys(e))){throw new ss["a"]("datacontroller-init-non-existent-root",this)}this.model.enqueueChange("transparent",(t=>{for(const n of Object.keys(e)){const o=this.model.document.getRoot(n);t.insert(this.parse(e[n],o),o,0)}}));return Promise.resolve()}set(t){let e={};if(typeof t==="string"){e.main=t}else{e=t}if(!this._checkIfRootsExists(Object.keys(e))){throw new ss["a"]("datacontroller-set-non-existent-root",this)}this.model.enqueueChange("transparent",(t=>{t.setSelection(null);t.removeSelectionAttribute(this.model.document.selection.getAttributeKeys());for(const n of Object.keys(e)){const o=this.model.document.getRoot(n);t.remove(t.createRangeIn(o));t.insert(this.parse(e[n],o),o,0)}}))}parse(t,e="$root"){const n=this.processor.toView(t);return this.toModel(n,e)}toModel(t,e="$root"){return this.model.change((n=>this.upcastDispatcher.convert(t,n,e)))}addStyleProcessorRules(t){t(this.stylesProcessor)}destroy(){this.stopListening()}_checkIfRootsExists(t){for(const e of t){if(!this.model.document.getRootNames().includes(e)){return false}}return true}}_s(ng,Jc);function og(t){const e=[];const n=t.root.document;if(!n){return[]}const o=ef._createIn(t);for(const t of n.model.markers){const n=o.getIntersection(t.getRange());if(n){e.push([t.name,n])}}return e}class ig{constructor(t,e){this._helpers=new Map;this._downcast=xs(t);this._createConversionHelpers({name:"downcast",dispatchers:this._downcast,isDowncast:true});this._upcast=xs(e);this._createConversionHelpers({name:"upcast",dispatchers:this._upcast,isDowncast:false})}addAlias(t,e){const n=this._downcast.includes(e);const o=this._upcast.includes(e);if(!o&&!n){throw new ss["a"]("conversion-add-alias-dispatcher-not-registered",this)}this._createConversionHelpers({name:t,dispatchers:[e],isDowncast:n})}for(t){if(!this._helpers.has(t)){throw new ss["a"]("conversion-for-unknown-group",this)}return this._helpers.get(t)}elementToElement(t){this.for("downcast").elementToElement(t);for(const{model:e,view:n}of rg(t)){this.for("upcast").elementToElement({model:e,view:n,converterPriority:t.converterPriority})}}attributeToElement(t){this.for("downcast").attributeToElement(t);for(const{model:e,view:n}of rg(t)){this.for("upcast").elementToAttribute({view:n,model:e,converterPriority:t.converterPriority})}}attributeToAttribute(t){this.for("downcast").attributeToAttribute(t);for(const{model:e,view:n}of rg(t)){this.for("upcast").attributeToAttribute({view:n,model:e})}}_createConversionHelpers({name:t,dispatchers:e,isDowncast:n}){if(this._helpers.has(t)){throw new ss["a"]("conversion-group-exists",this)}const o=n?new If(e):new um(e);this._helpers.set(t,o)}}function*rg(t){if(t.model.values){for(const e of t.model.values){const n={key:t.model.key,value:e};const o=t.view[e];const i=t.upcastAlso?t.upcastAlso[e]:undefined;yield*sg(n,o,i)}}else{yield*sg(t.model,t.view,t.upcastAlso)}}function*sg(t,e,n){yield{model:t,view:e};if(n){for(const e of xs(n)){yield{model:t,view:e}}}}class ag{constructor(t="default"){this.operations=[];this.type=t}get baseVersion(){for(const t of this.operations){if(t.baseVersion!==null){return t.baseVersion}}return null}addOperation(t){t.batch=this;this.operations.push(t);return t}}class cg{constructor(t){this.baseVersion=t;this.isDocumentOperation=this.baseVersion!==null;this.batch=null}_validate(){}toJSON(){const t=Object.assign({},this);t.__className=this.constructor.className;delete t.batch;delete t.isDocumentOperation;return t}static get className(){return"Operation"}static fromJSON(t){return new this(t.baseVersion)}}class lg{constructor(t){this.markers=new Map;this._children=new Wh;if(t){this._insertChild(0,t)}}[Symbol.iterator](){return this.getChildren()}get childCount(){return this._children.length}get maxOffset(){return this._children.maxOffset}get isEmpty(){return this.childCount===0}get root(){return this}get parent(){return null}is(t){return t==="documentFragment"||t==="model:documentFragment"}getChild(t){return this._children.getNode(t)}getChildren(){return this._children[Symbol.iterator]()}getChildIndex(t){return this._children.getNodeIndex(t)}getChildStartOffset(t){return this._children.getNodeStartOffset(t)}getPath(){return[]}getNodeByPath(t){let e=this;for(const n of t){e=e.getChild(e.offsetToIndex(n))}return e}offsetToIndex(t){return this._children.offsetToIndex(t)}toJSON(){const t=[];for(const e of this._children){t.push(e.toJSON())}return t}static fromJSON(t){const e=[];for(const n of t){if(n.name){e.push(qh.fromJSON(n))}else{e.push(Gh.fromJSON(n))}}return new lg(e)}_appendChild(t){this._insertChild(this.childCount,t)}_insertChild(t,e){const n=dg(e);for(const t of n){if(t.parent!==null){t._remove()}t.parent=this}this._children._insertNodes(t,n)}_removeChildren(t,e=1){const n=this._children._removeNodes(t,e);for(const t of n){t.parent=null}return n}}function dg(t){if(typeof t=="string"){return[new Gh(t)]}if(!As(t)){t=[t]}return Array.from(t).map((t=>{if(typeof t=="string"){return new Gh(t)}if(t instanceof Kh){return new Gh(t.data,t.getAttributes())}return t}))}function ug(t,e){e=gg(e);const n=e.reduce(((t,e)=>t+e.offsetSize),0);const o=t.parent;kg(t);const i=t.index;o._insertChild(i,e);pg(o,i+e.length);pg(o,i);return new ef(t,t.getShiftedBy(n))}function hg(t){if(!t.isFlat){throw new ss["a"]("operation-utils-remove-range-not-flat",this)}const e=t.start.parent;kg(t.start);kg(t.end);const n=e._removeChildren(t.start.index,t.end.index-t.start.index);pg(e,t.start.index);return n}function fg(t,e){if(!t.isFlat){throw new ss["a"]("operation-utils-move-range-not-flat",this)}const n=hg(t);e=e._getTransformedByDeletion(t.start,t.end.offset-t.start.offset);return ug(e,n)}function mg(t,e,n){kg(t.start);kg(t.end);for(const o of t.getItems({shallow:true})){const t=o.is("$textProxy")?o.textNode:o;if(n!==null){t._setAttribute(e,n)}else{t._removeAttribute(e)}pg(t.parent,t.index)}pg(t.end.parent,t.end.index)}function gg(t){const e=[];if(!(t instanceof Array)){t=[t]}for(let n=0;nt.maxOffset){throw new ss["a"]("move-operation-nodes-do-not-exist",this)}else if(t===e&&n=n&&this.targetPosition.path[t]t._clone(true))));const e=new yg(this.position,t,this.baseVersion);e.shouldReceiveAttributes=this.shouldReceiveAttributes;return e}getReversed(){const t=this.position.root.document.graveyard;const e=new Jh(t,[0]);return new vg(this.position,this.nodes.maxOffset,e,this.baseVersion+1)}_validate(){const t=this.position.parent;if(!t||t.maxOffsett._clone(true))));ug(this.position,t)}toJSON(){const t=super.toJSON();t.position=this.position.toJSON();t.nodes=this.nodes.toJSON();return t}static get className(){return"InsertOperation"}static fromJSON(t,e){const n=[];for(const e of t.nodes){if(e.name){n.push(qh.fromJSON(e))}else{n.push(Gh.fromJSON(e))}}const o=new yg(Jh.fromJSON(t.position,e),n,t.baseVersion);o.shouldReceiveAttributes=t.shouldReceiveAttributes;return o}}class xg extends cg{constructor(t,e,n,o,i,r){super(r);this.name=t;this.oldRange=e?e.clone():null;this.newRange=n?n.clone():null;this.affectsData=i;this._markers=o}get type(){return"marker"}clone(){return new xg(this.name,this.oldRange,this.newRange,this._markers,this.affectsData,this.baseVersion)}getReversed(){return new xg(this.name,this.newRange,this.oldRange,this._markers,this.affectsData,this.baseVersion+1)}_execute(){const t=this.newRange?"_set":"_remove";this._markers[t](this.name,this.newRange,true,this.affectsData)}toJSON(){const t=super.toJSON();if(this.oldRange){t.oldRange=this.oldRange.toJSON()}if(this.newRange){t.newRange=this.newRange.toJSON()}delete t._markers;return t}static get className(){return"MarkerOperation"}static fromJSON(t,e){return new xg(t.name,t.oldRange?ef.fromJSON(t.oldRange,e):null,t.newRange?ef.fromJSON(t.newRange,e):null,e.model.markers,t.affectsData,t.baseVersion)}}class Dg extends cg{constructor(t,e,n,o){super(o);this.position=t;this.position.stickiness="toNext";this.oldName=e;this.newName=n}get type(){return"rename"}clone(){return new Dg(this.position.clone(),this.oldName,this.newName,this.baseVersion)}getReversed(){return new Dg(this.position.clone(),this.newName,this.oldName,this.baseVersion+1)}_validate(){const t=this.position.nodeAfter;if(!(t instanceof qh)){throw new ss["a"]("rename-operation-wrong-position",this)}else if(t.name!==this.oldName){throw new ss["a"]("rename-operation-wrong-name",this)}}_execute(){const t=this.position.nodeAfter;t.name=this.newName}toJSON(){const t=super.toJSON();t.position=this.position.toJSON();return t}static get className(){return"RenameOperation"}static fromJSON(t,e){return new Dg(Jh.fromJSON(t.position,e),t.oldName,t.newName,t.baseVersion)}}class Eg extends cg{constructor(t,e,n,o,i){super(i);this.root=t;this.key=e;this.oldValue=n;this.newValue=o}get type(){if(this.oldValue===null){return"addRootAttribute"}else if(this.newValue===null){return"removeRootAttribute"}else{return"changeRootAttribute"}}clone(){return new Eg(this.root,this.key,this.oldValue,this.newValue,this.baseVersion)}getReversed(){return new Eg(this.root,this.key,this.newValue,this.oldValue,this.baseVersion+1)}_validate(){if(this.root!=this.root.root||this.root.is("documentFragment")){throw new ss["a"]("rootattribute-operation-not-a-root",this,{root:this.root,key:this.key})}if(this.oldValue!==null&&this.root.getAttribute(this.key)!==this.oldValue){throw new ss["a"]("rootattribute-operation-wrong-old-value",this,{root:this.root,key:this.key})}if(this.oldValue===null&&this.newValue!==null&&this.root.hasAttribute(this.key)){throw new ss["a"]("rootattribute-operation-attribute-exists",this,{root:this.root,key:this.key})}}_execute(){if(this.newValue!==null){this.root._setAttribute(this.key,this.newValue)}else{this.root._removeAttribute(this.key)}}toJSON(){const t=super.toJSON();t.root=this.root.toJSON();return t}static get className(){return"RootAttributeOperation"}static fromJSON(t,e){if(!e.getRoot(t.root)){throw new ss["a"]("rootattribute-operation-fromjson-no-root",this,{rootName:t.root})}return new Eg(e.getRoot(t.root),t.key,t.oldValue,t.newValue,t.baseVersion)}}class Mg extends cg{constructor(t,e,n,o,i){super(i);this.sourcePosition=t.clone();this.sourcePosition.stickiness="toPrevious";this.howMany=e;this.targetPosition=n.clone();this.targetPosition.stickiness="toNext";this.graveyardPosition=o.clone()}get type(){return"merge"}get deletionPosition(){return new Jh(this.sourcePosition.root,this.sourcePosition.path.slice(0,-1))}get movedRange(){const t=this.sourcePosition.getShiftedBy(Number.POSITIVE_INFINITY);return new ef(this.sourcePosition,t)}clone(){return new this.constructor(this.sourcePosition,this.howMany,this.targetPosition,this.graveyardPosition,this.baseVersion)}getReversed(){const t=this.targetPosition._getTransformedByMergeOperation(this);const e=this.sourcePosition.path.slice(0,-1);const n=new Jh(this.sourcePosition.root,e)._getTransformedByMergeOperation(this);const o=new Tg(t,this.howMany,this.graveyardPosition,this.baseVersion+1);o.insertionPosition=n;return o}_validate(){const t=this.sourcePosition.parent;const e=this.targetPosition.parent;if(!t.parent){throw new ss["a"]("merge-operation-source-position-invalid",this)}else if(!e.parent){throw new ss["a"]("merge-operation-target-position-invalid",this)}else if(this.howMany!=t.maxOffset){throw new ss["a"]("merge-operation-how-many-invalid",this)}}_execute(){const t=this.sourcePosition.parent;const e=ef._createIn(t);fg(e,this.targetPosition);fg(ef._createOn(t),this.graveyardPosition)}toJSON(){const t=super.toJSON();t.sourcePosition=t.sourcePosition.toJSON();t.targetPosition=t.targetPosition.toJSON();t.graveyardPosition=t.graveyardPosition.toJSON();return t}static get className(){return"MergeOperation"}static fromJSON(t,e){const n=Jh.fromJSON(t.sourcePosition,e);const o=Jh.fromJSON(t.targetPosition,e);const i=Jh.fromJSON(t.graveyardPosition,e);return new this(n,t.howMany,o,i,t.baseVersion)}}class Tg extends cg{constructor(t,e,n,o){super(o);this.splitPosition=t.clone();this.splitPosition.stickiness="toNext";this.howMany=e;this.insertionPosition=Tg.getInsertionPosition(t);this.insertionPosition.stickiness="toNone";this.graveyardPosition=n?n.clone():null;if(this.graveyardPosition){this.graveyardPosition.stickiness="toNext"}}get type(){return"split"}get moveTargetPosition(){const t=this.insertionPosition.path.slice();t.push(0);return new Jh(this.insertionPosition.root,t)}get movedRange(){const t=this.splitPosition.getShiftedBy(Number.POSITIVE_INFINITY);return new ef(this.splitPosition,t)}clone(){const t=new this.constructor(this.splitPosition,this.howMany,this.graveyardPosition,this.baseVersion);t.insertionPosition=this.insertionPosition;return t}getReversed(){const t=this.splitPosition.root.document.graveyard;const e=new Jh(t,[0]);return new Mg(this.moveTargetPosition,this.howMany,this.splitPosition,e,this.baseVersion+1)}_validate(){const t=this.splitPosition.parent;const e=this.splitPosition.offset;if(!t||t.maxOffset{for(const e of t.getAttributeKeys()){this.removeAttribute(e,t)}};if(!(t instanceof ef)){e(t)}else{for(const n of t.getItems()){e(n)}}}move(t,e,n){this._assertWriterUsedCorrectly();if(!(t instanceof ef)){throw new ss["a"]("writer-move-invalid-range",this)}if(!t.isFlat){throw new ss["a"]("writer-move-range-not-flat",this)}const o=Jh._createAt(e,n);if(o.isEqual(t.start)){return}this._addOperationForAffectedMarkers("move",t);if(!Lg(t.root,o.root)){throw new ss["a"]("writer-move-different-document",this)}const i=t.root.document?t.root.document.version:null;const r=new vg(t.start,t.end.offset-t.start.offset,o,i);this.batch.addOperation(r);this.model.applyOperation(r)}remove(t){this._assertWriterUsedCorrectly();const e=t instanceof ef?t:ef._createOn(t);const n=e.getMinimalFlatRanges().reverse();for(const t of n){this._addOperationForAffectedMarkers("move",t);zg(t.start,t.end.offset-t.start.offset,this.batch,this.model)}}merge(t){this._assertWriterUsedCorrectly();const e=t.nodeBefore;const n=t.nodeAfter;this._addOperationForAffectedMarkers("merge",t);if(!(e instanceof qh)){throw new ss["a"]("writer-merge-no-element-before",this)}if(!(n instanceof qh)){throw new ss["a"]("writer-merge-no-element-after",this)}if(!t.root.document){this._mergeDetached(t)}else{this._merge(t)}}createPositionFromPath(t,e,n){return this.model.createPositionFromPath(t,e,n)}createPositionAt(t,e){return this.model.createPositionAt(t,e)}createPositionAfter(t){return this.model.createPositionAfter(t)}createPositionBefore(t){return this.model.createPositionBefore(t)}createRange(t,e){return this.model.createRange(t,e)}createRangeIn(t){return this.model.createRangeIn(t)}createRangeOn(t){return this.model.createRangeOn(t)}createSelection(t,e,n){return this.model.createSelection(t,e,n)}_mergeDetached(t){const e=t.nodeBefore;const n=t.nodeAfter;this.move(ef._createIn(n),Jh._createAt(e,"end"));this.remove(n)}_merge(t){const e=Jh._createAt(t.nodeBefore,"end");const n=Jh._createAt(t.nodeAfter,0);const o=t.root.document.graveyard;const i=new Jh(o,[0]);const r=t.root.document.version;const s=new Mg(n,t.nodeAfter.maxOffset,e,i,r);this.batch.addOperation(s);this.model.applyOperation(s)}rename(t,e){this._assertWriterUsedCorrectly();if(!(t instanceof qh)){throw new ss["a"]("writer-rename-not-element-instance",this)}const n=t.root.document?t.root.document.version:null;const o=new Dg(Jh._createBefore(t),t.name,e,n);this.batch.addOperation(o);this.model.applyOperation(o)}split(t,e){this._assertWriterUsedCorrectly();let n=t.parent;if(!n.parent){throw new ss["a"]("writer-split-element-no-parent",this)}if(!e){e=n.parent}if(!t.parent.getAncestors({includeSelf:true}).includes(e)){throw new ss["a"]("writer-split-invalid-limit-element",this)}let o,i;do{const e=n.root.document?n.root.document.version:null;const r=n.maxOffset-t.offset;const s=new Tg(t,r,null,e);this.batch.addOperation(s);this.model.applyOperation(s);if(!o&&!i){o=n;i=t.parent.nextSibling}t=this.createPositionAfter(t.parent);n=t.parent}while(n!==e);return{position:t,range:new ef(Jh._createAt(o,"end"),Jh._createAt(i,0))}}wrap(t,e){this._assertWriterUsedCorrectly();if(!t.isFlat){throw new ss["a"]("writer-wrap-range-not-flat",this)}const n=e instanceof qh?e:new qh(e);if(n.childCount>0){throw new ss["a"]("writer-wrap-element-not-empty",this)}if(n.parent!==null){throw new ss["a"]("writer-wrap-element-attached",this)}this.insert(n,t.start);const o=new ef(t.start.getShiftedBy(1),t.end.getShiftedBy(1));this.move(o,Jh._createAt(n,0))}unwrap(t){this._assertWriterUsedCorrectly();if(t.parent===null){throw new ss["a"]("writer-unwrap-element-no-parent",this)}this.move(ef._createIn(t),this.createPositionAfter(t));this.remove(t)}addMarker(t,e){this._assertWriterUsedCorrectly();if(!e||typeof e.usingOperation!="boolean"){throw new ss["a"]("writer-addmarker-no-usingoperation",this)}const n=e.usingOperation;const o=e.range;const i=e.affectsData===undefined?false:e.affectsData;if(this.model.markers.has(t)){throw new ss["a"]("writer-addmarker-marker-exists",this)}if(!o){throw new ss["a"]("writer-addmarker-no-range",this)}if(!n){return this.model.markers._set(t,o,n,i)}Pg(this,t,null,o,i);return this.model.markers.get(t)}updateMarker(t,e){this._assertWriterUsedCorrectly();const n=typeof t=="string"?t:t.name;const o=this.model.markers.get(n);if(!o){throw new ss["a"]("writer-updatemarker-marker-not-exists",this)}if(!e){this.model.markers._refresh(o);return}const i=typeof e.usingOperation=="boolean";const r=typeof e.affectsData=="boolean";const s=r?e.affectsData:o.affectsData;if(!i&&!e.range&&!r){throw new ss["a"]("writer-updatemarker-wrong-options",this)}const a=o.getRange();const c=e.range?e.range:a;if(i&&e.usingOperation!==o.managedUsingOperations){if(e.usingOperation){Pg(this,n,null,c,s)}else{Pg(this,n,a,null,s);this.model.markers._set(n,c,undefined,s)}return}if(o.managedUsingOperations){Pg(this,n,a,c,s)}else{this.model.markers._set(n,c,undefined,s)}}removeMarker(t){this._assertWriterUsedCorrectly();const e=typeof t=="string"?t:t.name;if(!this.model.markers.has(e)){throw new ss["a"]("writer-removemarker-no-marker",this)}const n=this.model.markers.get(e);if(!n.managedUsingOperations){this.model.markers._remove(e);return}const o=n.getRange();Pg(this,e,o,null,n.affectsData)}setSelection(t,e,n){this._assertWriterUsedCorrectly();this.model.document.selection._setTo(t,e,n)}setSelectionFocus(t,e){this._assertWriterUsedCorrectly();this.model.document.selection._setFocus(t,e)}setSelectionAttribute(t,e){this._assertWriterUsedCorrectly();if(typeof t==="string"){this._setSelectionAttribute(t,e)}else{for(const[e,n]of Gs(t)){this._setSelectionAttribute(e,n)}}}removeSelectionAttribute(t){this._assertWriterUsedCorrectly();if(typeof t==="string"){this._removeSelectionAttribute(t)}else{for(const e of t){this._removeSelectionAttribute(e)}}}overrideSelectionGravity(){return this.model.document.selection._overrideGravity()}restoreSelectionGravity(t){this.model.document.selection._restoreGravity(t)}_setSelectionAttribute(t,e){const n=this.model.document.selection;if(n.isCollapsed&&n.anchor.parent.isEmpty){const o=_f._getStoreAttributeKey(t);this.setAttribute(o,e,n.anchor.parent)}n._setAttribute(t,e)}_removeSelectionAttribute(t){const e=this.model.document.selection;if(e.isCollapsed&&e.anchor.parent.isEmpty){const n=_f._getStoreAttributeKey(t);this.removeAttribute(n,e.anchor.parent)}e._removeAttribute(t)}_assertWriterUsedCorrectly(){if(this.model._currentWriter!==this){throw new ss["a"]("writer-incorrect-use",this)}}_addOperationForAffectedMarkers(t,e){for(const n of this.model.markers){if(!n.managedUsingOperations){continue}const o=n.getRange();let i=false;if(t==="move"){i=e.containsPosition(o.start)||e.start.isEqual(o.start)||e.containsPosition(o.end)||e.end.isEqual(o.end)}else{const t=e.nodeBefore;const n=e.nodeAfter;const r=o.start.parent==t&&o.start.isAtEnd;const s=o.end.parent==n&&o.end.offset==0;const a=o.end.nodeAfter==n;const c=o.start.nodeAfter==n;i=r||s||a||c}if(i){this.updateMarker(n.name,{range:o})}}}}function Ng(t,e,n,o){const i=t.model;const r=i.document;let s=o.start;let a;let c;let l;for(const t of o.getWalker({shallow:true})){l=t.item.getAttribute(e);if(a&&c!=l){if(c!=n){d()}s=a}a=t.nextPosition;c=l}if(a instanceof Jh&&a!=s&&c!=n){d()}function d(){const o=new ef(s,a);const l=o.root.document?r.version:null;const d=new Ag(o,e,c,n,l);t.batch.addOperation(d);i.applyOperation(d)}}function Bg(t,e,n,o){const i=t.model;const r=i.document;const s=o.getAttribute(e);let a,c;if(s!=n){const l=o.root===o;if(l){const t=o.document?r.version:null;c=new Eg(o,e,s,n,t)}else{a=new ef(Jh._createBefore(o),t.createPositionAfter(o));const i=a.root.document?r.version:null;c=new Ag(a,e,s,n,i)}t.batch.addOperation(c);i.applyOperation(c)}}function Pg(t,e,n,o,i){const r=t.model;const s=r.document;const a=new xg(e,n,o,r.markers,i,s.version);t.batch.addOperation(a);r.applyOperation(a)}function zg(t,e,n,o){let i;if(t.root.document){const n=o.document;const r=new Jh(n.graveyard,[0]);i=new vg(t,e,r,n.version)}else{i=new _g(t,e)}n.addOperation(i);o.applyOperation(i)}function Lg(t,e){if(t===e){return true}if(t instanceof Sg&&e instanceof Sg){return true}return false}class Og{constructor(t){this._markerCollection=t;this._changesInElement=new Map;this._elementSnapshots=new Map;this._changedMarkers=new Map;this._changeCount=0;this._cachedChanges=null;this._cachedChangesWithGraveyard=null}get isEmpty(){return this._changesInElement.size==0&&this._changedMarkers.size==0}refreshItem(t){if(this._isInInsertedElement(t.parent)){return}this._markRemove(t.parent,t.startOffset,t.offsetSize);this._markInsert(t.parent,t.startOffset,t.offsetSize);const e=ef._createOn(t);for(const t of this._markerCollection.getMarkersIntersectingRange(e)){const e=t.getRange();this.bufferMarkerChange(t.name,e,e,t.affectsData)}this._cachedChanges=null}bufferOperation(t){switch(t.type){case"insert":{if(this._isInInsertedElement(t.position.parent)){return}this._markInsert(t.position.parent,t.position.offset,t.nodes.maxOffset);break}case"addAttribute":case"removeAttribute":case"changeAttribute":{for(const e of t.range.getItems({shallow:true})){if(this._isInInsertedElement(e.parent)){continue}this._markAttribute(e)}break}case"remove":case"move":case"reinsert":{if(t.sourcePosition.isEqual(t.targetPosition)||t.sourcePosition.getShiftedBy(t.howMany).isEqual(t.targetPosition)){return}const e=this._isInInsertedElement(t.sourcePosition.parent);const n=this._isInInsertedElement(t.targetPosition.parent);if(!e){this._markRemove(t.sourcePosition.parent,t.sourcePosition.offset,t.howMany)}if(!n){this._markInsert(t.targetPosition.parent,t.getMovedRangeStart().offset,t.howMany)}break}case"rename":{if(this._isInInsertedElement(t.position.parent)){return}this._markRemove(t.position.parent,t.position.offset,1);this._markInsert(t.position.parent,t.position.offset,1);const e=ef._createFromPositionAndShift(t.position,1);for(const t of this._markerCollection.getMarkersIntersectingRange(e)){const e=t.getRange();this.bufferMarkerChange(t.name,e,e,t.affectsData)}break}case"split":{const e=t.splitPosition.parent;if(!this._isInInsertedElement(e)){this._markRemove(e,t.splitPosition.offset,t.howMany)}if(!this._isInInsertedElement(t.insertionPosition.parent)){this._markInsert(t.insertionPosition.parent,t.insertionPosition.offset,1)}if(t.graveyardPosition){this._markRemove(t.graveyardPosition.parent,t.graveyardPosition.offset,1)}break}case"merge":{const e=t.sourcePosition.parent;if(!this._isInInsertedElement(e.parent)){this._markRemove(e.parent,e.startOffset,1)}const n=t.graveyardPosition.parent;this._markInsert(n,t.graveyardPosition.offset,1);const o=t.targetPosition.parent;if(!this._isInInsertedElement(o)){this._markInsert(o,t.targetPosition.offset,e.maxOffset)}break}}this._cachedChanges=null}bufferMarkerChange(t,e,n,o){const i=this._changedMarkers.get(t);if(!i){this._changedMarkers.set(t,{oldRange:e,newRange:n,affectsData:o})}else{i.newRange=n;i.affectsData=o;if(i.oldRange==null&&i.newRange==null){this._changedMarkers.delete(t)}}}getMarkersToRemove(){const t=[];for(const[e,n]of this._changedMarkers){if(n.oldRange!=null){t.push({name:e,range:n.oldRange})}}return t}getMarkersToAdd(){const t=[];for(const[e,n]of this._changedMarkers){if(n.newRange!=null){t.push({name:e,range:n.newRange})}}return t}getChangedMarkers(){return Array.from(this._changedMarkers).map((t=>({name:t[0],data:{oldRange:t[1].oldRange,newRange:t[1].newRange}})))}hasDataChanges(){for(const[,t]of this._changedMarkers){if(t.affectsData){return true}}return this._changesInElement.size>0}getChanges(t={includeChangesInGraveyard:false}){if(this._cachedChanges){if(t.includeChangesInGraveyard){return this._cachedChangesWithGraveyard.slice()}else{return this._cachedChanges.slice()}}const e=[];for(const t of this._changesInElement.keys()){const n=this._changesInElement.get(t).sort(((t,e)=>{if(t.offset===e.offset){if(t.type!=e.type){return t.type=="remove"?-1:1}return 0}return t.offset{if(t.position.root!=e.position.root){return t.position.root.rootNamen.offset){if(o>i){const t={type:"attribute",offset:i,howMany:o-i,count:this._changeCount++};this._handleChange(t,e);e.push(t)}t.nodesToHandle=n.offset-t.offset;t.howMany=t.nodesToHandle}else if(t.offset>=n.offset&&t.offseti){t.nodesToHandle=o-i;t.offset=i}else{t.nodesToHandle=0}}}if(n.type=="remove"){if(t.offsetn.offset){const i={type:"attribute",offset:n.offset,howMany:o-n.offset,count:this._changeCount++};this._handleChange(i,e);e.push(i);t.nodesToHandle=n.offset-t.offset;t.howMany=t.nodesToHandle}}if(n.type=="attribute"){if(t.offset>=n.offset&&o<=i){t.nodesToHandle=0;t.howMany=0;t.offset=0}else if(t.offset<=n.offset&&o>=i){n.howMany=0}}}}t.howMany=t.nodesToHandle;delete t.nodesToHandle}_getInsertDiff(t,e,n){return{type:"insert",position:Jh._createAt(t,e),name:n,length:1,changeCount:this._changeCount++}}_getRemoveDiff(t,e,n){return{type:"remove",position:Jh._createAt(t,e),name:n,length:1,changeCount:this._changeCount++}}_getAttributesDiff(t,e,n){const o=[];n=new Map(n);for(const[i,r]of e){const e=n.has(i)?n.get(i):null;if(e!==r){o.push({type:"attribute",position:t.start,range:t.clone(),length:1,attributeKey:i,attributeOldValue:r,attributeNewValue:e,changeCount:this._changeCount++})}n.delete(i)}for(const[e,i]of n){o.push({type:"attribute",position:t.start,range:t.clone(),length:1,attributeKey:e,attributeOldValue:null,attributeNewValue:i,changeCount:this._changeCount++})}return o}_isInInsertedElement(t){const e=t.parent;if(!e){return false}const n=this._changesInElement.get(e);const o=t.startOffset;if(n){for(const t of n){if(t.type=="insert"&&o>=t.offset&&oo){for(let e=0;e=t&&o.baseVersion{const n=e[0];if(n.isDocumentOperation&&n.baseVersion!==this.version){throw new ss["a"]("model-document-applyoperation-wrong-version",this,{operation:n})}}),{priority:"highest"});this.listenTo(t,"applyOperation",((t,e)=>{const n=e[0];if(n.isDocumentOperation){this.differ.bufferOperation(n)}}),{priority:"high"});this.listenTo(t,"applyOperation",((t,e)=>{const n=e[0];if(n.isDocumentOperation){this.version++;this.history.addOperation(n)}}),{priority:"low"});this.listenTo(this.selection,"change",(()=>{this._hasSelectionChangedFromTheLastChangeBlock=true}));this.listenTo(t.markers,"update",((t,e,n,o)=>{this.differ.bufferMarkerChange(e.name,n,o,e.affectsData);if(n===null){e.on("change",((t,n)=>{this.differ.bufferMarkerChange(e.name,n,e.getRange(),e.affectsData)}))}}))}get graveyard(){return this.getRoot(qg)}createRoot(t="$root",e="main"){if(this.roots.get(e)){throw new ss["a"]("model-document-createroot-name-exists",this,{name:e})}const n=new Sg(this,t,e);this.roots.add(n);return n}destroy(){this.selection.destroy();this.stopListening()}getRoot(t="main"){return this.roots.get(t)}getRootNames(){return Array.from(this.roots,(t=>t.rootName)).filter((t=>t!=qg))}registerPostFixer(t){this._postFixers.add(t)}toJSON(){const t=js(this);t.selection="[engine.model.DocumentSelection]";t.model="[engine.model.Model]";return t}_handleChangeBlock(t){if(this._hasDocumentChangedFromTheLastChangeBlock()){this._callPostFixers(t);this.selection.refresh();if(this.differ.hasDataChanges()){this.fire("change:data",t.batch)}else{this.fire("change",t.batch)}this.selection.refresh();this.differ.reset()}this._hasSelectionChangedFromTheLastChangeBlock=false}_hasDocumentChangedFromTheLastChangeBlock(){return!this.differ.isEmpty||this._hasSelectionChangedFromTheLastChangeBlock}_getDefaultRoot(){for(const t of this.roots){if(t!==this.graveyard){return t}}return this.graveyard}_getDefaultRange(){const t=this._getDefaultRoot();const e=this.model;const n=e.schema;const o=e.createPositionFromPath(t,[0]);const i=n.getNearestSelectionRange(o);return i||e.createRange(o)}_validateSelectionRange(t){return Qg(t.start)&&Qg(t.end)}_callPostFixers(t){let e=false;do{for(const n of this._postFixers){this.selection.refresh();e=n(t);if(e){break}}}while(e)}}_s(Yg,ds);function Qg(t){const e=t.textNode;if(e){const n=e.data;const o=t.offset-e.startOffset;return!Kg(n,o)&&!Wg(n,o)}return true}class $g{constructor(){this._markers=new Map}[Symbol.iterator](){return this._markers.values()}has(t){return this._markers.has(t)}get(t){return this._markers.get(t)||null}_set(t,e,n=false,o=false){const i=t instanceof Jg?t.name:t;if(i.includes(",")){throw new ss["a"]("markercollection-incorrect-marker-name",this)}const r=this._markers.get(i);if(r){const t=r.getRange();let s=false;if(!t.isEqual(e)){r._attachLiveRange(kf.fromRange(e));s=true}if(n!=r.managedUsingOperations){r._managedUsingOperations=n;s=true}if(typeof o==="boolean"&&o!=r.affectsData){r._affectsData=o;s=true}if(s){this.fire("update:"+i,r,t,e)}return r}const s=kf.fromRange(e);const a=new Jg(i,s,n,o);this._markers.set(i,a);this.fire("update:"+i,a,null,e);return a}_remove(t){const e=t instanceof Jg?t.name:t;const n=this._markers.get(e);if(n){this._markers.delete(e);this.fire("update:"+e,n,n.getRange(),null);this._destroyMarker(n);return true}return false}_refresh(t){const e=t instanceof Jg?t.name:t;const n=this._markers.get(e);if(!n){throw new ss["a"]("markercollection-refresh-marker-not-exists",this)}const o=n.getRange();this.fire("update:"+e,n,o,o,n.managedUsingOperations,n.affectsData)}*getMarkersAtPosition(t){for(const e of this){if(e.getRange().containsPosition(t)){yield e}}}*getMarkersIntersectingRange(t){for(const e of this){if(e.getRange().getIntersection(t)!==null){yield e}}}destroy(){for(const t of this._markers.values()){this._destroyMarker(t)}this._markers=null;this.stopListening()}*getMarkersGroup(t){for(const e of this._markers.values()){if(e.name.startsWith(t+":")){yield e}}}_destroyMarker(t){t.stopListening();t._detachLiveRange()}}_s($g,ds);class Jg{constructor(t,e,n,o){this.name=t;this._liveRange=this._attachLiveRange(e);this._managedUsingOperations=n;this._affectsData=o}get managedUsingOperations(){if(!this._liveRange){throw new ss["a"]("marker-destroyed",this)}return this._managedUsingOperations}get affectsData(){if(!this._liveRange){throw new ss["a"]("marker-destroyed",this)}return this._affectsData}getStart(){if(!this._liveRange){throw new ss["a"]("marker-destroyed",this)}return this._liveRange.start.clone()}getEnd(){if(!this._liveRange){throw new ss["a"]("marker-destroyed",this)}return this._liveRange.end.clone()}getRange(){if(!this._liveRange){throw new ss["a"]("marker-destroyed",this)}return this._liveRange.toRange()}is(t){return t==="marker"||t==="model:marker"}_attachLiveRange(t){if(this._liveRange){this._detachLiveRange()}t.delegate("change:range").to(this);t.delegate("change:content").to(this);this._liveRange=t;return t}_detachLiveRange(){this._liveRange.stopDelegating("change:range",this);this._liveRange.stopDelegating("change:content",this);this._liveRange.detach();this._liveRange=null}}_s(Jg,ds);class Zg extends cg{get type(){return"noop"}clone(){return new Zg(this.baseVersion)}getReversed(){return new Zg(this.baseVersion+1)}_execute(){}static get className(){return"NoOperation"}}const Xg={};Xg[Ag.className]=Ag;Xg[yg.className]=yg;Xg[xg.className]=xg;Xg[vg.className]=vg;Xg[Zg.className]=Zg;Xg[cg.className]=cg;Xg[Dg.className]=Dg;Xg[Eg.className]=Eg;Xg[Tg.className]=Tg;Xg[Mg.className]=Mg;class tp{static fromJSON(t,e){return Xg[t.__className].fromJSON(t,e)}}class ep extends Jh{constructor(t,e,n="toNone"){super(t,e,n);if(!this.root.is("rootElement")){throw new ss["a"]("model-liveposition-root-not-rootelement",t)}np.call(this)}detach(){this.stopListening()}is(t){return t==="livePosition"||t==="model:livePosition"||t=="position"||t==="model:position"}toPosition(){return new Jh(this.root,this.path.slice(),this.stickiness)}static fromPosition(t,e){return new this(t.root,t.path.slice(),e?e:t.stickiness)}}function np(){this.listenTo(this.root.document.model,"applyOperation",((t,e)=>{const n=e[0];if(!n.isDocumentOperation){return}op.call(this,n)}),{priority:"low"})}function op(t){const e=this.getTransformedByOperation(t);if(!this.isEqual(e)){const t=this.toPosition();this.path=e.path;this.root=e.root;this.fire("change",t)}}_s(ep,ds);function ip(t,e,n,o){return t.change((i=>{let r;if(!n){r=t.document.selection}else if(n instanceof uf||n instanceof _f){r=n}else{r=i.createSelection(n,o)}if(!r.isCollapsed){t.deleteContent(r,{doNotAutoparagraph:true})}const s=new rp(t,i,r.anchor);let a;if(e.is("documentFragment")){a=e.getChildren()}else{a=[e]}s.handleNodes(a,{isFirst:true,isLast:true});const c=s.getSelectionRange();if(c){if(r instanceof _f){i.setSelection(c)}else{r.setTo(c)}}else{}const l=s.getAffectedRange()||t.createRange(r.anchor);s.destroy();return l}))}class rp{constructor(t,e,n){this.model=t;this.writer=e;this.position=n;this.canMergeWith=new Set([this.position.parent]);this.schema=t.schema;this._filterAttributesOf=[];this._affectedStart=null;this._affectedEnd=null}handleNodes(t,e){t=Array.from(t);for(let n=0;n{if(!n.doNotResetEntireContent&&wp(i,e)){bp(t,e,i);return}const[r,s]=ap(o);if(!r.isTouching(s)){t.remove(t.createRange(r,s))}if(!n.leaveUnmerged){lp(t,r,s);i.removeDisallowedAttributes(r.parent.getChildren(),t)}Cp(t,e,r);if(!n.doNotAutoparagraph&&gp(i,r)){kp(t,r,e)}r.detach();s.detach()}))}function ap(t){const e=t.root.document.model;const n=t.start;let o=t.end;if(e.hasContent(t,{ignoreMarkers:true})){const n=cp(o);if(n&&o.isTouching(e.createPositionAt(n,0))){const n=e.createSelection(t);e.modifySelection(n,{direction:"backward"});o=n.getLastPosition()}}return[ep.fromPosition(n,"toPrevious"),ep.fromPosition(o,"toNext")]}function cp(t){const e=t.parent;const n=e.root.document.model.schema;const o=e.getAncestors({parentFirst:true,includeSelf:true});for(const t of o){if(n.isLimit(t)){return null}if(n.isBlock(t)){return t}}}function lp(t,e,n){const o=t.model;if(!fp(t.model.schema,e,n)){return}const[i,r]=mp(e,n);if(!i||!r){return}if(!o.hasContent(i,{ignoreMarkers:true})&&o.hasContent(r,{ignoreMarkers:true})){up(t,e,n,i.parent)}else{dp(t,e,n,i.parent)}}function dp(t,e,n,o){const i=e.parent;const r=n.parent;if(i==o||r==o){return}e=t.createPositionAfter(i);n=t.createPositionBefore(r);if(!n.isEqual(e)){t.insert(r,e)}t.merge(e);while(n.parent.isEmpty){const e=n.parent;n=t.createPositionBefore(e);t.remove(e)}if(!fp(t.model.schema,e,n)){return}dp(t,e,n,o)}function up(t,e,n,o){const i=e.parent;const r=n.parent;if(i==o||r==o){return}e=t.createPositionAfter(i);n=t.createPositionBefore(r);if(!n.isEqual(e)){t.insert(i,n)}while(e.parent.isEmpty){const n=e.parent;e=t.createPositionBefore(n);t.remove(n)}n=t.createPositionBefore(r);hp(t,n);if(!fp(t.model.schema,e,n)){return}up(t,e,n,o)}function hp(t,e){const n=e.nodeBefore;const o=e.nodeAfter;if(n.name!=o.name){t.rename(n,o.name)}t.clearAttributes(n);t.setAttributes(Object.fromEntries(o.getAttributes()),n);t.merge(e)}function fp(t,e,n){const o=e.parent;const i=n.parent;if(o==i){return false}if(t.isLimit(o)||t.isLimit(i)){return false}return pp(e,n,t)}function mp(t,e){const n=t.getAncestors();const o=e.getAncestors();let i=0;while(n[i]&&n[i]==o[i]){i++}return[n[i],o[i]]}function gp(t,e){const n=t.checkChild(e,"$text");const o=t.checkChild(e,"paragraph");return!n&&o}function pp(t,e,n){const o=new ef(t,e);for(const t of o.getWalker()){if(n.isLimit(t.item)){return false}}return true}function kp(t,e,n){const o=t.createElement("paragraph");t.insert(o,e);Cp(t,n,t.createPositionAt(o,0))}function bp(t,e){const n=t.model.schema.getLimitElement(e);t.remove(t.createRangeIn(n));kp(t,t.createPositionAt(n,0),e)}function wp(t,e){const n=t.getLimitElement(e);if(!e.containsEntireContent(n)){return false}const o=e.getFirstRange();if(o.start.parent==o.end.parent){return false}return t.checkChild(n,"paragraph")}function Cp(t,e,n){if(e instanceof _f){t.setSelection(n)}else{e.setTo(n)}}const Ap=' ,.?!:;"-()';function _p(t,e,n={}){const o=t.schema;const i=n.direction!="backward";const r=n.unit?n.unit:"character";const s=e.focus;const a=new Qh({boundaries:Dp(s,i),singleCharacters:true,direction:i?"forward":"backward"});const c={walker:a,schema:o,isForward:i,unit:r};let l;while(l=a.next()){if(l.done){return}const n=vp(c,l.value);if(n){if(e instanceof _f){t.change((t=>{t.setSelectionFocus(n)}))}else{e.setFocus(n)}return}}}function vp(t,e){const{isForward:n,walker:o,unit:i,schema:r}=t;const{type:s,item:a,nextPosition:c}=e;if(s=="text"){if(t.unit==="word"){return xp(o,n)}return yp(o,i,n)}if(s==(n?"elementStart":"elementEnd")){if(r.isSelectable(a)){return Jh._createAt(a,n?"after":"before")}if(r.checkChild(c,"$text")){return c}}else{if(r.isLimit(a)){o.skip((()=>true));return}if(r.checkChild(c,"$text")){return c}}}function yp(t,e){const n=t.position.textNode;if(n){const o=n.data;let i=t.position.offset-n.startOffset;while(Kg(o,i)||e=="character"&&Wg(o,i)){t.next();i=t.position.offset-n.startOffset}}return t.position}function xp(t,e){let n=t.position.textNode;if(n){let o=t.position.offset-n.startOffset;while(!Ep(n.data,o,e)&&!Mp(n,o,e)){t.next();const i=e?t.position.nodeAfter:t.position.nodeBefore;if(i&&i.is("$text")){const o=i.data.charAt(e?0:i.data.length-1);if(!Ap.includes(o)){t.next();n=t.position.textNode}}o=t.position.offset-n.startOffset}}return t.position}function Dp(t,e){const n=t.root;const o=Jh._createAt(n,e?"end":0);if(e){return new ef(t,o)}else{return new ef(o,t)}}function Ep(t,e,n){const o=e+(n?0:-1);return Ap.includes(t.charAt(o))}function Mp(t,e,n){return e===(n?t.endOffset:0)}function Tp(t,e){return t.change((t=>{const n=t.createDocumentFragment();const o=e.getFirstRange();if(!o||o.isCollapsed){return n}const i=o.start.root;const r=o.start.getCommonPath(o.end);const s=i.getNodeByPath(r);let a;if(o.start.parent==o.end.parent){a=o}else{a=t.createRange(t.createPositionAt(s,o.start.path[r.length]),t.createPositionAt(s,o.end.path[r.length]+1))}const c=a.end.offset-a.start.offset;for(const e of a.getItems({shallow:true})){if(e.is("$textProxy")){t.appendText(e.data,e.getAttributes(),n)}else{t.append(t.cloneElement(e,true),n)}}if(a!=o){const e=o._getTransformedByMove(a.start,t.createPositionAt(n,0),c)[0];const i=t.createRange(t.createPositionAt(n,0),e.start);const r=t.createRange(e.end,t.createPositionAt(n,"end"));Sp(r,t);Sp(i,t)}return n}))}function Sp(t,e){const n=[];Array.from(t.getItems({direction:"backward"})).map((t=>e.createRangeOn(t))).filter((e=>{const n=(e.start.isAfter(t.start)||e.start.isEqual(t.start))&&(e.end.isBefore(t.end)||e.end.isEqual(t.end));return n})).forEach((t=>{n.push(t.start.parent);e.remove(t)}));n.forEach((t=>{let n=t;while(n.parent&&n.isEmpty){const t=e.createRangeOn(n);n=n.parent;e.remove(t)}}))}function Ip(t){t.document.registerPostFixer((e=>Np(e,t)))}function Np(t,e){const n=e.document.selection;const o=e.schema;const i=[];let r=false;for(const t of n.getRanges()){const e=Bp(t,o);if(e&&!e.isEqual(t)){i.push(e);r=true}else{i.push(t)}}if(r){t.setSelection(Rp(i),{backward:n.isBackward})}}function Bp(t,e){if(t.isCollapsed){return Pp(t,e)}return zp(t,e)}function Pp(t,e){const n=t.start;const o=e.getNearestSelectionRange(n);if(!o){return null}if(!o.isCollapsed){return o}const i=o.start;if(n.isEqual(i)){return null}return new ef(i)}function zp(t,e){const{start:n,end:o}=t;const i=e.checkChild(n,"$text");const r=e.checkChild(o,"$text");const s=e.getLimitElement(n);const a=e.getLimitElement(o);if(s===a){if(i&&r){return null}if(Op(n,o,e)){const t=n.nodeAfter&&e.isSelectable(n.nodeAfter);const i=t?null:e.getNearestSelectionRange(n,"forward");const r=o.nodeBefore&&e.isSelectable(o.nodeBefore);const s=r?null:e.getNearestSelectionRange(o,"backward");const a=i?i.start:n;const c=s?s.end:o;return new ef(a,c)}}const c=s&&!s.is("rootElement");const l=a&&!a.is("rootElement");if(c||l){const t=n.nodeAfter&&o.nodeBefore&&n.nodeAfter.parent===o.nodeBefore.parent;const i=c&&(!t||!jp(n.nodeAfter,e));const r=l&&(!t||!jp(o.nodeBefore,e));let d=n;let u=o;if(i){d=Jh._createBefore(Lp(s,e))}if(r){u=Jh._createAfter(Lp(a,e))}return new ef(d,u)}return null}function Lp(t,e){let n=t;let o=n;while(e.isLimit(o)&&o.parent){n=o;o=o.parent}return n}function Op(t,e,n){const o=t.nodeAfter&&!n.isLimit(t.nodeAfter)||n.checkChild(t,"$text");const i=e.nodeBefore&&!n.isLimit(e.nodeBefore)||n.checkChild(e,"$text");return o||i}function Rp(t){const e=[];e.push(t.shift());for(const n of t){const t=e.pop();if(n.isEqual(t)){e.push(t)}else if(n.isIntersecting(t)){const o=t.start.isAfter(n.start)?n.start:t.start;const i=t.end.isAfter(n.end)?t.end:n.end;const r=new ef(o,i);e.push(r)}else{e.push(t);e.push(n)}}return e}function jp(t,e){return t&&e.isSelectable(t)}class Fp{constructor(){this.markers=new $g;this.document=new Yg(this);this.schema=new zm;this._pendingChanges=[];this._currentWriter=null;["insertContent","deleteContent","modifySelection","getSelectedContent","applyOperation"].forEach((t=>this.decorate(t)));this.on("applyOperation",((t,e)=>{const n=e[0];n._validate()}),{priority:"highest"});this.schema.register("$root",{isLimit:true});this.schema.register("$block",{allowIn:"$root",isBlock:true});this.schema.register("$text",{allowIn:"$block",isInline:true,isContent:true});this.schema.register("$clipboardHolder",{allowContentOf:"$root",isLimit:true});this.schema.extend("$text",{allowIn:"$clipboardHolder"});this.schema.register("$marker");this.schema.addChildCheck(((t,e)=>{if(e.name==="$marker"){return true}}));Ip(this);this.document.registerPostFixer(cm)}change(t){try{if(this._pendingChanges.length===0){this._pendingChanges.push({batch:new ag,callback:t});return this._runPendingChanges()[0]}else{return t(this._currentWriter)}}catch(t){ss["a"].rethrowUnexpectedError(t,this)}}enqueueChange(t,e){try{if(typeof t==="string"){t=new ag(t)}else if(typeof t=="function"){e=t;t=new ag}this._pendingChanges.push({batch:t,callback:e});if(this._pendingChanges.length==1){this._runPendingChanges()}}catch(t){ss["a"].rethrowUnexpectedError(t,this)}}applyOperation(t){t._execute()}insertContent(t,e,n){return ip(this,t,e,n)}deleteContent(t,e){sp(this,t,e)}modifySelection(t,e){_p(this,t,e)}getSelectedContent(t){return Tp(this,t)}hasContent(t,e={}){const n=t instanceof qh?ef._createIn(t):t;if(n.isCollapsed){return false}const{ignoreWhitespaces:o=false,ignoreMarkers:i=false}=e;if(!i){for(const t of this.markers.getMarkersIntersectingRange(n)){if(t.affectsData){return true}}}for(const t of n.getItems()){if(this.schema.isContent(t)){if(t.is("$textProxy")){if(!o){return true}else if(t.data.search(/\S/)!==-1){return true}}else{return true}}}return false}createPositionFromPath(t,e,n){return new Jh(t,e,n)}createPositionAt(t,e){return Jh._createAt(t,e)}createPositionAfter(t){return Jh._createAfter(t)}createPositionBefore(t){return Jh._createBefore(t)}createRange(t,e){return new ef(t,e)}createRangeIn(t){return ef._createIn(t)}createRangeOn(t){return ef._createOn(t)}createSelection(t,e,n){return new uf(t,e,n)}createBatch(t){return new ag(t)}createOperationFromJSON(t){return tp.fromJSON(t,this.document)}destroy(){this.document.destroy();this.stopListening()}_runPendingChanges(){const t=[];this.fire("_beforeChanges");while(this._pendingChanges.length){const e=this._pendingChanges[0].batch;this._currentWriter=new Ig(this,e);const n=this._pendingChanges[0].callback(this._currentWriter);t.push(n);this.document._handleChangeBlock(this._currentWriter);this._pendingChanges.shift();this._currentWriter=null}this.fire("_afterChanges");return t}}_s(Fp,Jc);class Vp{constructor(){this._listener=Object.create(Jd)}listenTo(t){this._listener.listenTo(t,"keydown",((t,e)=>{this._listener.fire("_keydown:"+Ol(e),e)}))}set(t,e,n={}){const o=Rl(t);const i=n.priority;this._listener.listenTo(this._listener,"_keydown:"+o,((t,n)=>{e(n,(()=>{n.preventDefault();n.stopPropagation();t.stop()}));t.return=true}),{priority:i})}press(t){return!!this._listener.fire("_keydown:"+Ol(t),t)}destroy(){this._listener.stopListening()}}class Up extends Vp{constructor(t){super();this.editor=t}set(t,e,n={}){if(typeof e=="string"){const t=e;e=(e,n)=>{this.editor.execute(t);n()}}super.set(t,e,n)}}class Hp{constructor(t={}){this._context=t.context||new zs({language:t.language});this._context._addEditor(this,!t.context);const e=Array.from(this.constructor.builtinPlugins||[]);this.config=new Qr(t,this.constructor.defaultConfig);this.config.define("plugins",e);this.config.define(this._context._getEditorConfig());this.plugins=new ys(this,e,this._context.plugins);this.locale=this._context.locale;this.t=this.locale.t;this.commands=new Nm;this.set("state","initializing");this.once("ready",(()=>this.state="ready"),{priority:"high"});this.once("destroy",(()=>this.state="destroyed"),{priority:"high"});this.set("isReadOnly",false);this.model=new Fp;const n=new zc;this.data=new ng(this.model,n);this.editing=new Im(this.model,n);this.editing.view.document.bind("isReadOnly").to(this);this.conversion=new ig([this.editing.downcastDispatcher,this.data.downcastDispatcher],this.data.upcastDispatcher);this.conversion.addAlias("dataDowncast",this.data.downcastDispatcher);this.conversion.addAlias("editingDowncast",this.editing.downcastDispatcher);this.keystrokes=new Up(this);this.keystrokes.listenTo(this.editing.view.document)}initPlugins(){const t=this.config;const e=t.get("plugins");const n=t.get("removePlugins")||[];const o=t.get("extraPlugins")||[];return this.plugins.init(e.concat(o),n)}destroy(){let t=Promise.resolve();if(this.state=="initializing"){t=new Promise((t=>this.once("ready",t)))}return t.then((()=>{this.fire("destroy");this.stopListening();this.commands.destroy()})).then((()=>this.plugins.destroy())).then((()=>{this.model.destroy();this.data.destroy();this.editing.destroy();this.keystrokes.destroy()})).then((()=>this._context._removeEditor(this)))}execute(...t){try{return this.commands.execute(...t)}catch(t){ss["a"].rethrowUnexpectedError(t,this)}}focus(){this.editing.view.focus()}}_s(Hp,Jc);const Gp={setData(t){this.data.set(t)},getData(t){return this.data.get(t)}};var Kp=Gp;function Wp(t,e){if(t instanceof HTMLTextAreaElement){t.value=e}t.innerHTML=e}const qp={updateSourceElement(){if(!this.sourceElement){throw new ss["a"]("editor-missing-sourceelement",this)}Wp(this.sourceElement,this.data.get())}};var Yp=qp;function Qp(t){if(!mt(t.updateSourceElement)){throw new ss["a"]("attachtoform-missing-elementapi-interface",t)}const e=t.sourceElement;if(e&&e.tagName.toLowerCase()==="textarea"&&e.form){let n;const o=e.form;const i=()=>t.updateSourceElement();if(mt(o.submit)){n=o.submit;o.submit=()=>{i();n.apply(o)}}o.addEventListener("submit",i);t.on("destroy",(()=>{o.removeEventListener("submit",i);if(n){o.submit=n}}))}}class $p{getHtml(t){const e=document.implementation.createHTMLDocument("");const n=e.createElement("div");n.appendChild(t);return n.innerHTML}}class Jp{constructor(t){this._domParser=new DOMParser;this._domConverter=new Gd(t,{blockFillerMode:"nbsp"});this._htmlWriter=new $p}toData(t){const e=this._domConverter.viewToDom(t,document);return this._htmlWriter.getHtml(e)}toView(t){const e=this._toDom(t);return this._domConverter.domToView(e)}registerRawContentMatcher(t){this._domConverter.registerRawContentMatcher(t)}_toDom(t){const e=this._domParser.parseFromString(t,"text/html");const n=e.createDocumentFragment();const o=e.body.childNodes;while(o.length>0){n.appendChild(o[0])}return n}}class Zp{constructor(t){this.editor=t;this._components=new Map}*names(){for(const t of this._components.values()){yield t.originalName}}add(t,e){this._components.set(Xp(t),{callback:e,originalName:t})}create(t){if(!this.has(t)){throw new ss["a"]("componentfactory-item-missing",this,{name:t})}return this._components.get(Xp(t)).callback(this.editor.locale)}has(t){return this._components.has(Xp(t))}}function Xp(t){return String(t).toLowerCase()}class tk{constructor(){this.set("isFocused",false);this.set("focusedElement",null);this._elements=new Set;this._nextEventLoopTimeout=null}add(t){if(this._elements.has(t)){throw new ss["a"]("focustracker-add-element-already-exist",this)}this.listenTo(t,"focus",(()=>this._focus(t)),{useCapture:true});this.listenTo(t,"blur",(()=>this._blur()),{useCapture:true});this._elements.add(t)}remove(t){if(t===this.focusedElement){this._blur(t)}if(this._elements.has(t)){this.stopListening(t);this._elements.delete(t)}}destroy(){this.stopListening()}_focus(t){clearTimeout(this._nextEventLoopTimeout);this.focusedElement=t;this.isFocused=true}_blur(){clearTimeout(this._nextEventLoopTimeout);this._nextEventLoopTimeout=setTimeout((()=>{this.focusedElement=null;this.isFocused=false}),0)}}_s(tk,Jd);_s(tk,Jc);class ek{constructor(t){this.editor=t;this.componentFactory=new Zp(t);this.focusTracker=new tk;this._editableElementsMap=new Map;this.listenTo(t.editing.view.document,"layoutChanged",(()=>this.update()))}get element(){return null}update(){this.fire("update")}destroy(){this.stopListening();this.focusTracker.destroy();for(const t of this._editableElementsMap.values()){t.ckeditorInstance=null}this._editableElementsMap=new Map}setEditableElement(t,e){this._editableElementsMap.set(t,e);if(!e.ckeditorInstance){e.ckeditorInstance=this.editor}}getEditableElement(t="main"){return this._editableElementsMap.get(t)}getEditableElementsNames(){return this._editableElementsMap.keys()}get _editableElements(){console.warn("editor-ui-deprecated-editable-elements: "+"The EditorUI#_editableElements property has been deprecated and will be removed in the near future.",{editorUI:this});return this._editableElementsMap}}_s(ek,ds);function nk({origin:t,originKeystrokeHandler:e,originFocusTracker:n,toolbar:o,beforeFocus:i,afterBlur:r}){n.add(o.element);e.set("Alt+F10",((t,e)=>{if(n.isFocused&&!o.focusTracker.isFocused){if(i){i()}o.focus();e()}}));o.keystrokes.set("Esc",((e,n)=>{if(o.focusTracker.isFocused){t.focus();if(r){r()}n()}}))}function ok(t){if(Array.isArray(t)){return{items:t}}if(!t){return{items:[]}}return Object.assign({items:[]},t)}var ik=n(1);var rk=n.n(ik);var sk=n(12);var ak={injectType:"singletonStyleTag",attributes:{"data-cke":true}};ak.insert="head";ak.singleton=true;var ck=rk()(sk["a"],ak);var lk=sk["a"].locals||{};const dk=new WeakMap;function uk(t){const{view:e,element:n,text:o,isDirectHost:i=true}=t;const r=e.document;if(!dk.has(r)){dk.set(r,new Map);r.registerPostFixer((t=>pk(r,t)))}dk.get(r).set(n,{text:o,isDirectHost:i});e.change((t=>pk(r,t)))}function hk(t,e){const n=e.document;t.change((t=>{if(!dk.has(n)){return}const o=dk.get(n);const i=o.get(e);t.removeAttribute("data-placeholder",i.hostElement);mk(t,i.hostElement);o.delete(e)}))}function fk(t,e){if(!e.hasClass("ck-placeholder")){t.addClass("ck-placeholder",e);return true}return false}function mk(t,e){if(e.hasClass("ck-placeholder")){t.removeClass("ck-placeholder",e);return true}return false}function gk(t){if(!t.isAttached()){return false}const e=!Array.from(t.getChildren()).some((t=>!t.is("uiElement")));const n=t.document;if(!n.isFocused&&e){return true}const o=n.selection;const i=o.anchor;if(e&&i&&i.parent!==t){return true}return false}function pk(t,e){const n=dk.get(t);let o=false;for(const[t,i]of n){if(kk(e,t,i)){o=true}}return o}function kk(t,e,n){const{text:o,isDirectHost:i}=n;const r=i?e:bk(e);let s=false;if(!r){return false}n.hostElement=r;if(r.getAttribute("data-placeholder")!==o){t.setAttribute("data-placeholder",o,r);s=true}if(gk(r)){if(fk(t,r)){s=true}}else if(mk(t,r)){s=true}return s}function bk(t){if(t.childCount===1){const e=t.getChild(0);if(e.is("element")&&!e.is("uiElement")){return e}}return null}class wk{constructor(){this._replacedElements=[]}replace(t,e){this._replacedElements.push({element:t,newElement:e});t.style.display="none";if(e){t.parentNode.insertBefore(e,t.nextSibling)}}restore(){this._replacedElements.forEach((({element:t,newElement:e})=>{t.style.display="";if(e){e.remove()}}));this._replacedElements=[]}}class Ck extends ek{constructor(t,e){super(t);this.view=e;this._toolbarConfig=ok(t.config.get("toolbar"));this._elementReplacer=new wk}get element(){return this.view.element}init(t){const e=this.editor;const n=this.view;const o=e.editing.view;const i=n.editable;const r=o.document.getRoot();i.name=r.rootName;n.render();const s=i.element;this.setEditableElement(i.name,s);this.focusTracker.add(s);n.editable.bind("isFocused").to(this.focusTracker);o.attachDomRoot(s);if(t){this._elementReplacer.replace(t,this.element)}this._initPlaceholder();this._initToolbar();this.fire("ready")}destroy(){const t=this.view;const e=this.editor.editing.view;this._elementReplacer.restore();e.detachDomRoot(t.editable.name);t.destroy();super.destroy()}_initToolbar(){const t=this.editor;const e=this.view;const n=t.editing.view;e.stickyPanel.bind("isActive").to(this.focusTracker,"isFocused");e.stickyPanel.limiterElement=e.element;if(this._toolbarConfig.viewportTopOffset){e.stickyPanel.viewportTopOffset=this._toolbarConfig.viewportTopOffset}e.toolbar.fillFromConfig(this._toolbarConfig.items,this.componentFactory);nk({origin:n,originFocusTracker:this.focusTracker,originKeystrokeHandler:t.keystrokes,toolbar:e.toolbar})}_initPlaceholder(){const t=this.editor;const e=t.editing.view;const n=e.document.getRoot();const o=t.sourceElement;const i=t.config.get("placeholder")||o&&o.tagName.toLowerCase()==="textarea"&&o.getAttribute("placeholder");if(i){uk({view:e,element:n,text:i,isDirectHost:false})}}}class Ak extends vs{constructor(t=[]){super(t,{idProperty:"viewUid"});this.on("add",((t,e,n)=>{this._renderViewIntoCollectionParent(e,n)}));this.on("remove",((t,e)=>{if(e.element&&this._parentElement){e.element.remove()}}));this._parentElement=null}destroy(){this.map((t=>t.destroy()))}setParent(t){this._parentElement=t;for(const t of this){this._renderViewIntoCollectionParent(t)}}delegate(...t){if(!t.length||!_k(t)){throw new ss["a"]("ui-viewcollection-delegate-wrong-events",this)}return{to:e=>{for(const n of this){for(const o of t){n.delegate(o).to(e)}}this.on("add",((n,o)=>{for(const n of t){o.delegate(n).to(e)}}));this.on("remove",((n,o)=>{for(const n of t){o.stopDelegating(n,e)}}))}}}_renderViewIntoCollectionParent(t,e){if(!t.isRendered){t.render()}if(t.element&&this._parentElement){this._parentElement.insertBefore(t.element,this._parentElement.children[e])}}}function _k(t){return t.every((t=>typeof t=="string"))}const vk="http://www.w3.org/1999/xhtml";class yk{constructor(t){Object.assign(this,zk(Pk(t)));this._isRendered=false;this._revertData=null}render(){const t=this._renderNode({intoFragment:true});this._isRendered=true;return t}apply(t){this._revertData=Yk();this._renderNode({node:t,isApplying:true,revertData:this._revertData});return t}revert(t){if(!this._revertData){throw new ss["a"]("ui-template-revert-not-applied",[this,t])}this._revertTemplateFromNode(t,this._revertData)}*getViews(){function*t(e){if(e.children){for(const n of e.children){if(Kk(n)){yield n}else if(Wk(n)){yield*t(n)}}}}yield*t(this)}static bind(t,e){return{to(n,o){return new Dk({eventNameOrFunction:n,attribute:n,observable:t,emitter:e,callback:o})},if(n,o,i){return new Ek({observable:t,emitter:e,attribute:n,valueIfTrue:o,callback:i})}}}static extend(t,e){if(t._isRendered){throw new ss["a"]("template-extend-render",[this,t])}Hk(t,zk(Pk(e)))}_renderNode(t){let e;if(t.node){e=this.tag&&this.text}else{e=this.tag?this.text:!this.text}if(e){throw new ss["a"]("ui-template-wrong-syntax",this)}if(this.text){return this._renderText(t)}else{return this._renderElement(t)}}_renderElement(t){let e=t.node;if(!e){e=t.node=document.createElementNS(this.ns||vk,this.tag)}this._renderAttributes(t);this._renderElementChildren(t);this._setUpListeners(t);return e}_renderText(t){let e=t.node;if(e){t.revertData.text=e.textContent}else{e=t.node=document.createTextNode("")}if(Mk(this.text)){this._bindToObservable({schema:this.text,updater:Ik(e),data:t})}else{e.textContent=this.text.join("")}return e}_renderAttributes(t){let e,n,o,i;if(!this.attributes){return}const r=t.node;const s=t.revertData;for(e in this.attributes){o=r.getAttribute(e);n=this.attributes[e];if(s){s.attributes[e]=o}i=ct(n[0])&&n[0].ns?n[0].ns:null;if(Mk(n)){const a=i?n[0].value:n;if(s&&Qk(e)){a.unshift(o)}this._bindToObservable({schema:a,updater:Nk(r,e,i),data:t})}else if(e=="style"&&typeof n[0]!=="string"){this._renderStyleAttribute(n[0],t)}else{if(s&&o&&Qk(e)){n.unshift(o)}n=n.map((t=>t?t.value||t:t)).reduce(((t,e)=>t.concat(e)),[]).reduce(Vk,"");if(!Gk(n)){r.setAttributeNS(i,e,n)}}}}_renderStyleAttribute(t,e){const n=e.node;for(const o in t){const i=t[o];if(Mk(i)){this._bindToObservable({schema:[i],updater:Bk(n,o),data:e})}else{n.style[o]=i}}}_renderElementChildren(t){const e=t.node;const n=t.intoFragment?document.createDocumentFragment():e;const o=t.isApplying;let i=0;for(const r of this.children){if(qk(r)){if(!o){r.setParent(e);for(const t of r){n.appendChild(t.element)}}}else if(Kk(r)){if(!o){if(!r.isRendered){r.render()}n.appendChild(r.element)}}else if(Sd(r)){n.appendChild(r)}else{if(o){const e=t.revertData;const o=Yk();e.children.push(o);r._renderNode({node:n.childNodes[i++],isApplying:true,revertData:o})}else{n.appendChild(r.render())}}}if(t.intoFragment){e.appendChild(n)}}_setUpListeners(t){if(!this.eventListeners){return}for(const e in this.eventListeners){const n=this.eventListeners[e].map((n=>{const[o,i]=e.split("@");return n.activateDomEventListener(o,i,t)}));if(t.revertData){t.revertData.bindings.push(n)}}}_bindToObservable({schema:t,updater:e,data:n}){const o=n.revertData;Sk(t,e,n);const i=t.filter((t=>!Gk(t))).filter((t=>t.observable)).map((o=>o.activateAttributeListener(t,e,n)));if(o){o.bindings.push(i)}}_revertTemplateFromNode(t,e){for(const t of e.bindings){for(const e of t){e()}}if(e.text){t.textContent=e.text;return}for(const n in e.attributes){const o=e.attributes[n];if(o===null){t.removeAttribute(n)}else{t.setAttribute(n,o)}}for(let n=0;nSk(t,e,n);this.emitter.listenTo(this.observable,"change:"+this.attribute,o);return()=>{this.emitter.stopListening(this.observable,"change:"+this.attribute,o)}}}class Dk extends xk{activateDomEventListener(t,e,n){const o=(t,n)=>{if(!e||n.target.matches(e)){if(typeof this.eventNameOrFunction=="function"){this.eventNameOrFunction(n)}else{this.observable.fire(this.eventNameOrFunction,n)}}};this.emitter.listenTo(n.node,t,o);return()=>{this.emitter.stopListening(n.node,t,o)}}}class Ek extends xk{getValue(t){const e=super.getValue(t);return Gk(e)?false:this.valueIfTrue||true}}function Mk(t){if(!t){return false}if(t.value){t=t.value}if(Array.isArray(t)){return t.some(Mk)}else if(t instanceof xk){return true}return false}function Tk(t,e){return t.map((t=>{if(t instanceof xk){return t.getValue(e)}return t}))}function Sk(t,e,{node:n}){let o=Tk(t,n);if(t.length==1&&t[0]instanceof Ek){o=o[0]}else{o=o.reduce(Vk,"")}if(Gk(o)){e.remove()}else{e.set(o)}}function Ik(t){return{set(e){t.textContent=e},remove(){t.textContent=""}}}function Nk(t,e,n){return{set(o){t.setAttributeNS(n,e,o)},remove(){t.removeAttributeNS(n,e)}}}function Bk(t,e){return{set(n){t.style[e]=n},remove(){t.style[e]=null}}}function Pk(t){const e=Wr(t,(t=>{if(t&&(t instanceof xk||Wk(t)||Kk(t)||qk(t))){return t}}));return e}function zk(t){if(typeof t=="string"){t=Rk(t)}else if(t.text){jk(t)}if(t.on){t.eventListeners=Ok(t.on);delete t.on}if(!t.text){if(t.attributes){Lk(t.attributes)}const e=[];if(t.children){if(qk(t.children)){e.push(t.children)}else{for(const n of t.children){if(Wk(n)||Kk(n)||Sd(n)){e.push(n)}else{e.push(new yk(n))}}}}t.children=e}return t}function Lk(t){for(const e in t){if(t[e].value){t[e].value=xs(t[e].value)}Fk(t,e)}}function Ok(t){for(const e in t){Fk(t,e)}return t}function Rk(t){return{text:[t]}}function jk(t){t.text=xs(t.text)}function Fk(t,e){t[e]=xs(t[e])}function Vk(t,e){if(Gk(e)){return t}else if(Gk(t)){return e}else{return`${t} ${e}`}}function Uk(t,e){for(const n in e){if(t[n]){t[n].push(...e[n])}else{t[n]=e[n]}}}function Hk(t,e){if(e.attributes){if(!t.attributes){t.attributes={}}Uk(t.attributes,e.attributes)}if(e.eventListeners){if(!t.eventListeners){t.eventListeners={}}Uk(t.eventListeners,e.eventListeners)}if(e.text){t.text.push(...e.text)}if(e.children&&e.children.length){if(t.children.length!=e.children.length){throw new ss["a"]("ui-template-extend-children-mismatch",t)}let n=0;for(const o of e.children){Hk(t.children[n++],o)}}}function Gk(t){return!t&&t!==0}function Kk(t){return t instanceof tb}function Wk(t){return t instanceof yk}function qk(t){return t instanceof Ak}function Yk(){return{children:[],bindings:[],attributes:{}}}function Qk(t){return t=="class"||t=="style"}var $k=n(13);var Jk={injectType:"singletonStyleTag",attributes:{"data-cke":true}};Jk.insert="head";Jk.singleton=true;var Zk=rk()($k["a"],Jk);var Xk=$k["a"].locals||{};class tb{constructor(t){this.element=null;this.isRendered=false;this.locale=t;this.t=t&&t.t;this._viewCollections=new vs;this._unboundChildren=this.createCollection();this._viewCollections.on("add",((e,n)=>{n.locale=t}));this.decorate("render")}get bindTemplate(){if(this._bindTemplate){return this._bindTemplate}return this._bindTemplate=yk.bind(this,this)}createCollection(t){const e=new Ak(t);this._viewCollections.add(e);return e}registerChild(t){if(!As(t)){t=[t]}for(const e of t){this._unboundChildren.add(e)}}deregisterChild(t){if(!As(t)){t=[t]}for(const e of t){this._unboundChildren.remove(e)}}setTemplate(t){this.template=new yk(t)}extendTemplate(t){yk.extend(this.template,t)}render(){if(this.isRendered){throw new ss["a"]("ui-view-render-already-rendered",this)}if(this.template){this.element=this.template.render();this.registerChild(this.template.getViews())}this.isRendered=true}destroy(){this.stopListening();this._viewCollections.map((t=>t.destroy()));if(this.template&&this.template._revertData){this.template.revert(this.element)}}}_s(tb,Jd);_s(tb,Jc);var eb="[object String]";function nb(t){return typeof t=="string"||!Qe(t)&&D(t)&&C(t)==eb}var ob=nb;function ib(t,e,n={},o=[]){const i=n&&n.xmlns;const r=i?t.createElementNS(i,e):t.createElement(e);for(const t in n){r.setAttribute(t,n[t])}if(ob(o)||!As(o)){o=[o]}for(let e of o){if(ob(e)){e=t.createTextNode(e)}r.appendChild(e)}return r}class rb extends Ak{constructor(t,e=[]){super(e);this.locale=t}attachToDom(){this._bodyCollectionContainer=new yk({tag:"div",attributes:{class:["ck","ck-reset_all","ck-body","ck-rounded-corners"],dir:this.locale.uiLanguageDirection},children:this}).render();let t=document.querySelector(".ck-body-wrapper");if(!t){t=ib(document,"div",{class:"ck-body-wrapper"});document.body.appendChild(t)}t.appendChild(this._bodyCollectionContainer)}detachFromDom(){super.destroy();if(this._bodyCollectionContainer){this._bodyCollectionContainer.remove()}const t=document.querySelector(".ck-body-wrapper");if(t&&t.childElementCount==0){t.remove()}}}var sb=n(14);var ab={injectType:"singletonStyleTag",attributes:{"data-cke":true}};ab.insert="head";ab.singleton=true;var cb=rk()(sb["a"],ab);var lb=sb["a"].locals||{};class db extends tb{constructor(t){super(t);this.body=new rb(t)}render(){super.render();this.body.attachToDom()}destroy(){this.body.detachFromDom();return super.destroy()}}var ub=n(15);var hb={injectType:"singletonStyleTag",attributes:{"data-cke":true}};hb.insert="head";hb.singleton=true;var fb=rk()(ub["a"],hb);var mb=ub["a"].locals||{};class gb extends tb{constructor(t){super(t);this.set("text");this.set("for");this.id=`ck-editor__label_${ns()}`;const e=this.bindTemplate;this.setTemplate({tag:"label",attributes:{class:["ck","ck-label"],id:this.id,for:e.to("for")},children:[{text:e.to("text")}]})}}class pb extends db{constructor(t){super(t);this.top=this.createCollection();this.main=this.createCollection();this._voiceLabelView=this._createVoiceLabel();this.setTemplate({tag:"div",attributes:{class:["ck","ck-reset","ck-editor","ck-rounded-corners"],role:"application",dir:t.uiLanguageDirection,lang:t.uiLanguage,"aria-labelledby":this._voiceLabelView.id},children:[this._voiceLabelView,{tag:"div",attributes:{class:["ck","ck-editor__top","ck-reset_all"],role:"presentation"},children:this.top},{tag:"div",attributes:{class:["ck","ck-editor__main"],role:"presentation"},children:this.main}]})}_createVoiceLabel(){const t=this.t;const e=new gb;e.text=t("Rich Text Editor");e.extendTemplate({attributes:{class:"ck-voice-label"}});return e}}class kb extends tb{constructor(t,e,n){super(t);this.setTemplate({tag:"div",attributes:{class:["ck","ck-content","ck-editor__editable","ck-rounded-corners"],lang:t.contentLanguage,dir:t.contentLanguageDirection}});this.name=null;this.set("isFocused",false);this._editableElement=n;this._hasExternalElement=!!this._editableElement;this._editingView=e}render(){super.render();if(this._hasExternalElement){this.template.apply(this.element=this._editableElement)}else{this._editableElement=this.element}this.on("change:isFocused",(()=>this._updateIsFocusedClasses()));this._updateIsFocusedClasses()}destroy(){if(this._hasExternalElement){this.template.revert(this._editableElement)}super.destroy()}_updateIsFocusedClasses(){const t=this._editingView;if(t.isRenderingInProgress){n(this)}else{e(this)}function e(e){t.change((n=>{const o=t.document.getRoot(e.name);n.addClass(e.isFocused?"ck-focused":"ck-blurred",o);n.removeClass(e.isFocused?"ck-blurred":"ck-focused",o)}))}function n(o){t.once("change:isRenderingInProgress",((t,i,r)=>{if(!r){e(o)}else{n(o)}}))}}}class bb extends kb{constructor(t,e,n){super(t,e,n);this.extendTemplate({attributes:{role:"textbox",class:"ck-editor__editable_inline"}})}render(){super.render();const t=this._editingView;const e=this.t;t.change((n=>{const o=t.document.getRoot(this.name);n.setAttribute("aria-label",e("Rich Text Editor, %0",this.name),o)}))}}function wb(t){return e=>e+t}var Cb=n(16);var Ab={injectType:"singletonStyleTag",attributes:{"data-cke":true}};Ab.insert="head";Ab.singleton=true;var _b=rk()(Cb["a"],Ab);var vb=Cb["a"].locals||{};const yb=wb("px");class xb extends tb{constructor(t){super(t);const e=this.bindTemplate;this.set("isActive",false);this.set("isSticky",false);this.set("limiterElement",null);this.set("limiterBottomOffset",50);this.set("viewportTopOffset",0);this.set("_marginLeft",null);this.set("_isStickyToTheLimiter",false);this.set("_hasViewportTopOffset",false);this.content=this.createCollection();this._contentPanelPlaceholder=new yk({tag:"div",attributes:{class:["ck","ck-sticky-panel__placeholder"],style:{display:e.to("isSticky",(t=>t?"block":"none")),height:e.to("isSticky",(t=>t?yb(this._panelRect.height):null))}}}).render();this._contentPanel=new yk({tag:"div",attributes:{class:["ck","ck-sticky-panel__content",e.if("isSticky","ck-sticky-panel__content_sticky"),e.if("_isStickyToTheLimiter","ck-sticky-panel__content_sticky_bottom-limit")],style:{width:e.to("isSticky",(t=>t?yb(this._contentPanelPlaceholder.getBoundingClientRect().width):null)),top:e.to("_hasViewportTopOffset",(t=>t?yb(this.viewportTopOffset):null)),bottom:e.to("_isStickyToTheLimiter",(t=>t?yb(this.limiterBottomOffset):null)),marginLeft:e.to("_marginLeft")}},children:this.content}).render();this.setTemplate({tag:"div",attributes:{class:["ck","ck-sticky-panel"]},children:[this._contentPanelPlaceholder,this._contentPanel]})}render(){super.render();this._checkIfShouldBeSticky();this.listenTo(jd.window,"scroll",(()=>{this._checkIfShouldBeSticky()}));this.listenTo(this,"change:isActive",(()=>{this._checkIfShouldBeSticky()}))}_checkIfShouldBeSticky(){const t=this._panelRect=this._contentPanel.getBoundingClientRect();let e;if(!this.limiterElement){this.isSticky=false}else{e=this._limiterRect=this.limiterElement.getBoundingClientRect();this.isSticky=this.isActive&&e.top{this[e]();n()}))}}}}get first(){return this.focusables.find(Eb)||null}get last(){return this.focusables.filter(Eb).slice(-1)[0]||null}get next(){return this._getFocusableItem(1)}get previous(){return this._getFocusableItem(-1)}get current(){let t=null;if(this.focusTracker.focusedElement===null){return null}this.focusables.find(((e,n)=>{const o=e.element===this.focusTracker.focusedElement;if(o){t=n}return o}));return t}focusFirst(){this._focus(this.first)}focusLast(){this._focus(this.last)}focusNext(){this._focus(this.next)}focusPrevious(){this._focus(this.previous)}_focus(t){if(t){t.focus()}}_getFocusableItem(t){const e=this.current;const n=this.focusables.length;if(!n){return null}if(e===null){return this[t===1?"first":"last"]}let o=(e+n+t)%n;do{const e=this.focusables.get(o);if(Eb(e)){return e}o=(o+n+t)%n}while(o!==e);return null}}function Eb(t){return!!(t.focus&&jd.window.getComputedStyle(t.element).display!="none")}class Mb extends tb{constructor(t){super(t);this.setTemplate({tag:"span",attributes:{class:["ck","ck-toolbar__separator"]}})}}class Tb extends tb{constructor(t){super(t);this.setTemplate({tag:"span",attributes:{class:["ck","ck-toolbar__line-break"]}})}}const Sb=100;class Ib{constructor(t,e){if(!Ib._observerInstance){Ib._createObserver()}this._element=t;this._callback=e;Ib._addElementCallback(t,e);Ib._observerInstance.observe(t)}destroy(){Ib._deleteElementCallback(this._element,this._callback)}static _addElementCallback(t,e){if(!Ib._elementCallbacks){Ib._elementCallbacks=new Map}let n=Ib._elementCallbacks.get(t);if(!n){n=new Set;Ib._elementCallbacks.set(t,n)}n.add(e)}static _deleteElementCallback(t,e){const n=Ib._getElementCallbacks(t);if(n){n.delete(e);if(!n.size){Ib._elementCallbacks.delete(t);Ib._observerInstance.unobserve(t)}}if(Ib._elementCallbacks&&!Ib._elementCallbacks.size){Ib._observerInstance=null;Ib._elementCallbacks=null}}static _getElementCallbacks(t){if(!Ib._elementCallbacks){return null}return Ib._elementCallbacks.get(t)}static _createObserver(){let t;if(typeof jd.window.ResizeObserver==="function"){t=jd.window.ResizeObserver}else{t=Nb}Ib._observerInstance=new t((t=>{for(const e of t){const t=Ib._getElementCallbacks(e.target);if(t){for(const n of t){n(e)}}}}))}}Ib._observerInstance=null;Ib._elementCallbacks=null;class Nb{constructor(t){this._callback=t;this._elements=new Set;this._previousRects=new Map;this._periodicCheckTimeout=null}observe(t){this._elements.add(t);this._checkElementRectsAndExecuteCallback();if(this._elements.size===1){this._startPeriodicCheck()}}unobserve(t){this._elements.delete(t);this._previousRects.delete(t);if(!this._elements.size){this._stopPeriodicCheck()}}_startPeriodicCheck(){const t=()=>{this._checkElementRectsAndExecuteCallback();this._periodicCheckTimeout=setTimeout(t,Sb)};this.listenTo(jd.window,"resize",(()=>{this._checkElementRectsAndExecuteCallback()}));this._periodicCheckTimeout=setTimeout(t,Sb)}_stopPeriodicCheck(){clearTimeout(this._periodicCheckTimeout);this.stopListening();this._previousRects.clear()}_checkElementRectsAndExecuteCallback(){const t=[];for(const e of this._elements){if(this._hasRectChanged(e)){t.push({target:e,contentRect:this._previousRects.get(e)})}}if(t.length){this._callback(t)}}_hasRectChanged(t){if(!t.ownerDocument.body.contains(t)){return false}const e=new Eh(t);const n=this._previousRects.get(t);const o=!n||!n.isEqual(e);this._previousRects.set(t,e);return o}}_s(Nb,Jd);function Bb(t){return t.bindTemplate.to((e=>{if(e.target===t.element){e.preventDefault()}}))}class Pb extends tb{constructor(t){super(t);const e=this.bindTemplate;this.set("isVisible",false);this.set("position","se");this.children=this.createCollection();this.setTemplate({tag:"div",attributes:{class:["ck","ck-reset","ck-dropdown__panel",e.to("position",(t=>`ck-dropdown__panel_${t}`)),e.if("isVisible","ck-dropdown__panel-visible")]},children:this.children,on:{selectstart:e.to((t=>t.preventDefault()))}})}focus(){if(this.children.length){this.children.first.focus()}}focusLast(){if(this.children.length){const t=this.children.last;if(typeof t.focusLast==="function"){t.focusLast()}else{t.focus()}}}}var zb=n(17);var Lb={injectType:"singletonStyleTag",attributes:{"data-cke":true}};Lb.insert="head";Lb.singleton=true;var Ob=rk()(zb["a"],Lb);var Rb=zb["a"].locals||{};function jb(t){if(!t||!t.parentNode){return null}if(t.offsetParent===jd.document.body){return null}return t.offsetParent}function Fb({element:t,target:e,positions:n,limiter:o,fitInViewport:i}){if(mt(e)){e=e()}if(mt(o)){o=o()}const r=jb(t);const s=new Eh(t);const a=new Eh(e);let c;let l;if(!o&&!i){[l,c]=Vb(n[0],a,s)}else{const t=o&&new Eh(o).getVisible();const e=i&&new Eh(jd.window);const r=Ub(n,{targetRect:a,elementRect:s,limiterRect:t,viewportRect:e});[l,c]=r||Vb(n[0],a,s)}let d=Wb(c);if(r){d=Kb(d,r)}return{left:d.left,top:d.top,name:l}}function Vb(t,e,n){const o=t(e,n);if(!o){return null}const{left:i,top:r,name:s}=o;return[s,n.clone().moveTo(i,r)]}function Ub(t,e){const{elementRect:n,viewportRect:o}=e;const i=n.getArea();const r=Hb(t,e);if(o){const t=r.filter((({viewportIntersectArea:t})=>t===i));const e=Gb(t,i);if(e){return e}}return Gb(r,i)}function Hb(t,{targetRect:e,elementRect:n,limiterRect:o,viewportRect:i}){const r=[];const s=n.getArea();for(const a of t){const t=Vb(a,e,n);if(!t){continue}const[c,l]=t;let d=0;let u=0;if(o){if(i){const t=o.getIntersection(i);if(t){d=t.getIntersectionArea(l)}}else{d=o.getIntersectionArea(l)}}if(i){u=i.getIntersectionArea(l)}const h={positionName:c,positionRect:l,limiterIntersectArea:d,viewportIntersectArea:u};if(d===s){return[h]}r.push(h)}return r}function Gb(t,e){let n=0;let o;let i;for(const{positionName:r,positionRect:s,limiterIntersectArea:a,viewportIntersectArea:c}of t){if(a===e){return[r,s]}const t=c**2+a**2;if(t>n){n=t;o=s;i=r}}return o?[i,o]:null}function Kb({left:t,top:e},n){const o=Wb(new Eh(n));const i=xh(n);t-=o.left;e-=o.top;t+=n.scrollLeft;e+=n.scrollTop;t-=i.left;e-=i.top;return{left:t,top:e}}function Wb({left:t,top:e}){const{scrollX:n,scrollY:o}=jd.window;return{left:t+n,top:e+o}}class qb extends tb{constructor(t,e,n){super(t);const o=this.bindTemplate;this.buttonView=e;this.panelView=n;this.set("isOpen",false);this.set("isEnabled",true);this.set("class");this.set("id");this.set("panelPosition","auto");this.keystrokes=new Vp;this.setTemplate({tag:"div",attributes:{class:["ck","ck-dropdown",o.to("class"),o.if("isEnabled","ck-disabled",(t=>!t))],id:o.to("id"),"aria-describedby":o.to("ariaDescribedById")},children:[e,n]});e.extendTemplate({attributes:{class:["ck-dropdown__button"]}})}render(){super.render();this.listenTo(this.buttonView,"open",(()=>{this.isOpen=!this.isOpen}));this.panelView.bind("isVisible").to(this,"isOpen");this.on("change:isOpen",(()=>{if(!this.isOpen){return}if(this.panelPosition==="auto"){this.panelView.position=qb._getOptimalPosition({element:this.panelView.element,target:this.buttonView.element,fitInViewport:true,positions:this._panelPositions}).name}else{this.panelView.position=this.panelPosition}}));this.keystrokes.listenTo(this.element);const t=(t,e)=>{if(this.isOpen){this.buttonView.focus();this.isOpen=false;e()}};this.keystrokes.set("arrowdown",((t,e)=>{if(this.buttonView.isEnabled&&!this.isOpen){this.isOpen=true;e()}}));this.keystrokes.set("arrowright",((t,e)=>{if(this.isOpen){e()}}));this.keystrokes.set("arrowleft",t);this.keystrokes.set("esc",t)}focus(){this.buttonView.focus()}get _panelPositions(){const{southEast:t,southWest:e,northEast:n,northWest:o}=qb.defaultPanelPositions;if(this.locale.uiLanguageDirection==="ltr"){return[t,e,n,o]}else{return[e,t,o,n]}}}qb.defaultPanelPositions={southEast:t=>({top:t.bottom,left:t.left,name:"se"}),southWest:(t,e)=>({top:t.bottom,left:t.left-e.width+t.width,name:"sw"}),northEast:(t,e)=>({top:t.top-e.height,left:t.left,name:"ne"}),northWest:(t,e)=>({top:t.bottom-e.height,left:t.left-e.width+t.width,name:"nw"})};qb._getOptimalPosition=Fb;var Yb=n(18);var Qb={injectType:"singletonStyleTag",attributes:{"data-cke":true}};Qb.insert="head";Qb.singleton=true;var $b=rk()(Yb["a"],Qb);var Jb=Yb["a"].locals||{};class Zb extends tb{constructor(){super();const t=this.bindTemplate;this.set("content","");this.set("viewBox","0 0 20 20");this.set("fillColor","");this.setTemplate({tag:"svg",ns:"http://www.w3.org/2000/svg",attributes:{class:["ck","ck-icon"],viewBox:t.to("viewBox")}})}render(){super.render();this._updateXMLContent();this._colorFillPaths();this.on("change:content",(()=>{this._updateXMLContent();this._colorFillPaths()}));this.on("change:fillColor",(()=>{this._colorFillPaths()}))}_updateXMLContent(){if(this.content){const t=(new DOMParser).parseFromString(this.content.trim(),"image/svg+xml");const e=t.querySelector("svg");const n=e.getAttribute("viewBox");if(n){this.viewBox=n}this.element.innerHTML="";while(e.childNodes.length>0){this.element.appendChild(e.childNodes[0])}}}_colorFillPaths(){if(this.fillColor){this.element.querySelectorAll(".ck-icon__fill").forEach((t=>{t.style.fill=this.fillColor}))}}}var Xb=n(19);var tw={injectType:"singletonStyleTag",attributes:{"data-cke":true}};tw.insert="head";tw.singleton=true;var ew=rk()(Xb["a"],tw);var nw=Xb["a"].locals||{};class ow extends tb{constructor(t){super(t);this.set("text","");this.set("position","s");const e=this.bindTemplate;this.setTemplate({tag:"span",attributes:{class:["ck","ck-tooltip",e.to("position",(t=>"ck-tooltip_"+t)),e.if("text","ck-hidden",(t=>!t.trim()))]},children:[{tag:"span",attributes:{class:["ck","ck-tooltip__text"]},children:[{text:e.to("text")}]}]})}}var iw=n(20);var rw={injectType:"singletonStyleTag",attributes:{"data-cke":true}};rw.insert="head";rw.singleton=true;var sw=rk()(iw["a"],rw);var aw=iw["a"].locals||{};class cw extends tb{constructor(t){super(t);const e=this.bindTemplate;const n=ns();this.set("class");this.set("labelStyle");this.set("icon");this.set("isEnabled",true);this.set("isOn",false);this.set("isVisible",true);this.set("isToggleable",false);this.set("keystroke");this.set("label");this.set("tabindex",-1);this.set("tooltip");this.set("tooltipPosition","s");this.set("type","button");this.set("withText",false);this.set("withKeystroke",false);this.children=this.createCollection();this.tooltipView=this._createTooltipView();this.labelView=this._createLabelView(n);this.iconView=new Zb;this.iconView.extendTemplate({attributes:{class:"ck-button__icon"}});this.keystrokeView=this._createKeystrokeView();this.bind("_tooltipString").to(this,"tooltip",this,"label",this,"keystroke",this._getTooltipString.bind(this));this.setTemplate({tag:"button",attributes:{class:["ck","ck-button",e.to("class"),e.if("isEnabled","ck-disabled",(t=>!t)),e.if("isVisible","ck-hidden",(t=>!t)),e.to("isOn",(t=>t?"ck-on":"ck-off")),e.if("withText","ck-button_with-text"),e.if("withKeystroke","ck-button_with-keystroke")],type:e.to("type",(t=>t?t:"button")),tabindex:e.to("tabindex"),"aria-labelledby":`ck-editor__aria-label_${n}`,"aria-disabled":e.if("isEnabled",true,(t=>!t)),"aria-pressed":e.to("isOn",(t=>this.isToggleable?String(t):false))},children:this.children,on:{mousedown:e.to((t=>{t.preventDefault()})),click:e.to((t=>{if(this.isEnabled){this.fire("execute")}else{t.preventDefault()}}))}})}render(){super.render();if(this.icon){this.iconView.bind("content").to(this,"icon");this.children.add(this.iconView)}this.children.add(this.tooltipView);this.children.add(this.labelView);if(this.withKeystroke){this.children.add(this.keystrokeView)}}focus(){this.element.focus()}_createTooltipView(){const t=new ow;t.bind("text").to(this,"_tooltipString");t.bind("position").to(this,"tooltipPosition");return t}_createLabelView(t){const e=new tb;const n=this.bindTemplate;e.setTemplate({tag:"span",attributes:{class:["ck","ck-button__label"],style:n.to("labelStyle"),id:`ck-editor__aria-label_${t}`},children:[{text:this.bindTemplate.to("label")}]});return e}_createKeystrokeView(){const t=new tb;t.setTemplate({tag:"span",attributes:{class:["ck","ck-button__keystroke"]},children:[{text:this.bindTemplate.to("keystroke",(t=>jl(t)))}]});return t}_getTooltipString(t,e,n){if(t){if(typeof t=="string"){return t}else{if(n){n=jl(n)}if(t instanceof Function){return t(e,n)}else{return`${e}${n?` (${n})`:""}`}}}return""}}var lw='';class dw extends cw{constructor(t){super(t);this.arrowView=this._createArrowView();this.extendTemplate({attributes:{"aria-haspopup":true}});this.delegate("execute").to(this,"open")}render(){super.render();this.children.add(this.arrowView)}_createArrowView(){const t=new Zb;t.content=lw;t.extendTemplate({attributes:{class:"ck-dropdown__arrow"}});return t}}var uw=n(21);var hw={injectType:"singletonStyleTag",attributes:{"data-cke":true}};hw.insert="head";hw.singleton=true;var fw=rk()(uw["a"],hw);var mw=uw["a"].locals||{};class gw extends tb{constructor(){super();this.items=this.createCollection();this.focusTracker=new tk;this.keystrokes=new Vp;this._focusCycler=new Db({focusables:this.items,focusTracker:this.focusTracker,keystrokeHandler:this.keystrokes,actions:{focusPrevious:"arrowup",focusNext:"arrowdown"}});this.setTemplate({tag:"ul",attributes:{class:["ck","ck-reset","ck-list"]},children:this.items})}render(){super.render();for(const t of this.items){this.focusTracker.add(t.element)}this.items.on("add",((t,e)=>{this.focusTracker.add(e.element)}));this.items.on("remove",((t,e)=>{this.focusTracker.remove(e.element)}));this.keystrokes.listenTo(this.element)}focus(){this._focusCycler.focusFirst()}focusLast(){this._focusCycler.focusLast()}}class pw extends tb{constructor(t){super(t);this.children=this.createCollection();this.setTemplate({tag:"li",attributes:{class:["ck","ck-list__item"]},children:this.children})}focus(){this.children.first.focus()}}class kw extends tb{constructor(t){super(t);this.setTemplate({tag:"li",attributes:{class:["ck","ck-list__separator"]}})}}var bw=n(22);var ww={injectType:"singletonStyleTag",attributes:{"data-cke":true}};ww.insert="head";ww.singleton=true;var Cw=rk()(bw["a"],ww);var Aw=bw["a"].locals||{};class _w extends cw{constructor(t){super(t);this.isToggleable=true;this.toggleSwitchView=this._createToggleView();this.extendTemplate({attributes:{class:"ck-switchbutton"}})}render(){super.render();this.children.add(this.toggleSwitchView)}_createToggleView(){const t=new tb;t.setTemplate({tag:"span",attributes:{class:["ck","ck-button__toggle"]},children:[{tag:"span",attributes:{class:["ck","ck-button__toggle__inner"]}}]});return t}}function vw({emitter:t,activator:e,callback:n,contextElements:o}){t.listenTo(document,"mousedown",((t,i)=>{if(!e()){return}const r=typeof i.composedPath=="function"?i.composedPath():[];for(const t of o){if(t.contains(i.target)||r.includes(t)){return}}n()}))}var yw=n(23);var xw={injectType:"singletonStyleTag",attributes:{"data-cke":true}};xw.insert="head";xw.singleton=true;var Dw=rk()(yw["a"],xw);var Ew=yw["a"].locals||{};var Mw=n(24);var Tw={injectType:"singletonStyleTag",attributes:{"data-cke":true}};Tw.insert="head";Tw.singleton=true;var Sw=rk()(Mw["a"],Tw);var Iw=Mw["a"].locals||{};function Nw(t,e=dw){const n=new e(t);const o=new Pb(t);const i=new qb(t,n,o);n.bind("isEnabled").to(i);if(n instanceof dw){n.bind("isOn").to(i,"isOpen")}else{n.arrowView.bind("isOn").to(i,"isOpen")}zw(i);return i}function Bw(t,e){const n=t.locale;const o=n.t;const i=t.toolbarView=new Gw(n);i.set("ariaLabel",o("Dropdown toolbar"));t.extendTemplate({attributes:{class:["ck-toolbar-dropdown"]}});e.map((t=>i.items.add(t)));t.panelView.children.add(i);i.items.delegate("execute").to(t)}function Pw(t,e){const n=t.locale;const o=t.listView=new gw(n);o.items.bindTo(e).using((({type:t,model:e})=>{if(t==="separator"){return new kw(n)}else if(t==="button"||t==="switchbutton"){const o=new pw(n);let i;if(t==="button"){i=new cw(n)}else{i=new _w(n)}i.bind(...Object.keys(e)).to(e);i.delegate("execute").to(o);o.children.add(i);return o}}));t.panelView.children.add(o);o.items.delegate("execute").to(t)}function zw(t){Lw(t);Ow(t);Rw(t)}function Lw(t){t.on("render",(()=>{vw({emitter:t,activator:()=>t.isOpen,callback:()=>{t.isOpen=false},contextElements:[t.element]})}))}function Ow(t){t.on("execute",(e=>{if(e.source instanceof _w){return}t.isOpen=false}))}function Rw(t){t.keystrokes.set("arrowdown",((e,n)=>{if(t.isOpen){t.panelView.focus();n()}}));t.keystrokes.set("arrowup",((e,n)=>{if(t.isOpen){t.panelView.focusLast();n()}}))}var jw='';var Fw=n(25);var Vw={injectType:"singletonStyleTag",attributes:{"data-cke":true}};Vw.insert="head";Vw.singleton=true;var Uw=rk()(Fw["a"],Vw);var Hw=Fw["a"].locals||{};class Gw extends tb{constructor(t,e){super(t);const n=this.bindTemplate;const o=this.t;this.options=e||{};this.set("ariaLabel",o("Editor toolbar"));this.set("maxWidth","auto");this.items=this.createCollection();this.focusTracker=new tk;this.keystrokes=new Vp;this.set("class");this.set("isCompact",false);this.itemsView=new Kw(t);this.children=this.createCollection();this.children.add(this.itemsView);this.focusables=this.createCollection();this._focusCycler=new Db({focusables:this.focusables,focusTracker:this.focusTracker,keystrokeHandler:this.keystrokes,actions:{focusPrevious:["arrowleft","arrowup"],focusNext:["arrowright","arrowdown"]}});const i=["ck","ck-toolbar",n.to("class"),n.if("isCompact","ck-toolbar_compact")];if(this.options.shouldGroupWhenFull&&this.options.isFloating){i.push("ck-toolbar_floating")}this.setTemplate({tag:"div",attributes:{class:i,role:"toolbar","aria-label":n.to("ariaLabel"),style:{maxWidth:n.to("maxWidth")}},children:this.children,on:{mousedown:Bb(this)}});this._behavior=this.options.shouldGroupWhenFull?new qw(this):new Ww(this)}render(){super.render();for(const t of this.items){this.focusTracker.add(t.element)}this.items.on("add",((t,e)=>{this.focusTracker.add(e.element)}));this.items.on("remove",((t,e)=>{this.focusTracker.remove(e.element)}));this.keystrokes.listenTo(this.element);this._behavior.render(this)}destroy(){this._behavior.destroy();return super.destroy()}focus(){this._focusCycler.focusFirst()}focusLast(){this._focusCycler.focusLast()}fillFromConfig(t,e){this.items.addMany(t.map((n=>{if(n=="|"){return new Mb}else if(n=="-"){if(this.options.shouldGroupWhenFull){Object(ss["c"])("toolbarview-line-break-ignored-when-grouping-items",t)}return new Tb}else if(e.has(n)){return e.create(n)}else{Object(ss["c"])("toolbarview-item-unavailable",{name:n})}})).filter((t=>t!==undefined)))}}class Kw extends tb{constructor(t){super(t);this.children=this.createCollection();this.setTemplate({tag:"div",attributes:{class:["ck","ck-toolbar__items"]},children:this.children})}}class Ww{constructor(t){const e=t.bindTemplate;t.set("isVertical",false);t.itemsView.children.bindTo(t.items).using((t=>t));t.focusables.bindTo(t.items).using((t=>t));t.extendTemplate({attributes:{class:[e.if("isVertical","ck-toolbar_vertical")]}})}render(){}destroy(){}}class qw{constructor(t){this.view=t;this.viewChildren=t.children;this.viewFocusables=t.focusables;this.viewItemsView=t.itemsView;this.viewFocusTracker=t.focusTracker;this.viewLocale=t.locale;this.ungroupedItems=t.createCollection();this.groupedItems=t.createCollection();this.groupedItemsDropdown=this._createGroupedItemsDropdown();this.resizeObserver=null;this.cachedPadding=null;this.shouldUpdateGroupingOnNextResize=false;t.itemsView.children.bindTo(this.ungroupedItems).using((t=>t));this.ungroupedItems.on("add",this._updateFocusCycleableItems.bind(this));this.ungroupedItems.on("remove",this._updateFocusCycleableItems.bind(this));t.children.on("add",this._updateFocusCycleableItems.bind(this));t.children.on("remove",this._updateFocusCycleableItems.bind(this));t.items.on("change",((t,e)=>{const n=e.index;for(const t of e.removed){if(n>=this.ungroupedItems.length){this.groupedItems.remove(t)}else{this.ungroupedItems.remove(t)}}for(let t=n;tthis.ungroupedItems.length){this.groupedItems.add(o,t-this.ungroupedItems.length)}else{this.ungroupedItems.add(o,t)}}this._updateGrouping()}));t.extendTemplate({attributes:{class:["ck-toolbar_grouping"]}})}render(t){this.viewElement=t.element;this._enableGroupingOnResize();this._enableGroupingOnMaxWidthChange(t)}destroy(){this.groupedItemsDropdown.destroy();this.resizeObserver.destroy()}_updateGrouping(){if(!this.viewElement.ownerDocument.body.contains(this.viewElement)){return}if(!this.viewElement.offsetParent){this.shouldUpdateGroupingOnNextResize=true;return}const t=this.groupedItems.length;let e;while(this._areItemsOverflowing){this._groupLastItem();e=true}if(!e&&this.groupedItems.length){while(this.groupedItems.length&&!this._areItemsOverflowing){this._ungroupFirstItem()}if(this._areItemsOverflowing){this._groupLastItem()}}if(this.groupedItems.length!==t){this.view.fire("groupedItemsUpdate")}}get _areItemsOverflowing(){if(!this.ungroupedItems.length){return false}const t=this.viewElement;const e=this.viewLocale.uiLanguageDirection;const n=new Eh(t.lastChild);const o=new Eh(t);if(!this.cachedPadding){const n=jd.window.getComputedStyle(t);const o=e==="ltr"?"paddingRight":"paddingLeft";this.cachedPadding=Number.parseInt(n[o])}if(e==="ltr"){return n.right>o.right-this.cachedPadding}else{return n.left{if(!t||t!==e.contentRect.width||this.shouldUpdateGroupingOnNextResize){this.shouldUpdateGroupingOnNextResize=false;this._updateGrouping();t=e.contentRect.width}}));this._updateGrouping()}_enableGroupingOnMaxWidthChange(t){t.on("change:maxWidth",(()=>{this._updateGrouping()}))}_groupLastItem(){if(!this.groupedItems.length){this.viewChildren.add(new Mb);this.viewChildren.add(this.groupedItemsDropdown);this.viewFocusTracker.add(this.groupedItemsDropdown.element)}this.groupedItems.add(this.ungroupedItems.remove(this.ungroupedItems.last),0)}_ungroupFirstItem(){this.ungroupedItems.add(this.groupedItems.remove(this.groupedItems.first));if(!this.groupedItems.length){this.viewChildren.remove(this.groupedItemsDropdown);this.viewChildren.remove(this.viewChildren.last);this.viewFocusTracker.remove(this.groupedItemsDropdown.element)}}_createGroupedItemsDropdown(){const t=this.viewLocale;const e=t.t;const n=Nw(t);n.class="ck-toolbar__grouped-dropdown";n.panelPosition=t.uiLanguageDirection==="ltr"?"sw":"se";Bw(n,[]);n.buttonView.set({label:e("Show more items"),tooltip:true,icon:jw});n.toolbarView.items.bindTo(this.groupedItems).using((t=>t));return n}_updateFocusCycleableItems(){this.viewFocusables.clear();this.ungroupedItems.map((t=>{this.viewFocusables.add(t)}));if(this.groupedItems.length){this.viewFocusables.add(this.groupedItemsDropdown)}}}var Yw=n(26);var Qw={injectType:"singletonStyleTag",attributes:{"data-cke":true}};Qw.insert="head";Qw.singleton=true;var $w=rk()(Yw["a"],Qw);var Jw=Yw["a"].locals||{};class Zw extends pb{constructor(t,e,n={}){super(t);this.stickyPanel=new xb(t);this.toolbar=new Gw(t,{shouldGroupWhenFull:n.shouldToolbarGroupWhenFull});this.editable=new bb(t,e)}render(){super.render();this.stickyPanel.content.add(this.toolbar);this.top.add(this.stickyPanel);this.main.add(this.editable)}}function Xw(t){if(t instanceof HTMLTextAreaElement){return t.value}return t.innerHTML}class tC extends Hp{constructor(t,e){super(e);if(Yr(t)){this.sourceElement=t}this.data.processor=new Jp(this.data.viewDocument);this.model.document.createRoot();const n=!this.config.get("toolbar.shouldNotGroupWhenFull");const o=new Zw(this.locale,this.editing.view,{shouldToolbarGroupWhenFull:n});this.ui=new Ck(this,o);Qp(this)}destroy(){if(this.sourceElement){this.updateSourceElement()}this.ui.destroy();return super.destroy()}static create(t,e={}){return new Promise((n=>{const o=new this(t,e);n(o.initPlugins().then((()=>o.ui.init(Yr(t)?t:null))).then((()=>{if(!Yr(t)&&e.initialData){throw new ss["a"]("editor-create-initial-data",null)}const n=e.initialData||eC(t);return o.data.init(n)})).then((()=>o.fire("ready"))).then((()=>o)))}))}}_s(tC,Kp);_s(tC,Yp);function eC(t){return Yr(t)?Xw(t):t}class nC{constructor(t){this.editor=t;this.set("isEnabled",true);this._disableStack=new Set}forceDisabled(t){this._disableStack.add(t);if(this._disableStack.size==1){this.on("set:isEnabled",oC,{priority:"highest"});this.isEnabled=false}}clearForceDisabled(t){this._disableStack.delete(t);if(this._disableStack.size==0){this.off("set:isEnabled",oC);this.isEnabled=true}}destroy(){this.stopListening()}static get isContextPlugin(){return false}}_s(nC,Jc);function oC(t){t.return=false;t.stop()}class iC{constructor(t){this.editor=t;this.set("value",undefined);this.set("isEnabled",false);this._disableStack=new Set;this.decorate("execute");this.listenTo(this.editor.model.document,"change",(()=>{this.refresh()}));this.on("execute",(t=>{if(!this.isEnabled){t.stop()}}),{priority:"high"});this.listenTo(t,"change:isReadOnly",((t,e,n)=>{if(n){this.forceDisabled("readOnlyMode")}else{this.clearForceDisabled("readOnlyMode")}}))}refresh(){this.isEnabled=true}forceDisabled(t){this._disableStack.add(t);if(this._disableStack.size==1){this.on("set:isEnabled",rC,{priority:"highest"});this.isEnabled=false}}clearForceDisabled(t){this._disableStack.delete(t);if(this._disableStack.size==0){this.off("set:isEnabled",rC);this.refresh()}}execute(){}destroy(){this.stopListening()}}_s(iC,Jc);function rC(t){t.return=false;t.stop()}function sC(t){const e=t.next();if(e.done){return null}return e.value}const aC=["left","right","center","justify"];function cC(t){return aC.includes(t)}function lC(t,e){if(e.contentLanguageDirection=="rtl"){return t==="right"}else{return t==="left"}}const dC="alignment";class uC extends iC{refresh(){const t=this.editor;const e=t.locale;const n=sC(this.editor.model.document.selection.getSelectedBlocks());this.isEnabled=!!n&&this._canBeAligned(n);if(this.isEnabled&&n.hasAttribute("alignment")){this.value=n.getAttribute("alignment")}else{this.value=e.contentLanguageDirection==="rtl"?"right":"left"}}execute(t={}){const e=this.editor;const n=e.locale;const o=e.model;const i=o.document;const r=t.value;o.change((t=>{const e=Array.from(i.selection.getSelectedBlocks()).filter((t=>this._canBeAligned(t)));const o=e[0].getAttribute("alignment");const s=lC(r,n)||o===r||!r;if(s){hC(e,t)}else{fC(e,t,r)}}))}_canBeAligned(t){return this.editor.model.schema.checkAttribute(t,dC)}}function hC(t,e){for(const n of t){e.removeAttribute(dC,n)}}function fC(t,e,n){for(const o of t){e.setAttribute(dC,n,o)}}class mC extends nC{static get pluginName(){return"AlignmentEditing"}constructor(t){super(t);t.config.define("alignment",{options:[...aC]})}init(){const t=this.editor;const e=t.locale;const n=t.model.schema;const o=t.config.get("alignment.options").filter(cC);n.extend("$block",{allowAttributes:"alignment"});t.model.schema.setAttributeProperties("alignment",{isFormatting:true});const i=gC(o.filter((t=>!lC(t,e))));t.conversion.attributeToAttribute(i);t.commands.add("alignment",new uC(t))}}function gC(t){const e={model:{key:"alignment",values:t.slice()},view:{}};for(const n of t){e.view[n]={key:"style",value:{"text-align":n}}}return e}var pC='';var kC='';var bC='';var wC='';const CC=new Map([["left",pC],["right",kC],["center",bC],["justify",wC]]);class AC extends nC{get localizedOptionTitles(){const t=this.editor.t;return{left:t("Align left"),right:t("Align right"),center:t("Align center"),justify:t("Justify")}}static get pluginName(){return"AlignmentUI"}init(){const t=this.editor;const e=t.ui.componentFactory;const n=t.t;const o=t.config.get("alignment.options");o.filter(cC).forEach((t=>this._addButton(t)));e.add("alignment",(t=>{const i=Nw(t);const r=o.map((t=>e.create(`alignment:${t}`)));Bw(i,r);i.buttonView.set({label:n("Text alignment"),tooltip:true});i.toolbarView.isVertical=true;i.toolbarView.ariaLabel=n("Text alignment toolbar");i.extendTemplate({attributes:{class:"ck-alignment-dropdown"}});const s=t.contentLanguageDirection==="rtl"?kC:pC;i.buttonView.bind("icon").toMany(r,"isOn",((...t)=>{const e=t.findIndex((t=>t));if(e<0){return s}return r[e].icon}));i.bind("isEnabled").toMany(r,"isEnabled",((...t)=>t.some((t=>t))));return i}))}_addButton(t){const e=this.editor;e.ui.componentFactory.add(`alignment:${t}`,(n=>{const o=e.commands.get("alignment");const i=new cw(n);i.set({label:this.localizedOptionTitles[t],icon:CC.get(t),tooltip:true,isToggleable:true});i.bind("isEnabled").to(o);i.bind("isOn").to(o,"value",(e=>e===t));this.listenTo(i,"execute",(()=>{e.execute("alignment",{value:t});e.editing.view.focus()}));return i}))}}class _C extends nC{static get requires(){return[mC,AC]}static get pluginName(){return"Alignment"}}function vC(t,e,n,o){let i;let r=null;if(typeof o=="function"){i=o}else{r=t.commands.get(o);i=()=>{t.execute(o)}}t.model.document.on("change:data",((o,s)=>{if(r&&!r.isEnabled||!e.isEnabled){return}const a=sC(t.model.document.selection.getRanges());if(!a.isCollapsed){return}if(s.type=="transparent"){return}const c=Array.from(t.model.document.differ.getChanges());const l=c[0];if(c.length!=1||l.type!=="insert"||l.name!="$text"||l.length!=1){return}const d=l.position.parent;if(d.is("element","codeBlock")){return}if(r&&r.value===true){return}const u=d.getChild(0);const h=t.model.createRangeOn(u);if(!h.containsRange(a)&&!a.end.isEqual(h.end)){return}const f=n.exec(u.data.substr(0,a.end.offset));if(!f){return}t.model.enqueueChange((t=>{const e=t.createPositionAt(d,0);const n=t.createPositionAt(d,f[0].length);const o=new kf(e,n);const r=i({match:f});if(r!==false){t.remove(o)}o.detach()}))}))}function yC(t,e,n,o){let i;let r;if(n instanceof RegExp){i=n}else{r=n}r=r||(t=>{let e;const n=[];const o=[];while((e=i.exec(t))!==null){if(e&&e.length<4){break}let{index:t,1:i,2:r,3:s}=e;const a=i+r+s;t+=e[0].length-a.length;const c=[t,t+i.length];const l=[t+i.length+r.length,t+i.length+r.length+s.length];n.push(c);n.push(l);o.push([t+i.length,t+i.length+r.length])}return{remove:n,format:o}});t.model.document.on("change:data",((n,i)=>{if(i.type=="transparent"||!e.isEnabled){return}const s=t.model;const a=s.document.selection;if(!a.isCollapsed){return}const c=Array.from(s.document.differ.getChanges());const l=c[0];if(c.length!=1||l.type!=="insert"||l.name!="$text"||l.length!=1){return}const d=a.focus;const u=d.parent;const{text:h,range:f}=DC(s.createRange(s.createPositionAt(u,0),d),s);const m=r(h);const g=xC(f.start,m.format,s);const p=xC(f.start,m.remove,s);if(!(g.length&&p.length)){return}s.enqueueChange((t=>{const e=o(t,g);if(e===false){return}for(const e of p.reverse()){t.remove(e)}}))}))}function xC(t,e,n){return e.filter((t=>t[0]!==undefined&&t[1]!==undefined)).map((e=>n.createRange(t.getShiftedBy(e[0]),t.getShiftedBy(e[1]))))}function DC(t,e){let n=t.start;const o=Array.from(t.getItems()).reduce(((t,o)=>{if(!(o.is("$text")||o.is("$textProxy"))||o.getAttribute("code")){n=e.createPositionAfter(o);return""}return t+o.data}),"");return{text:o,range:e.createRange(n,t.end)}}class EC extends nC{static get pluginName(){return"Autoformat"}afterInit(){this._addListAutoformats();this._addBasicStylesAutoformats();this._addHeadingAutoformats();this._addBlockQuoteAutoformats();this._addCodeBlockAutoformats()}_addListAutoformats(){const t=this.editor.commands;if(t.get("bulletedList")){vC(this.editor,this,/^[*-]\s$/,"bulletedList")}if(t.get("numberedList")){vC(this.editor,this,/^1[.|)]\s$/,"numberedList")}}_addBasicStylesAutoformats(){const t=this.editor.commands;if(t.get("bold")){const t=MC(this.editor,"bold");yC(this.editor,this,/(\*\*)([^*]+)(\*\*)$/g,t);yC(this.editor,this,/(__)([^_]+)(__)$/g,t)}if(t.get("italic")){const t=MC(this.editor,"italic");yC(this.editor,this,/(?:^|[^*])(\*)([^*_]+)(\*)$/g,t);yC(this.editor,this,/(?:^|[^_])(_)([^_]+)(_)$/g,t)}if(t.get("code")){const t=MC(this.editor,"code");yC(this.editor,this,/(`)([^`]+)(`)$/g,t)}if(t.get("strikethrough")){const t=MC(this.editor,"strikethrough");yC(this.editor,this,/(~~)([^~]+)(~~)$/g,t)}}_addHeadingAutoformats(){const t=this.editor.commands.get("heading");if(t){t.modelElements.filter((t=>t.match(/^heading[1-6]$/))).forEach((e=>{const n=e[7];const o=new RegExp(`^(#{${n}})\\s$`);vC(this.editor,this,o,(()=>{if(!t.isEnabled||t.value===e){return false}this.editor.execute("heading",{value:e})}))}))}}_addBlockQuoteAutoformats(){if(this.editor.commands.get("blockQuote")){vC(this.editor,this,/^>\s$/,"blockQuote")}}_addCodeBlockAutoformats(){if(this.editor.commands.get("codeBlock")){vC(this.editor,this,/^```$/,"codeBlock")}}}function MC(t,e){return(n,o)=>{const i=t.commands.get(e);if(!i.isEnabled){return false}const r=t.model.schema.getValidRanges(o,e);for(const t of r){n.setAttribute(e,true,t)}n.removeSelectionAttribute(e)}}class TC{constructor(t){this.context=t}destroy(){this.stopListening()}static get isContextPlugin(){return true}}_s(TC,Jc);class SC extends TC{static get pluginName(){return"PendingActions"}init(){this.set("hasAny",false);this._actions=new vs({idProperty:"_id"});this._actions.delegate("add","remove").to(this)}add(t){if(typeof t!=="string"){throw new ss["a"]("pendingactions-add-invalid-message",this)}const e=Object.create(Jc);e.set("message",t);this._actions.add(e);this.hasAny=true;return e}remove(t){this._actions.remove(t);this.hasAny=!!this._actions.length}get first(){return this._actions.get(0)}[Symbol.iterator](){return this._actions[Symbol.iterator]()}}class IC{constructor(){const t=new window.FileReader;this._reader=t;this._data=undefined;this.set("loaded",0);t.onprogress=t=>{this.loaded=t.loaded}}get error(){return this._reader.error}get data(){return this._data}read(t){const e=this._reader;this.total=t.size;return new Promise(((n,o)=>{e.onload=()=>{const t=e.result;this._data=t;n(t)};e.onerror=()=>{o("error")};e.onabort=()=>{o("aborted")};this._reader.readAsDataURL(t)}))}abort(){this._reader.abort()}}_s(IC,Jc);class NC extends nC{static get pluginName(){return"FileRepository"}static get requires(){return[SC]}init(){this.loaders=new vs;this.loaders.on("add",(()=>this._updatePendingAction()));this.loaders.on("remove",(()=>this._updatePendingAction()));this._loadersMap=new Map;this._pendingAction=null;this.set("uploaded",0);this.set("uploadTotal",null);this.bind("uploadedPercent").to(this,"uploaded",this,"uploadTotal",((t,e)=>e?t/e*100:0))}getLoader(t){return this._loadersMap.get(t)||null}createLoader(t){if(!this.createUploadAdapter){Object(ss["c"])("filerepository-no-upload-adapter");return null}const e=new BC(Promise.resolve(t),this.createUploadAdapter);this.loaders.add(e);this._loadersMap.set(t,e);if(t instanceof Promise){e.file.then((t=>{this._loadersMap.set(t,e)})).catch((()=>{}))}e.on("change:uploaded",(()=>{let t=0;for(const e of this.loaders){t+=e.uploaded}this.uploaded=t}));e.on("change:uploadTotal",(()=>{let t=0;for(const e of this.loaders){if(e.uploadTotal){t+=e.uploadTotal}}this.uploadTotal=t}));return e}destroyLoader(t){const e=t instanceof BC?t:this.getLoader(t);e._destroy();this.loaders.remove(e);this._loadersMap.forEach(((t,n)=>{if(t===e){this._loadersMap.delete(n)}}))}_updatePendingAction(){const t=this.editor.plugins.get(SC);if(this.loaders.length){if(!this._pendingAction){const e=this.editor.t;const n=t=>`${e("Upload in progress")} ${parseInt(t)}%.`;this._pendingAction=t.add(n(this.uploadedPercent));this._pendingAction.bind("message").to(this,"uploadedPercent",n)}}else{t.remove(this._pendingAction);this._pendingAction=null}}}_s(NC,Jc);class BC{constructor(t,e){this.id=ns();this._filePromiseWrapper=this._createFilePromiseWrapper(t);this._adapter=e(this);this._reader=new IC;this.set("status","idle");this.set("uploaded",0);this.set("uploadTotal",null);this.bind("uploadedPercent").to(this,"uploaded",this,"uploadTotal",((t,e)=>e?t/e*100:0));this.set("uploadResponse",null)}get file(){if(!this._filePromiseWrapper){return Promise.resolve(null)}else{return this._filePromiseWrapper.promise.then((t=>this._filePromiseWrapper?t:null))}}get data(){return this._reader.data}read(){if(this.status!="idle"){throw new ss["a"]("filerepository-read-wrong-status",this)}this.status="reading";return this.file.then((t=>this._reader.read(t))).then((t=>{if(this.status!=="reading"){throw this.status}this.status="idle";return t})).catch((t=>{if(t==="aborted"){this.status="aborted";throw"aborted"}this.status="error";throw this._reader.error?this._reader.error:t}))}upload(){if(this.status!="idle"){throw new ss["a"]("filerepository-upload-wrong-status",this)}this.status="uploading";return this.file.then((()=>this._adapter.upload())).then((t=>{this.uploadResponse=t;this.status="idle";return t})).catch((t=>{if(this.status==="aborted"){throw"aborted"}this.status="error";throw t}))}abort(){const t=this.status;this.status="aborted";if(!this._filePromiseWrapper.isFulfilled){this._filePromiseWrapper.promise.catch((()=>{}));this._filePromiseWrapper.rejecter("aborted")}else if(t=="reading"){this._reader.abort()}else if(t=="uploading"&&this._adapter.abort){this._adapter.abort()}this._destroy()}_destroy(){this._filePromiseWrapper=undefined;this._reader=undefined;this._adapter=undefined;this.uploadResponse=undefined}_createFilePromiseWrapper(t){const e={};e.promise=new Promise(((n,o)=>{e.rejecter=o;e.isFulfilled=false;t.then((t=>{e.isFulfilled=true;n(t)})).catch((t=>{e.isFulfilled=true;o(t)}))}));return e}}_s(BC,Jc);class PC extends nC{static get requires(){return[NC]}static get pluginName(){return"Base64UploadAdapter"}init(){this.editor.plugins.get(NC).createUploadAdapter=t=>new zC(t)}}class zC{constructor(t){this.loader=t}upload(){return new Promise(((t,e)=>{const n=this.reader=new window.FileReader;n.addEventListener("load",(()=>{t({default:n.result})}));n.addEventListener("error",(t=>{e(t)}));n.addEventListener("abort",(()=>{e()}));this.loader.file.then((t=>{n.readAsDataURL(t)}))}))}abort(){this.reader.abort()}}class LC extends iC{refresh(){this.value=this._getValue();this.isEnabled=this._checkEnabled()}execute(t={}){const e=this.editor.model;const n=e.schema;const o=e.document.selection;const i=Array.from(o.getSelectedBlocks());const r=t.forceValue===undefined?!this.value:t.forceValue;e.change((t=>{if(!r){this._removeQuote(t,i.filter(OC))}else{const e=i.filter((t=>OC(t)||jC(n,t)));this._applyQuote(t,e)}}))}_getValue(){const t=this.editor.model.document.selection;const e=sC(t.getSelectedBlocks());return!!(e&&OC(e))}_checkEnabled(){if(this.value){return true}const t=this.editor.model.document.selection;const e=this.editor.model.schema;const n=sC(t.getSelectedBlocks());if(!n){return false}return jC(e,n)}_removeQuote(t,e){RC(t,e).reverse().forEach((e=>{if(e.start.isAtStart&&e.end.isAtEnd){t.unwrap(e.start.parent);return}if(e.start.isAtStart){const n=t.createPositionBefore(e.start.parent);t.move(e,n);return}if(!e.end.isAtEnd){t.split(e.end)}const n=t.createPositionAfter(e.end.parent);t.move(e,n)}))}_applyQuote(t,e){const n=[];RC(t,e).reverse().forEach((e=>{let o=OC(e.start);if(!o){o=t.createElement("blockQuote");t.wrap(e,o)}n.push(o)}));n.reverse().reduce(((e,n)=>{if(e.nextSibling==n){t.merge(t.createPositionAfter(e));return e}return n}))}}function OC(t){return t.parent.name=="blockQuote"?t.parent:null}function RC(t,e){let n;let o=0;const i=[];while(o{if(t.endsWith("blockQuote")&&e.name=="blockQuote"){return false}}));t.conversion.elementToElement({model:"blockQuote",view:"blockquote"});t.model.document.registerPostFixer((n=>{const o=t.model.document.differ.getChanges();for(const t of o){if(t.type=="insert"){const o=t.position.nodeAfter;if(!o){continue}if(o.is("element","blockQuote")&&o.isEmpty){n.remove(o);return true}else if(o.is("element","blockQuote")&&!e.checkChild(t.position,o)){n.unwrap(o);return true}else if(o.is("element")){const t=n.createRangeIn(o);for(const o of t.getItems()){if(o.is("element","blockQuote")&&!e.checkChild(n.createPositionBefore(o),o)){n.unwrap(o);return true}}}}else if(t.type=="remove"){const e=t.position.parent;if(e.is("element","blockQuote")&&e.isEmpty){n.remove(e);return true}}}return false}))}afterInit(){const t=this.editor;const e=t.commands.get("blockQuote");this.listenTo(this.editor.editing.view.document,"enter",((t,n)=>{const o=this.editor.model.document;const i=o.selection.getLastPosition().parent;if(o.selection.isCollapsed&&i.isEmpty&&e.value){this.editor.execute("blockQuote");this.editor.editing.view.scrollToTheSelection();n.preventDefault();t.stop()}}))}}var VC='';var UC=n(27);var HC={injectType:"singletonStyleTag",attributes:{"data-cke":true}};HC.insert="head";HC.singleton=true;var GC=rk()(UC["a"],HC);var KC=UC["a"].locals||{};class WC extends nC{init(){const t=this.editor;const e=t.t;t.ui.componentFactory.add("blockQuote",(n=>{const o=t.commands.get("blockQuote");const i=new cw(n);i.set({label:e("Block quote"),icon:VC,tooltip:true,isToggleable:true});i.bind("isOn","isEnabled").to(o,"value","isEnabled");this.listenTo(i,"execute",(()=>{t.execute("blockQuote");t.editing.view.focus()}));return i}))}}class qC extends nC{static get requires(){return[FC,WC]}static get pluginName(){return"BlockQuote"}}class YC extends iC{constructor(t,e){super(t);this.attributeKey=e}refresh(){const t=this.editor.model;const e=t.document;this.value=this._getValueFromFirstAllowedNode();this.isEnabled=t.schema.checkAttributeInSelection(e.selection,this.attributeKey)}execute(t={}){const e=this.editor.model;const n=e.document;const o=n.selection;const i=t.forceValue===undefined?!this.value:t.forceValue;e.change((t=>{if(o.isCollapsed){if(i){t.setSelectionAttribute(this.attributeKey,true)}else{t.removeSelectionAttribute(this.attributeKey)}}else{const n=e.schema.getValidRanges(o.getRanges(),this.attributeKey);for(const e of n){if(i){t.setAttribute(this.attributeKey,i,e)}else{t.removeAttribute(this.attributeKey,e)}}}}))}_getValueFromFirstAllowedNode(){const t=this.editor.model;const e=t.schema;const n=t.document.selection;if(n.isCollapsed){return n.hasAttribute(this.attributeKey)}for(const t of n.getRanges()){for(const n of t.getItems()){if(e.checkAttribute(n,this.attributeKey)){return n.hasAttribute(this.attributeKey)}}}return false}}const QC="bold";class $C extends nC{static get pluginName(){return"BoldEditing"}init(){const t=this.editor;t.model.schema.extend("$text",{allowAttributes:QC});t.model.schema.setAttributeProperties(QC,{isFormatting:true,copyOnEnter:true});t.conversion.attributeToElement({model:QC,view:"strong",upcastAlso:["b",t=>{const e=t.getStyle("font-weight");if(!e){return null}if(e=="bold"||Number(e)>=600){return{name:true,styles:["font-weight"]}}}]});t.commands.add(QC,new YC(t,QC));t.keystrokes.set("CTRL+B",QC)}}var JC='';const ZC="bold";class XC extends nC{init(){const t=this.editor;const e=t.t;t.ui.componentFactory.add(ZC,(n=>{const o=t.commands.get(ZC);const i=new cw(n);i.set({label:e("Bold"),icon:JC,keystroke:"CTRL+B",tooltip:true,isToggleable:true});i.bind("isOn","isEnabled").to(o,"value","isEnabled");this.listenTo(i,"execute",(()=>{t.execute(ZC);t.editing.view.focus()}));return i}))}}class tA extends nC{static get requires(){return[$C,XC]}static get pluginName(){return"Bold"}}var eA='';class nA extends nC{static get pluginName(){return"CKFinderUI"}init(){const t=this.editor;const e=t.ui.componentFactory;const n=t.t;e.add("ckfinder",(e=>{const o=t.commands.get("ckfinder");const i=new cw(e);i.set({label:n("Insert image or file"),icon:eA,tooltip:true});i.bind("isEnabled").to(o);i.on("execute",(()=>{t.execute("ckfinder");t.editing.view.focus()}));return i}))}}class oA extends tu{observe(t){this.listenTo(t,"load",((t,e)=>{const n=e.target;if(this.checkShouldIgnoreEventFromTarget(n)){return}if(n.tagName=="IMG"){this._fireEvents(e)}}),{useCapture:true})}_fireEvents(t){if(this.isEnabled){this.document.fire("layoutChanged");this.document.fire("imageLoaded",t)}}}class iA{constructor(){this._stack=[]}add(t,e){const n=this._stack;const o=n[0];this._insertDescriptor(t);const i=n[0];if(o!==i&&!rA(o,i)){this.fire("change:top",{oldDescriptor:o,newDescriptor:i,writer:e})}}remove(t,e){const n=this._stack;const o=n[0];this._removeDescriptor(t);const i=n[0];if(o!==i&&!rA(o,i)){this.fire("change:top",{oldDescriptor:o,newDescriptor:i,writer:e})}}_insertDescriptor(t){const e=this._stack;const n=e.findIndex((e=>e.id===t.id));if(rA(t,e[n])){return}if(n>-1){e.splice(n,1)}let o=0;while(e[o]&&sA(e[o],t)){o++}e.splice(o,0,t)}_removeDescriptor(t){const e=this._stack;const n=e.findIndex((e=>e.id===t));if(n>-1){e.splice(n,1)}}}_s(iA,ds);function rA(t,e){return t&&e&&t.priority==e.priority&&aA(t.classes)==aA(e.classes)}function sA(t,e){if(t.priority>e.priority){return true}else if(t.priorityaA(e.classes)}function aA(t){return Array.isArray(t)?t.sort().join(","):t}var cA=n(28);var lA={injectType:"singletonStyleTag",attributes:{"data-cke":true}};lA.insert="head";lA.singleton=true;var dA=rk()(cA["a"],lA);var uA=cA["a"].locals||{};const hA=wb("px");const fA=jd.document.body;class mA extends tb{constructor(t){super(t);const e=this.bindTemplate;this.set("top",0);this.set("left",0);this.set("position","arrow_nw");this.set("isVisible",false);this.set("withArrow",true);this.set("class");this.content=this.createCollection();this.setTemplate({tag:"div",attributes:{class:["ck","ck-balloon-panel",e.to("position",(t=>`ck-balloon-panel_${t}`)),e.if("isVisible","ck-balloon-panel_visible"),e.if("withArrow","ck-balloon-panel_with-arrow"),e.to("class")],style:{top:e.to("top",hA),left:e.to("left",hA)}},children:this.content})}show(){this.isVisible=true}hide(){this.isVisible=false}attachTo(t){this.show();const e=mA.defaultPositions;const n=Object.assign({},{element:this.element,positions:[e.southArrowNorth,e.southArrowNorthMiddleWest,e.southArrowNorthMiddleEast,e.southArrowNorthWest,e.southArrowNorthEast,e.northArrowSouth,e.northArrowSouthMiddleWest,e.northArrowSouthMiddleEast,e.northArrowSouthWest,e.northArrowSouthEast],limiter:fA,fitInViewport:true},t);const o=mA._getOptimalPosition(n);const i=parseInt(o.left);const r=parseInt(o.top);const s=o.name;Object.assign(this,{top:r,left:i,position:s})}pin(t){this.unpin();this._pinWhenIsVisibleCallback=()=>{if(this.isVisible){this._startPinning(t)}else{this._stopPinning()}};this._startPinning(t);this.listenTo(this,"change:isVisible",this._pinWhenIsVisibleCallback)}unpin(){if(this._pinWhenIsVisibleCallback){this._stopPinning();this.stopListening(this,"change:isVisible",this._pinWhenIsVisibleCallback);this._pinWhenIsVisibleCallback=null;this.hide()}}_startPinning(t){this.attachTo(t);const e=gA(t.target);const n=t.limiter?gA(t.limiter):fA;this.listenTo(jd.document,"scroll",((o,i)=>{const r=i.target;const s=e&&r.contains(e);const a=n&&r.contains(n);if(s||a||!e||!n){this.attachTo(t)}}),{useCapture:true});this.listenTo(jd.window,"resize",(()=>{this.attachTo(t)}))}_stopPinning(){this.stopListening(jd.document,"scroll");this.stopListening(jd.window,"resize")}}function gA(t){if(Yr(t)){return t}if(yh(t)){return t.commonAncestorContainer}if(typeof t=="function"){return gA(t())}return null}mA.arrowHorizontalOffset=25;mA.arrowVerticalOffset=10;mA._getOptimalPosition=Fb;mA.defaultPositions={northWestArrowSouthWest:(t,e)=>({top:pA(t,e),left:t.left-mA.arrowHorizontalOffset,name:"arrow_sw"}),northWestArrowSouthMiddleWest:(t,e)=>({top:pA(t,e),left:t.left-e.width*.25-mA.arrowHorizontalOffset,name:"arrow_smw"}),northWestArrowSouth:(t,e)=>({top:pA(t,e),left:t.left-e.width/2,name:"arrow_s"}),northWestArrowSouthMiddleEast:(t,e)=>({top:pA(t,e),left:t.left-e.width*.75+mA.arrowHorizontalOffset,name:"arrow_sme"}),northWestArrowSouthEast:(t,e)=>({top:pA(t,e),left:t.left-e.width+mA.arrowHorizontalOffset,name:"arrow_se"}),northArrowSouthWest:(t,e)=>({top:pA(t,e),left:t.left+t.width/2-mA.arrowHorizontalOffset,name:"arrow_sw"}),northArrowSouthMiddleWest:(t,e)=>({top:pA(t,e),left:t.left+t.width/2-e.width*.25-mA.arrowHorizontalOffset,name:"arrow_smw"}),northArrowSouth:(t,e)=>({top:pA(t,e),left:t.left+t.width/2-e.width/2,name:"arrow_s"}),northArrowSouthMiddleEast:(t,e)=>({top:pA(t,e),left:t.left+t.width/2-e.width*.75+mA.arrowHorizontalOffset,name:"arrow_sme"}),northArrowSouthEast:(t,e)=>({top:pA(t,e),left:t.left+t.width/2-e.width+mA.arrowHorizontalOffset,name:"arrow_se"}),northEastArrowSouthWest:(t,e)=>({top:pA(t,e),left:t.right-mA.arrowHorizontalOffset,name:"arrow_sw"}),northEastArrowSouthMiddleWest:(t,e)=>({top:pA(t,e),left:t.right-e.width*.25-mA.arrowHorizontalOffset,name:"arrow_smw"}),northEastArrowSouth:(t,e)=>({top:pA(t,e),left:t.right-e.width/2,name:"arrow_s"}),northEastArrowSouthMiddleEast:(t,e)=>({top:pA(t,e),left:t.right-e.width*.75+mA.arrowHorizontalOffset,name:"arrow_sme"}),northEastArrowSouthEast:(t,e)=>({top:pA(t,e),left:t.right-e.width+mA.arrowHorizontalOffset,name:"arrow_se"}),southWestArrowNorthWest:(t,e)=>({top:kA(t,e),left:t.left-mA.arrowHorizontalOffset,name:"arrow_nw"}),southWestArrowNorthMiddleWest:(t,e)=>({top:kA(t,e),left:t.left-e.width*.25-mA.arrowHorizontalOffset,name:"arrow_nmw"}),southWestArrowNorth:(t,e)=>({top:kA(t,e),left:t.left-e.width/2,name:"arrow_n"}),southWestArrowNorthMiddleEast:(t,e)=>({top:kA(t,e),left:t.left-e.width*.75+mA.arrowHorizontalOffset,name:"arrow_nme"}),southWestArrowNorthEast:(t,e)=>({top:kA(t,e),left:t.left-e.width+mA.arrowHorizontalOffset,name:"arrow_ne"}),southArrowNorthWest:(t,e)=>({top:kA(t,e),left:t.left+t.width/2-mA.arrowHorizontalOffset,name:"arrow_nw"}),southArrowNorthMiddleWest:(t,e)=>({top:kA(t,e),left:t.left+t.width/2-e.width*.25-mA.arrowHorizontalOffset,name:"arrow_nmw"}),southArrowNorth:(t,e)=>({top:kA(t,e),left:t.left+t.width/2-e.width/2,name:"arrow_n"}),southArrowNorthMiddleEast:(t,e)=>({top:kA(t,e),left:t.left+t.width/2-e.width*.75+mA.arrowHorizontalOffset,name:"arrow_nme"}),southArrowNorthEast:(t,e)=>({top:kA(t,e),left:t.left+t.width/2-e.width+mA.arrowHorizontalOffset,name:"arrow_ne"}),southEastArrowNorthWest:(t,e)=>({top:kA(t,e),left:t.right-mA.arrowHorizontalOffset,name:"arrow_nw"}),southEastArrowNorthMiddleWest:(t,e)=>({top:kA(t,e),left:t.right-e.width*.25-mA.arrowHorizontalOffset,name:"arrow_nmw"}),southEastArrowNorth:(t,e)=>({top:kA(t,e),left:t.right-e.width/2,name:"arrow_n"}),southEastArrowNorthMiddleEast:(t,e)=>({top:kA(t,e),left:t.right-e.width*.75+mA.arrowHorizontalOffset,name:"arrow_nme"}),southEastArrowNorthEast:(t,e)=>({top:kA(t,e),left:t.right-e.width+mA.arrowHorizontalOffset,name:"arrow_ne"})};function pA(t,e){return t.top-e.height-mA.arrowVerticalOffset}function kA(t){return t.bottom+mA.arrowVerticalOffset}var bA='';const wA="widget-type-around";function CA(t,e,n){return t&&EA(t)&&!n.isInline(e)}function AA(t){return t.closest(".ck-widget__type-around__button")}function _A(t){return t.classList.contains("ck-widget__type-around__button_before")?"before":"after"}function vA(t,e){const n=t.closest(".ck-widget");return e.mapDomToView(n)}function yA(t){return t.getAttribute(wA)}const xA="ck-widget";const DA="ck-widget_selected";function EA(t){if(!t.is("element")){return false}return!!t.getCustomProperty("widget")}function MA(t,e,n={}){if(!t.is("containerElement")){throw new ss["a"]("widget-to-widget-wrong-element-type",null,{element:t})}e.setAttribute("contenteditable","false",t);e.addClass(xA,t);e.setCustomProperty("widget",true,t);t.getFillerOffset=LA;if(n.label){SA(t,n.label,e)}if(n.hasSelectionHandle){OA(t,e)}TA(t,e,((t,e,n)=>n.addClass(xs(e.classes),t)),((t,e,n)=>n.removeClass(xs(e.classes),t)));return t}function TA(t,e,n,o){const i=new iA;i.on("change:top",((e,i)=>{if(i.oldDescriptor){o(t,i.oldDescriptor,i.writer)}if(i.newDescriptor){n(t,i.newDescriptor,i.writer)}}));e.setCustomProperty("addHighlight",((t,e,n)=>i.add(e,n)),t);e.setCustomProperty("removeHighlight",((t,e,n)=>i.remove(e,n)),t)}function SA(t,e,n){n.setCustomProperty("widgetLabel",e,t)}function IA(t){const e=t.getCustomProperty("widgetLabel");if(!e){return""}return typeof e=="function"?e():e}function NA(t,e){e.addClass(["ck-editor__editable","ck-editor__nested-editable"],t);e.setAttribute("contenteditable",t.isReadOnly?"false":"true",t);t.on("change:isReadOnly",((n,o,i)=>{e.setAttribute("contenteditable",i?"false":"true",t)}));t.on("change:isFocused",((n,o,i)=>{if(i){e.addClass("ck-editor__nested-editable_focused",t)}else{e.removeClass("ck-editor__nested-editable_focused",t)}}));return t}function BA(t,e){const n=t.getSelectedElement();if(n){const o=yA(t);if(o){return e.createPositionAt(n,o)}if(e.schema.isBlock(n)){return e.createPositionAfter(n)}}const o=t.getSelectedBlocks().next().value;if(o){if(o.isEmpty){return e.createPositionAt(o,0)}const n=e.createPositionAfter(o);if(t.focus.isTouching(n)){return n}return e.createPositionBefore(o)}return t.focus}function PA(t,e){return(n,o)=>{const{mapper:i,viewPosition:r}=o;const s=i.findMappedViewAncestor(r);if(!e(s)){return}const a=i.toModelElement(s);o.modelPosition=t.createPositionAt(a,r.isAtStart?"before":"after")}}function zA(t,e){const n=new Eh(jd.window);const o=n.getIntersection(t);const i=e.height+mA.arrowVerticalOffset;if(t.top-i>n.top||t.bottom+i{const i=o.createElement("image",e);const r=n||BA(t.document.selection,t);t.insertContent(i,r);if(i.parent){o.setSelection(i,"on")}}))}function HA(t){const e=t.schema;const n=t.document.selection;return KA(n,e,t)&&!WA(n,e)&&qA(n)}function GA(t){const e=[];for(const n of t.getChildren()){e.push(n);if(n.is("element")){e.push(...n.getChildren())}}return e.find((t=>t.is("element","img")))}function KA(t,e,n){const o=YA(t,n);return e.checkChild(o,"image")}function WA(t,e){const n=t.getSelectedElement();return n&&e.isObject(n)}function qA(t){return[...t.focus.getAncestors()].every((t=>!t.is("element","image")))}function YA(t,e){const n=BA(t,e);const o=n.parent;if(o.isEmpty&&!o.is("element","$root")){return o.parent}return o}function QA(){return e=>{e.on("element:figure",t)};function t(t,e,n){if(!n.consumable.test(e.viewItem,{name:true,classes:"image"})){return}const o=GA(e.viewItem);if(!o||!o.hasAttribute("src")||!n.consumable.test(o,{name:true})){return}const i=n.convertItem(o,e.modelCursor);const r=sC(i.modelRange.getItems());if(!r){return}n.convertChildren(e.viewItem,r);n.updateConversionResult(r,e)}}function $A(){return e=>{e.on("attribute:srcset:image",t)};function t(t,e,n){if(!n.consumable.consume(e.item,t.name)){return}const o=n.writer;const i=n.mapper.toViewElement(e.item);const r=GA(i);if(e.attributeNewValue===null){const t=e.attributeOldValue;if(t.data){o.removeAttribute("srcset",r);o.removeAttribute("sizes",r);if(t.width){o.removeAttribute("width",r)}}}else{const t=e.attributeNewValue;if(t.data){o.setAttribute("srcset",t.data,r);o.setAttribute("sizes","100vw",r);if(t.width){o.setAttribute("width",t.width,r)}}}}}function JA(t){return n=>{n.on(`attribute:${t}:image`,e)};function e(t,e,n){if(!n.consumable.consume(e.item,t.name)){return}const o=n.writer;const i=n.mapper.toViewElement(e.item);const r=GA(i);o.setAttribute(e.attributeKey,e.attributeNewValue||"",r)}}class ZA extends iC{refresh(){this.isEnabled=HA(this.editor.model)}execute(t){const e=this.editor.model;for(const n of xs(t.source)){UA(e,{src:n})}}}class XA extends nC{static get pluginName(){return"ImageEditing"}init(){const t=this.editor;const e=t.model.schema;const n=t.t;const o=t.conversion;t.editing.view.addObserver(oA);e.register("image",{isObject:true,isBlock:true,allowWhere:"$block",allowAttributes:["alt","src","srcset"]});o.for("dataDowncast").elementToElement({model:"image",view:(t,{writer:e})=>t_(e)});o.for("editingDowncast").elementToElement({model:"image",view:(t,{writer:e})=>RA(t_(e),e,n("image widget"))});o.for("downcast").add(JA("src")).add(JA("alt")).add($A());o.for("upcast").elementToElement({view:{name:"img",attributes:{src:true}},model:(t,{writer:e})=>e.createElement("image",{src:t.getAttribute("src")})}).attributeToAttribute({view:{name:"img",key:"alt"},model:"alt"}).attributeToAttribute({view:{name:"img",key:"srcset"},model:{key:"srcset",value:t=>{const e={data:t.getAttribute("srcset")};if(t.hasAttribute("width")){e.width=t.getAttribute("width")}return e}}}).add(QA());t.commands.add("imageInsert",new ZA(t))}}function t_(t){const e=t.createEmptyElement("img");const n=t.createContainerElement("figure",{class:"image"});t.insert(t.createPositionAt(n,0),e);return n}class e_ extends nh{constructor(t){super(t);this.domEventType="mousedown"}onDomEvent(t){this.fire(t.type,t)}}class n_ extends nC{static get pluginName(){return"TwoStepCaretMovement"}constructor(t){super(t);this.attributes=new Set;this._overrideUid=null}init(){const t=this.editor;const e=t.model;const n=t.editing.view;const o=t.locale;const i=e.document.selection;this.listenTo(n.document,"keydown",((t,e)=>{if(!i.isCollapsed){return}if(e.shiftKey||e.altKey||e.ctrlKey){return}const n=e.keyCode==Ll.arrowright;const r=e.keyCode==Ll.arrowleft;if(!n&&!r){return}const s=o.contentLanguageDirection;let a=false;if(s==="ltr"&&n||s==="rtl"&&r){a=this._handleForwardMovement(e)}else{a=this._handleBackwardMovement(e)}if(a===true){t.stop()}}),{priority:is.get("high")+1});this._isNextGravityRestorationSkipped=false;this.listenTo(i,"change:range",((t,e)=>{if(this._isNextGravityRestorationSkipped){this._isNextGravityRestorationSkipped=false;return}if(!this._isGravityOverridden){return}if(!e.directChange&&a_(i.getFirstPosition(),this.attributes)){return}this._restoreGravity()}))}registerAttribute(t){this.attributes.add(t)}_handleForwardMovement(t){const e=this.attributes;const n=this.editor.model;const o=n.document.selection;const i=o.getFirstPosition();if(this._isGravityOverridden){return false}if(i.isAtStart&&o_(o,e)){return false}if(a_(i,e)){r_(t);this._overrideGravity();return true}}_handleBackwardMovement(t){const e=this.attributes;const n=this.editor.model;const o=n.document.selection;const i=o.getFirstPosition();if(this._isGravityOverridden){r_(t);this._restoreGravity();i_(n,e,i);return true}else{if(i.isAtStart){if(o_(o,e)){r_(t);i_(n,e,i);return true}return false}if(s_(i,e)){if(i.isAtEnd&&!o_(o,e)&&a_(i,e)){r_(t);i_(n,e,i);return true}this._isNextGravityRestorationSkipped=true;this._overrideGravity();return false}}}get _isGravityOverridden(){return!!this._overrideUid}_overrideGravity(){this._overrideUid=this.editor.model.change((t=>t.overrideSelectionGravity()))}_restoreGravity(){this.editor.model.change((t=>{t.restoreSelectionGravity(this._overrideUid);this._overrideUid=null}))}}function o_(t,e){for(const n of e){if(t.hasAttribute(n)){return true}}return false}function i_(t,e,n){const o=n.nodeBefore;t.change((t=>{if(o){t.setSelectionAttribute(o.getAttributes())}else{t.removeSelectionAttribute(e)}}))}function r_(t){t.preventDefault()}function s_(t,e){const n=t.getShiftedBy(-1);return a_(n,e)}function a_(t,e){const{nodeBefore:n,nodeAfter:o}=t;for(const t of e){const e=n?n.getAttribute(t):undefined;const i=o?o.getAttribute(t):undefined;if(i!==e){return true}}return false}function c_(t,e,n,o){return o.createRange(l_(t,e,n,true,o),l_(t,e,n,false,o))}function l_(t,e,n,o,i){let r=t.textNode||(o?t.nodeBefore:t.nodeAfter);let s=null;while(r&&r.getAttribute(e)==n){s=r;r=o?r.previousSibling:r.nextSibling}return s?i.createPositionAt(s,o?"before":"after"):t}function d_(t,e,n,o){const i=t.editing.view;const r=new Set;i.document.registerPostFixer((i=>{const s=t.model.document.selection;let a=false;if(s.hasAttribute(e)){const c=c_(s.getFirstPosition(),e,s.getAttribute(e),t.model);const l=t.editing.mapper.toViewRange(c);for(const t of l.getItems()){if(t.is("element",n)&&!t.hasClass(o)){i.addClass(o,t);r.add(t);a=true}}}return a}));t.conversion.for("editingDowncast").add((t=>{t.on("insert",e,{priority:"highest"});t.on("remove",e,{priority:"highest"});t.on("attribute",e,{priority:"highest"});t.on("selection",e,{priority:"highest"});function e(){i.change((t=>{for(const e of r.values()){t.removeClass(o,e);r.delete(e)}}))}}))}class u_{constructor(t,e=20){this.model=t;this.size=0;this.limit=e;this.isLocked=false;this._changeCallback=(t,e)=>{if(e.type!="transparent"&&e!==this._batch){this._reset(true)}};this._selectionChangeCallback=()=>{this._reset()};this.model.document.on("change",this._changeCallback);this.model.document.selection.on("change:range",this._selectionChangeCallback);this.model.document.selection.on("change:attribute",this._selectionChangeCallback)}get batch(){if(!this._batch){this._batch=this.model.createBatch()}return this._batch}input(t){this.size+=t;if(this.size>=this.limit){this._reset(true)}}lock(){this.isLocked=true}unlock(){this.isLocked=false}destroy(){this.model.document.off("change",this._changeCallback);this.model.document.selection.off("change:range",this._selectionChangeCallback);this.model.document.selection.off("change:attribute",this._selectionChangeCallback)}_reset(t){if(!this.isLocked||t){this._batch=null;this.size=0}}}class h_ extends iC{constructor(t,e){super(t);this._buffer=new u_(t.model,e);this._batches=new WeakSet}get buffer(){return this._buffer}destroy(){super.destroy();this._buffer.destroy()}execute(t={}){const e=this.editor.model;const n=e.document;const o=t.text||"";const i=o.length;const r=t.range?e.createSelection(t.range):n.selection;const s=t.resultRange;e.enqueueChange(this._buffer.batch,(t=>{this._buffer.lock();this._batches.add(this._buffer.batch);e.deleteContent(r);if(o){e.insertContent(t.createText(o,n.selection.getAttributes()),r)}if(s){t.setSelection(s)}else if(!r.is("documentSelection")){t.setSelection(r)}this._buffer.unlock();this._buffer.input(i)}))}}function f_(t){let e=null;const n=t.model;const o=t.editing.view;const i=t.commands.get("input");if(El.isAndroid){o.document.on("beforeinput",((t,e)=>r(e)),{priority:"lowest"})}else{o.document.on("keydown",((t,e)=>r(e)),{priority:"lowest"})}o.document.on("compositionstart",s,{priority:"lowest"});o.document.on("compositionend",(()=>{e=n.createSelection(n.document.selection)}),{priority:"lowest"});function r(t){const r=n.document;const s=o.document.isComposing;const c=e&&e.isEqual(r.selection);e=null;if(!i.isEnabled){return}if(g_(t)||r.selection.isCollapsed){return}if(s&&t.keyCode===229){return}if(!s&&t.keyCode===229&&c){return}a()}function s(){const t=n.document;const e=t.selection.rangeCount===1?t.selection.getFirstRange().isFlat:true;if(t.selection.isCollapsed||e){return}a()}function a(){const t=i.buffer;t.lock();const e=t.batch;i._batches.add(e);n.enqueueChange(e,(()=>{n.deleteContent(n.document.selection)}));t.unlock()}}const m_=[Ol("arrowUp"),Ol("arrowRight"),Ol("arrowDown"),Ol("arrowLeft"),9,16,17,18,19,20,27,33,34,35,36,45,91,93,144,145,173,174,175,176,177,178,179,255];for(let t=112;t<=135;t++){m_.push(t)}function g_(t){if(t.ctrlKey){return true}return m_.includes(t.keyCode)}function p_(t,e){const n=[];let o=0;let i;t.forEach((t=>{if(t=="equal"){r();o++}else if(t=="insert"){if(s("insert")){i.values.push(e[o])}else{r();i={type:"insert",index:o,values:[e[o]]}}o++}else{if(s("delete")){i.howMany++}else{r();i={type:"delete",index:o,howMany:1}}}}));r();return n;function r(){if(i){n.push(i);i=null}}function s(t){return i&&i.type==t}}function k_(t){if(t.length==0){return false}for(const e of t){if(e.type==="children"&&!b_(e)){return true}}return false}function b_(t){if(t.newChildren.length-t.oldChildren.length!=1){return}const e=Ed(t.oldChildren,t.newChildren,w_);const n=p_(e,t.newChildren);if(n.length>1){return}const o=n[0];if(!(!!o.values[0]&&o.values[0].is("$text"))){return}return o}function w_(t,e){if(!!t&&t.is("$text")&&!!e&&e.is("$text")){return t.data===e.data}else{return t===e}}function C_(t){t.editing.view.document.on("mutations",((e,n,o)=>{new A_(t).handle(n,o)}))}class A_{constructor(t){this.editor=t;this.editing=this.editor.editing}handle(t,e){if(k_(t)){this._handleContainerChildrenMutations(t,e)}else{for(const n of t){this._handleTextMutation(n,e);this._handleTextNodeInsertion(n)}}}_handleContainerChildrenMutations(t,e){const n=__(t);if(!n){return}const o=this.editor.editing.view.domConverter;const i=o.mapViewToDom(n);const r=new Gd(this.editor.editing.view.document);const s=this.editor.data.toModel(r.domToView(i)).getChild(0);const a=this.editor.editing.mapper.toModelElement(n);if(!a){return}const c=Array.from(s.getChildren());const l=Array.from(a.getChildren());const d=c[c.length-1];const u=l[l.length-1];const h=d&&d.is("element","softBreak");const f=u&&!u.is("element","softBreak");if(h&&f){c.pop()}const m=this.editor.model.schema;if(!v_(c,m)||!v_(l,m)){return}const g=c.map((t=>t.is("$text")?t.data:"@")).join("").replace(/\u00A0/g," ");const p=l.map((t=>t.is("$text")?t.data:"@")).join("").replace(/\u00A0/g," ");if(p===g){return}const k=Ed(p,g);const{firstChangeAt:b,insertions:w,deletions:C}=y_(k);let A=null;if(e){A=this.editing.mapper.toModelRange(e.getFirstRange())}const _=g.substr(b,w);const v=this.editor.model.createRange(this.editor.model.createPositionAt(a,b),this.editor.model.createPositionAt(a,b+C));this.editor.execute("input",{text:_,range:v,resultRange:A})}_handleTextMutation(t,e){if(t.type!="text"){return}const n=t.newText.replace(/\u00A0/g," ");const o=t.oldText.replace(/\u00A0/g," ");if(o===n){return}const i=Ed(o,n);const{firstChangeAt:r,insertions:s,deletions:a}=y_(i);let c=null;if(e){c=this.editing.mapper.toModelRange(e.getFirstRange())}const l=this.editing.view.createPositionAt(t.node,r);const d=this.editing.mapper.toModelPosition(l);const u=this.editor.model.createRange(d,d.getShiftedBy(a));const h=n.substr(r,s);this.editor.execute("input",{text:h,range:u,resultRange:c})}_handleTextNodeInsertion(t){if(t.type!="children"){return}const e=b_(t);const n=this.editing.view.createPositionAt(t.node,e.index);const o=this.editing.mapper.toModelPosition(n);const i=e.values[0].data;this.editor.execute("input",{text:i.replace(/\u00A0/g," "),range:this.editor.model.createRange(o)})}}function __(t){const e=t.map((t=>t.node)).reduce(((t,e)=>t.getCommonAncestor(e,{includeSelf:true})));if(!e){return}return e.getAncestors({includeSelf:true,parentFirst:true}).find((t=>t.is("containerElement")||t.is("rootElement")))}function v_(t,e){return t.every((t=>e.isInline(t)))}function y_(t){let e=null;let n=null;for(let o=0;ot.kind==="file")).map((t=>t.getAsFile()))}class M_ extends nh{constructor(t){super(t);const e=this.document;this.domEventType=["paste","copy","cut","drop","dragover"];this.listenTo(e,"paste",n,{priority:"low"});this.listenTo(e,"drop",n,{priority:"low"});function n(t,n){n.preventDefault();const o=n.dropRange?[n.dropRange]:Array.from(e.selection.getRanges());const i=new ts(e,"clipboardInput");e.fire(i,{dataTransfer:n.dataTransfer,targetRanges:o});if(i.stop.called){n.stopPropagation()}}}onDomEvent(t){const e={dataTransfer:new D_(t.clipboardData?t.clipboardData:t.dataTransfer)};if(t.type=="drop"){e.dropRange=T_(this.view,t)}this.fire(t.type,t,e)}}function T_(t,e){const n=e.target.ownerDocument;const o=e.clientX;const i=e.clientY;let r;if(n.caretRangeFromPoint&&n.caretRangeFromPoint(o,i)){r=n.caretRangeFromPoint(o,i)}else if(e.rangeParent){r=n.createRange();r.setStart(e.rangeParent,e.rangeOffset);r.collapse(true)}if(r){return t.domConverter.domRangeToView(r)}else{return t.document.selection.getFirstRange()}}class S_ extends nC{static get pluginName(){return"PastePlainText"}init(){const t=this.editor.editing.view;const e=t.document;let n=false;t.addObserver(M_);this.listenTo(e,"keydown",((t,e)=>{n=e.shiftKey}));this.listenTo(e,"clipboardInput",((t,e)=>{if(n){e.asPlainText=true}}),{priority:"high"})}}function I_(t){t=t.replace(//g,">").replace(/\r?\n\r?\n/g,"

").replace(/\r?\n/g,"
").replace(/^\s/," ").replace(/\s$/," ").replace(/\s\s/g,"  ");if(t.includes("

")||t.includes("
")){t=`

${t}

`}return t}function N_(t){return t.replace(/(\s+)<\/span>/g,((t,e)=>{if(e.length==1){return" "}return e}))}const B_=["figcaption","li"];function P_(t){let e="";if(t.is("$text")||t.is("$textProxy")){e=t.data}else if(t.is("element","img")&&t.hasAttribute("alt")){e=t.getAttribute("alt")}else if(t.is("element","br")){e="\n"}else{let n=null;for(const o of t.getChildren()){const t=P_(o);if(n&&(n.is("containerElement")||o.is("containerElement"))){if(B_.includes(n.name)||B_.includes(o.name)){e+="\n"}else{e+="\n\n"}}e+=t;n=o}}return e}class z_ extends nC{static get pluginName(){return"Clipboard"}static get requires(){return[S_]}init(){const t=this.editor;const e=t.model.document;const n=t.editing.view;const o=n.document;this._htmlDataProcessor=new Jp(o);n.addObserver(M_);this.listenTo(o,"clipboardInput",(e=>{if(t.isReadOnly){e.stop()}}),{priority:"highest"});this.listenTo(o,"clipboardInput",((t,e)=>{const o=e.dataTransfer;let i="";if(o.getData("text/html")){i=N_(o.getData("text/html"))}else if(o.getData("text/plain")){i=I_(o.getData("text/plain"))}i=this._htmlDataProcessor.toView(i);const r=new ts(this,"inputTransformation");this.fire(r,{content:i,dataTransfer:o,asPlainText:e.asPlainText});if(r.stop.called){t.stop()}n.scrollToTheSelection()}),{priority:"low"});this.listenTo(this,"inputTransformation",((t,e)=>{if(!e.content.isEmpty){const n=this.editor.data;const o=this.editor.model;const i=n.toModel(e.content,"$clipboardHolder");if(i.childCount==0){return}o.change((t=>{const n=o.document.selection;if(e.asPlainText||L_(i,o.schema)){const e=Array.from(n.getAttributes()).filter((([t])=>o.schema.getAttributeProperties(t).isFormatting));if(!n.isCollapsed){o.deleteContent(n,{doNotAutoparagraph:true})}e.push(...n.getAttributes());const r=t.createRangeIn(i);for(const n of r.getItems()){if(n.is("$text")||n.is("$textProxy")){t.setAttributes(e,n)}}}o.insertContent(i)}));t.stop()}}),{priority:"low"});function i(n,i){const r=i.dataTransfer;i.preventDefault();const s=t.data.toView(t.model.getSelectedContent(e.selection));o.fire("clipboardOutput",{dataTransfer:r,content:s,method:n.name})}this.listenTo(o,"copy",i,{priority:"low"});this.listenTo(o,"cut",((e,n)=>{if(t.isReadOnly){n.preventDefault()}else{i(e,n)}}),{priority:"low"});this.listenTo(o,"clipboardOutput",((n,o)=>{if(!o.content.isEmpty){o.dataTransfer.setData("text/html",this._htmlDataProcessor.toData(o.content));o.dataTransfer.setData("text/plain",P_(o.content))}if(o.method=="cut"){t.model.deleteContent(e.selection)}}),{priority:"low"})}}function L_(t,e){if(t.childCount>1){return false}const n=t.getChild(0);if(e.isObject(n)){return false}return[...n.getAttributeKeys()].length==0}class O_{constructor(){this._definitions=new Set}get length(){return this._definitions.size}add(t){if(Array.isArray(t)){t.forEach((t=>this._definitions.add(t)))}else{this._definitions.add(t)}}getDispatcher(){return t=>{t.on("attribute:linkHref",((t,e,n)=>{if(!n.consumable.test(e.item,"attribute:linkHref")){return}const o=n.writer;const i=o.document.selection;for(const t of this._definitions){const r=o.createAttributeElement("a",t.attributes,{priority:5});o.setCustomProperty("link",true,r);if(t.callback(e.attributeNewValue)){if(e.item.is("selection")){o.wrap(i.getFirstRange(),r)}else{o.wrap(n.mapper.toViewRange(e.range),r)}}else{o.unwrap(n.mapper.toViewRange(e.range),r)}}}),{priority:"high"})}}getDispatcherForLinkedImage(){return t=>{t.on("attribute:linkHref:image",((t,e,n)=>{const o=n.mapper.toViewElement(e.item);const i=Array.from(o.getChildren()).find((t=>t.name==="a"));for(const t of this._definitions){const o=Gs(t.attributes);if(t.callback(e.attributeNewValue)){for(const[t,e]of o){if(t==="class"){n.writer.addClass(e,i)}else{n.writer.setAttribute(t,e,i)}}}else{for(const[t,e]of o){if(t==="class"){n.writer.removeClass(e,i)}else{n.writer.removeAttribute(t,i)}}}}}))}}}function R_(t,e,n){var o=t.length;n=n===undefined?o:n;return!e&&n>=o?t:Ba(t,e,n)}var j_=R_;var F_="\\ud800-\\udfff",V_="\\u0300-\\u036f",U_="\\ufe20-\\ufe2f",H_="\\u20d0-\\u20ff",G_=V_+U_+H_,K_="\\ufe0e\\ufe0f";var W_="\\u200d";var q_=RegExp("["+W_+F_+G_+K_+"]");function Y_(t){return q_.test(t)}var Q_=Y_;function $_(t){return t.split("")}var J_=$_;var Z_="\\ud800-\\udfff",X_="\\u0300-\\u036f",tv="\\ufe20-\\ufe2f",ev="\\u20d0-\\u20ff",nv=X_+tv+ev,ov="\\ufe0e\\ufe0f";var iv="["+Z_+"]",rv="["+nv+"]",sv="\\ud83c[\\udffb-\\udfff]",av="(?:"+rv+"|"+sv+")",cv="[^"+Z_+"]",lv="(?:\\ud83c[\\udde6-\\uddff]){2}",dv="[\\ud800-\\udbff][\\udc00-\\udfff]",uv="\\u200d";var hv=av+"?",fv="["+ov+"]?",mv="(?:"+uv+"(?:"+[cv,lv,dv].join("|")+")"+fv+hv+")*",gv=fv+hv+mv,pv="(?:"+[cv+rv+"?",rv,lv,dv,iv].join("|")+")";var kv=RegExp(sv+"(?="+sv+")|"+pv+gv,"g");function bv(t){return t.match(kv)||[]}var wv=bv;function Cv(t){return Q_(t)?wv(t):J_(t)}var Av=Cv;function _v(t){return function(e){e=_a(e);var n=Q_(e)?Av(e):undefined;var o=n?n[0]:e.charAt(0);var i=n?j_(n,1).join(""):e.slice(1);return o[t]()+i}}var vv=_v;var yv=vv("toUpperCase");var xv=yv;const Dv=/[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205f\u3000]/g;const Ev=/^(?:(?:https?|ftps?|mailto):|[^a-z]|[a-z+.-]+(?:[^a-z+.:-]|$))/i;const Mv=/^[\S]+@((?![-_])(?:[-\w\u00a1-\uffff]{0,63}[^-_]\.))+(?:[a-z\u00a1-\uffff]{2,})$/i;const Tv=/^((\w+:(\/{2,})?)|(\W))/i;const Sv="Ctrl+K";function Iv(t){return t.is("attributeElement")&&!!t.getCustomProperty("link")}function Nv(t,{writer:e}){const n=e.createAttributeElement("a",{href:t},{priority:5});e.setCustomProperty("link",true,n);return n}function Bv(t){t=String(t);return Pv(t)?t:"#"}function Pv(t){const e=t.replace(Dv,"");return e.match(Ev)}function zv(t,e){const n={"Open in a new tab":t("Open in a new tab"),Downloadable:t("Downloadable")};e.forEach((t=>{if(t.label&&n[t.label]){t.label=n[t.label]}return t}));return e}function Lv(t){const e=[];if(t){for(const[n,o]of Object.entries(t)){const t=Object.assign({},o,{id:`link${xv(n)}`});e.push(t)}}return e}function Ov(t,e){if(!t){return false}return t.is("element","image")&&e.checkAttribute("image","linkHref")}function Rv(t){return Mv.test(t)}function jv(t,e){const n=Rv(t)?"mailto:":e;const o=!!n&&!Tv.test(t);return t&&o?n+t:t}class Fv extends iC{constructor(t){super(t);this.manualDecorators=new vs;this.automaticDecorators=new O_}restoreManualDecoratorStates(){for(const t of this.manualDecorators){t.value=this._getDecoratorStateFromModel(t.id)}}refresh(){const t=this.editor.model;const e=t.document;const n=sC(e.selection.getSelectedBlocks());if(Ov(n,t.schema)){this.value=n.getAttribute("linkHref");this.isEnabled=t.schema.checkAttribute(n,"linkHref")}else{this.value=e.selection.getAttribute("linkHref");this.isEnabled=t.schema.checkAttributeInSelection(e.selection,"linkHref")}for(const t of this.manualDecorators){t.value=this._getDecoratorStateFromModel(t.id)}}execute(t,e={}){const n=this.editor.model;const o=n.document.selection;const i=[];const r=[];for(const t in e){if(e[t]){i.push(t)}else{r.push(t)}}n.change((e=>{if(o.isCollapsed){const s=o.getFirstPosition();if(o.hasAttribute("linkHref")){const a=c_(s,"linkHref",o.getAttribute("linkHref"),n);e.setAttribute("linkHref",t,a);i.forEach((t=>{e.setAttribute(t,true,a)}));r.forEach((t=>{e.removeAttribute(t,a)}));e.setSelection(e.createPositionAfter(a.end.nodeBefore))}else if(t!==""){const r=Gs(o.getAttributes());r.set("linkHref",t);i.forEach((t=>{r.set(t,true)}));const{end:a}=n.insertContent(e.createText(t,r),s);e.setSelection(a)}["linkHref",...i,...r].forEach((t=>{e.removeSelectionAttribute(t)}))}else{const s=n.schema.getValidRanges(o.getRanges(),"linkHref");const a=[];for(const t of o.getSelectedBlocks()){if(n.schema.checkAttribute(t,"linkHref")){a.push(e.createRangeOn(t))}}const c=a.slice();for(const t of s){if(this._isRangeToUpdate(t,a)){c.push(t)}}for(const n of c){e.setAttribute("linkHref",t,n);i.forEach((t=>{e.setAttribute(t,true,n)}));r.forEach((t=>{e.removeAttribute(t,n)}))}}}))}_getDecoratorStateFromModel(t){const e=this.editor.model;const n=e.document;const o=sC(n.selection.getSelectedBlocks());if(Ov(o,e.schema)){return o.getAttribute(t)}return n.selection.getAttribute(t)}_isRangeToUpdate(t,e){for(const n of e){if(n.containsRange(t)){return false}}return true}}class Vv extends iC{refresh(){const t=this.editor.model;const e=t.document;const n=sC(e.selection.getSelectedBlocks());if(Ov(n,t.schema)){this.isEnabled=t.schema.checkAttribute(n,"linkHref")}else{this.isEnabled=t.schema.checkAttributeInSelection(e.selection,"linkHref")}}execute(){const t=this.editor;const e=this.editor.model;const n=e.document.selection;const o=t.commands.get("link");e.change((t=>{const i=n.isCollapsed?[c_(n.getFirstPosition(),"linkHref",n.getAttribute("linkHref"),e)]:e.schema.getValidRanges(n.getRanges(),"linkHref");for(const e of i){t.removeAttribute("linkHref",e);if(o){for(const n of o.manualDecorators){t.removeAttribute(n.id,e)}}}}))}}class Uv{constructor({id:t,label:e,attributes:n,defaultValue:o}){this.id=t;this.set("value");this.defaultValue=o;this.label=e;this.attributes=n}}_s(Uv,Jc);var Hv=n(29);var Gv={injectType:"singletonStyleTag",attributes:{"data-cke":true}};Gv.insert="head";Gv.singleton=true;var Kv=rk()(Hv["a"],Gv);var Wv=Hv["a"].locals||{};const qv="ck-link_selected";const Yv="automatic";const Qv="manual";const $v=/^(https?:)?\/\//;class Jv extends nC{static get pluginName(){return"LinkEditing"}static get requires(){return[n_,x_,z_]}constructor(t){super(t);t.config.define("link",{addTargetToExternalLinks:false})}init(){const t=this.editor;t.model.schema.extend("$text",{allowAttributes:"linkHref"});t.conversion.for("dataDowncast").attributeToElement({model:"linkHref",view:Nv});t.conversion.for("editingDowncast").attributeToElement({model:"linkHref",view:(t,e)=>Nv(Bv(t),e)});t.conversion.for("upcast").elementToAttribute({view:{name:"a",attributes:{href:true}},model:{key:"linkHref",value:t=>t.getAttribute("href")}});t.commands.add("link",new Fv(t));t.commands.add("unlink",new Vv(t));const e=zv(t.t,Lv(t.config.get("link.decorators")));this._enableAutomaticDecorators(e.filter((t=>t.mode===Yv)));this._enableManualDecorators(e.filter((t=>t.mode===Qv)));const n=t.plugins.get(n_);n.registerAttribute("linkHref");d_(t,"linkHref","a",qv);this._enableInsertContentSelectionAttributesFixer();this._enableClickingAfterLink();this._enableTypingOverLink();this._handleDeleteContentAfterLink()}_enableAutomaticDecorators(t){const e=this.editor;const n=e.commands.get("link");const o=n.automaticDecorators;if(e.config.get("link.addTargetToExternalLinks")){o.add({id:"linkIsExternal",mode:Yv,callback:t=>$v.test(t),attributes:{target:"_blank",rel:"noopener noreferrer"}})}o.add(t);if(o.length){e.conversion.for("downcast").add(o.getDispatcher())}}_enableManualDecorators(t){if(!t.length){return}const e=this.editor;const n=e.commands.get("link");const o=n.manualDecorators;t.forEach((t=>{e.model.schema.extend("$text",{allowAttributes:t.id});o.add(new Uv(t));e.conversion.for("downcast").attributeToElement({model:t.id,view:(e,{writer:n})=>{if(e){const e=o.get(t.id).attributes;const i=n.createAttributeElement("a",e,{priority:5});n.setCustomProperty("link",true,i);return i}}});e.conversion.for("upcast").elementToAttribute({view:{name:"a",attributes:o.get(t.id).attributes},model:{key:t.id}})}))}_enableInsertContentSelectionAttributesFixer(){const t=this.editor;const e=t.model;const n=e.document.selection;const o=t.commands.get("link");this.listenTo(e,"insertContent",(()=>{const t=n.anchor.nodeBefore;const i=n.anchor.nodeAfter;if(!n.hasAttribute("linkHref")){return}if(!t){return}if(!t.hasAttribute("linkHref")){return}if(i&&i.hasAttribute("linkHref")){return}e.change((t=>{Zv(t,o.manualDecorators)}))}),{priority:"low"})}_enableClickingAfterLink(){const t=this.editor;const e=t.commands.get("link");t.editing.view.addObserver(e_);let n=false;this.listenTo(t.editing.view.document,"mousedown",(()=>{n=true}));this.listenTo(t.editing.view.document,"selectionChange",(()=>{if(!n){return}n=false;const o=t.model.document.selection;if(!o.isCollapsed){return}if(!o.hasAttribute("linkHref")){return}const i=o.getFirstPosition();const r=c_(i,"linkHref",o.getAttribute("linkHref"),t.model);if(i.isTouching(r.start)||i.isTouching(r.end)){t.model.change((t=>{Zv(t,e.manualDecorators)}))}}))}_enableTypingOverLink(){const t=this.editor;const e=t.editing.view;let n;let o;this.listenTo(e.document,"delete",(()=>{o=true}),{priority:"high"});this.listenTo(t.model,"deleteContent",(()=>{const e=t.model.document.selection;if(e.isCollapsed){return}if(o){o=false;return}if(!ty(t)){return}if(Xv(t.model)){n=e.getAttributes()}}),{priority:"high"});this.listenTo(t.model,"insertContent",((e,[i])=>{o=false;if(!ty(t)){return}if(!n){return}t.model.change((t=>{for(const[e,o]of n){t.setAttribute(e,o,i)}}));n=null}),{priority:"high"})}_handleDeleteContentAfterLink(){const t=this.editor;const e=t.model;const n=e.document.selection;const o=t.editing.view;const i=t.commands.get("link");let r=false;let s=false;this.listenTo(o.document,"delete",((t,e)=>{s=e.domEvent.keyCode===Ll.backspace}),{priority:"high"});this.listenTo(e,"deleteContent",(()=>{r=false;const t=n.getFirstPosition();const o=n.getAttribute("linkHref");if(!o){return}const i=c_(t,"linkHref",o,e);r=i.containsPosition(t)||i.end.isEqual(t)}),{priority:"high"});this.listenTo(e,"deleteContent",(()=>{if(!s){return}s=false;if(r){return}t.model.enqueueChange((t=>{Zv(t,i.manualDecorators)}))}),{priority:"low"})}}function Zv(t,e){t.removeSelectionAttribute("linkHref");for(const n of e){t.removeSelectionAttribute(n.id)}}function Xv(t){const e=t.document.selection;const n=e.getFirstPosition();const o=e.getLastPosition();const i=n.nodeAfter;if(!i){return false}if(!i.is("$text")){return false}if(!i.hasAttribute("linkHref")){return false}const r=o.textNode||o.nodeBefore;if(i===r){return true}const s=c_(n,"linkHref",i.getAttribute("linkHref"),t);return s.containsRange(t.createRange(n,o),true)}function ty(t){const e=t.plugins.get("Input");return e.isInput(t.model.change((t=>t.batch)))}class ey extends TC{static get pluginName(){return"Notification"}init(){this.on("show:warning",((t,e)=>{window.alert(e.message)}),{priority:"lowest"})}showSuccess(t,e={}){this._showNotification({message:t,type:"success",namespace:e.namespace,title:e.title})}showInfo(t,e={}){this._showNotification({message:t,type:"info",namespace:e.namespace,title:e.title})}showWarning(t,e={}){this._showNotification({message:t,type:"warning",namespace:e.namespace,title:e.title})}_showNotification(t){const e=`show:${t.type}`+(t.namespace?`:${t.namespace}`:"");this.fire(e,{message:t.message,type:t.type,title:t.title||""})}}class ny extends iC{constructor(t){super(t);this.stopListening(this.editor.model.document,"change");this.listenTo(this.editor.model.document,"change",(()=>this.refresh()),{priority:"low"})}refresh(){const t=this.editor.commands.get("imageInsert");const e=this.editor.commands.get("link");this.isEnabled=t.isEnabled||e.isEnabled}execute(){const t=this.editor;const e=this.editor.config.get("ckfinder.openerMethod")||"modal";if(e!="popup"&&e!="modal"){throw new ss["a"]("ckfinder-unknown-openermethod",t)}const n=this.editor.config.get("ckfinder.options")||{};n.chooseFiles=true;const o=n.onInit;if(!n.language){n.language=t.locale.uiLanguage}n.onInit=e=>{if(o){o(e)}e.on("files:choose",(n=>{const o=n.data.files.toArray();const i=o.filter((t=>!t.isImage()));const r=o.filter((t=>t.isImage()));for(const e of i){t.execute("link",e.getUrl())}const s=[];for(const t of r){const n=t.getUrl();s.push(n?n:e.request("file:getProxyUrl",{file:t}))}if(s.length){oy(t,s)}}));e.on("file:choose:resizedImage",(e=>{const n=e.data.resizedUrl;if(!n){const e=t.plugins.get("Notification");const n=t.locale.t;e.showWarning(n("Could not obtain resized image URL."),{title:n("Selecting resized image failed"),namespace:"ckfinder"});return}oy(t,[n])}))};window.CKFinder[e](n)}}function oy(t,e){const n=t.commands.get("imageInsert");if(!n.isEnabled){const e=t.plugins.get("Notification");const n=t.locale.t;e.showWarning(n("Could not insert image at the current position."),{title:n("Inserting image failed"),namespace:"ckfinder"});return}t.execute("imageInsert",{source:e})}class iy extends nC{static get pluginName(){return"CKFinderEditing"}static get requires(){return[ey,XA,Jv]}init(){const t=this.editor;t.commands.add("ckfinder",new ny(t))}}const ry="ckCsrfToken";const sy=40;const ay="abcdefghijklmnopqrstuvwxyz0123456789";function cy(){let t=ly(ry);if(!t||t.length!=sy){t=uy(sy);dy(ry,t)}return t}function ly(t){t=t.toLowerCase();const e=document.cookie.split(";");for(const n of e){const e=n.split("=");const o=decodeURIComponent(e[0].trim().toLowerCase());if(o===t){return decodeURIComponent(e[1])}}return null}function dy(t,e){document.cookie=encodeURIComponent(t)+"="+encodeURIComponent(e)+";path=/"}function uy(t){let e="";const n=new Uint8Array(t);window.crypto.getRandomValues(n);for(let t=0;t.5?o.toUpperCase():o}return e}class hy extends nC{static get requires(){return[NC]}static get pluginName(){return"CKFinderUploadAdapter"}init(){const t=this.editor.config.get("ckfinder.uploadUrl");if(!t){return}this.editor.plugins.get(NC).createUploadAdapter=e=>new fy(e,t,this.editor.t)}}class fy{constructor(t,e,n){this.loader=t;this.url=e;this.t=n}upload(){return this.loader.file.then((t=>new Promise(((e,n)=>{this._initRequest();this._initListeners(e,n,t);this._sendRequest(t)}))))}abort(){if(this.xhr){this.xhr.abort()}}_initRequest(){const t=this.xhr=new XMLHttpRequest;t.open("POST",this.url,true);t.responseType="json"}_initListeners(t,e,n){const o=this.xhr;const i=this.loader;const r=this.t;const s=r("Cannot upload file:")+` ${n.name}.`;o.addEventListener("error",(()=>e(s)));o.addEventListener("abort",(()=>e()));o.addEventListener("load",(()=>{const n=o.response;if(!n||!n.uploaded){return e(n&&n.error&&n.error.message?n.error.message:s)}t({default:n.url})}));if(o.upload){o.upload.addEventListener("progress",(t=>{if(t.lengthComputable){i.uploadTotal=t.total;i.uploaded=t.loaded}}))}}_sendRequest(t){const e=new FormData;e.append("upload",t);e.append("ckCsrfToken",cy());this.xhr.send(e)}}class my extends nC{static get pluginName(){return"CKFinder"}static get requires(){return[iy,nA,hy]}}function*gy(t,e){for(const n of e){if(n&&t.getAttributeProperties(n[0]).copyOnEnter){yield n}}}class py extends iC{execute(){const t=this.editor.model;const e=t.document;t.change((n=>{ky(this.editor.model,n,e.selection,t.schema);this.fire("afterExecute",{writer:n})}))}}function ky(t,e,n,o){const i=n.isCollapsed;const r=n.getFirstRange();const s=r.start.parent;const a=r.end.parent;if(o.isLimit(s)||o.isLimit(a)){if(!i&&s==a){t.deleteContent(n)}return}if(i){const t=gy(e.model.schema,n.getAttributes());by(e,r.start);e.setSelectionAttribute(t)}else{const o=!(r.start.isAtStart&&r.end.isAtEnd);const i=s==a;t.deleteContent(n,{leaveUnmerged:o});if(o){if(i){by(e,n.focus)}else{e.setSelection(a,0)}}}}function by(t,e){t.split(e);t.setSelection(e.parent.nextSibling,0)}class wy extends tu{constructor(t){super(t);const e=this.document;e.on("keydown",((t,n)=>{if(this.isEnabled&&n.keyCode==Ll.enter){let o;e.once("enter",(t=>o=t),{priority:"highest"});e.fire("enter",new eh(e,n.domEvent,{isSoft:n.shiftKey}));if(o&&o.stop.called){t.stop()}}}))}observe(){}}class Cy extends nC{static get pluginName(){return"Enter"}init(){const t=this.editor;const e=t.editing.view;const n=e.document;e.addObserver(wy);t.commands.add("enter",new py(t));this.listenTo(n,"enter",((n,o)=>{o.preventDefault();if(o.isSoft){return}t.execute("enter");e.scrollToTheSelection()}),{priority:"low"})}}class Ay extends iC{execute(){const t=this.editor.model;const e=t.document;t.change((n=>{vy(t,n,e.selection);this.fire("afterExecute",{writer:n})}))}refresh(){const t=this.editor.model;const e=t.document;this.isEnabled=_y(t.schema,e.selection)}}function _y(t,e){if(e.rangeCount>1){return false}const n=e.anchor;if(!n||!t.checkChild(n,"softBreak")){return false}const o=e.getFirstRange();const i=o.start.parent;const r=o.end.parent;if((xy(i,t)||xy(r,t))&&i!==r){return false}return true}function vy(t,e,n){const o=n.isCollapsed;const i=n.getFirstRange();const r=i.start.parent;const s=i.end.parent;const a=r==s;if(o){const o=gy(t.schema,n.getAttributes());yy(t,e,i.end);e.removeSelectionAttribute(n.getAttributeKeys());e.setSelectionAttribute(o)}else{const o=!(i.start.isAtStart&&i.end.isAtEnd);t.deleteContent(n,{leaveUnmerged:o});if(a){yy(t,e,n.focus)}else{if(o){e.setSelection(s,0)}}}}function yy(t,e,n){const o=e.createElement("softBreak");t.insertContent(o,n);e.setSelection(o,"after")}function xy(t,e){if(t.is("rootElement")){return false}return e.isLimit(t)||xy(t.parent,e)}class Dy extends nC{static get pluginName(){return"ShiftEnter"}init(){const t=this.editor;const e=t.model.schema;const n=t.conversion;const o=t.editing.view;const i=o.document;e.register("softBreak",{allowWhere:"$text",isInline:true});n.for("upcast").elementToElement({model:"softBreak",view:"br"});n.for("downcast").elementToElement({model:"softBreak",view:(t,{writer:e})=>e.createEmptyElement("br")});o.addObserver(wy);t.commands.add("shiftEnter",new Ay(t));this.listenTo(i,"enter",((e,n)=>{n.preventDefault();if(!n.isSoft){return}t.execute("shiftEnter");o.scrollToTheSelection()}),{priority:"low"})}}class Ey extends iC{execute(){const t=this.editor.model;const e=t.document.selection;let n=t.schema.getLimitElement(e);if(e.containsEntireContent(n)||!My(t.schema,n)){do{n=n.parent;if(!n){return}}while(!My(t.schema,n))}t.change((t=>{t.setSelection(n,"in")}))}}function My(t,e){return t.isLimit(e)&&(t.checkChild(e,"$text")||t.checkChild(e,"paragraph"))}const Ty=Rl("Ctrl+A");class Sy extends nC{static get pluginName(){return"SelectAllEditing"}init(){const t=this.editor;const e=t.editing.view;const n=e.document;t.commands.add("selectAll",new Ey(t));this.listenTo(n,"keydown",((e,n)=>{if(Ol(n)===Ty){t.execute("selectAll");n.preventDefault()}}))}}var Iy='';class Ny extends nC{static get pluginName(){return"SelectAllUI"}init(){const t=this.editor;t.ui.componentFactory.add("selectAll",(e=>{const n=t.commands.get("selectAll");const o=new cw(e);const i=e.t;o.set({label:i("Select all"),icon:Iy,keystroke:"Ctrl+A",tooltip:true});o.bind("isOn","isEnabled").to(n,"value","isEnabled");this.listenTo(o,"execute",(()=>{t.execute("selectAll");t.editing.view.focus()}));return o}))}}class By extends nC{static get requires(){return[Sy,Ny]}static get pluginName(){return"SelectAll"}}class Py extends iC{constructor(t,e){super(t);this.direction=e;this._buffer=new u_(t.model,t.config.get("typing.undoStep"))}get buffer(){return this._buffer}execute(t={}){const e=this.editor.model;const n=e.document;e.enqueueChange(this._buffer.batch,(o=>{this._buffer.lock();const i=o.createSelection(t.selection||n.selection);const r=i.isCollapsed;if(i.isCollapsed){e.modifySelection(i,{direction:this.direction,unit:t.unit})}if(this._shouldEntireContentBeReplacedWithParagraph(t.sequence||1)){this._replaceEntireContentWithParagraph(o);return}if(i.isCollapsed){return}let s=0;i.getFirstRange().getMinimalFlatRanges().forEach((t=>{s+=gl(t.getWalker({singleCharacters:true,ignoreElementEnd:true,shallow:true}))}));e.deleteContent(i,{doNotResetEntireContent:r,direction:this.direction});this._buffer.input(s);o.setSelection(i);this._buffer.unlock()}))}_shouldEntireContentBeReplacedWithParagraph(t){if(t>1){return false}const e=this.editor.model;const n=e.document;const o=n.selection;const i=e.schema.getLimitElement(o);const r=o.isCollapsed&&o.containsEntireContent(i);if(!r){return false}if(!e.schema.checkChild(i,"paragraph")){return false}const s=i.getChild(0);if(s&&s.name==="paragraph"){return false}return true}_replaceEntireContentWithParagraph(t){const e=this.editor.model;const n=e.document;const o=n.selection;const i=e.schema.getLimitElement(o);const r=t.createElement("paragraph");t.remove(t.createRangeIn(i));t.insert(r,i);t.setSelection(r,0)}}class zy extends tu{constructor(t){super(t);const e=t.document;let n=0;e.on("keyup",((t,e)=>{if(e.keyCode==Ll.delete||e.keyCode==Ll.backspace){n=0}}));e.on("keydown",((t,e)=>{const i={};if(e.keyCode==Ll.delete){i.direction="forward";i.unit="character"}else if(e.keyCode==Ll.backspace){i.direction="backward";i.unit="codePoint"}else{return}const r=El.isMac?e.altKey:e.ctrlKey;i.unit=r?"word":i.unit;i.sequence=++n;o(t,e.domEvent,i)}));if(El.isAndroid){e.on("beforeinput",((e,n)=>{if(n.domEvent.inputType!="deleteContentBackward"){return}const i={unit:"codepoint",direction:"backward",sequence:1};const r=n.domTarget.ownerDocument.defaultView.getSelection();if(r.anchorNode==r.focusNode&&r.anchorOffset+1!=r.focusOffset){i.selectionToRemove=t.domConverter.domSelectionToView(r)}o(e,n.domEvent,i)}))}function o(t,n,o){let i;e.once("delete",(t=>i=t),{priority:Number.POSITIVE_INFINITY});e.fire("delete",new eh(e,n,o));if(i&&i.stop.called){t.stop()}}}observe(){}}class Ly extends nC{static get pluginName(){return"Delete"}init(){const t=this.editor;const e=t.editing.view;const n=e.document;e.addObserver(zy);t.commands.add("forwardDelete",new Py(t,"forward"));t.commands.add("delete",new Py(t,"backward"));this.listenTo(n,"delete",((n,o)=>{const i={unit:o.unit,sequence:o.sequence};if(o.selectionToRemove){const e=t.model.createSelection();const n=[];for(const e of o.selectionToRemove.getRanges()){n.push(t.editing.mapper.toModelRange(e))}e.setTo(n);i.selection=e}t.execute(o.direction=="forward"?"forwardDelete":"delete",i);o.preventDefault();e.scrollToTheSelection()}));if(El.isAndroid){let t=null;this.listenTo(n,"delete",((e,n)=>{const o=n.domTarget.ownerDocument.defaultView.getSelection();t={anchorNode:o.anchorNode,anchorOffset:o.anchorOffset,focusNode:o.focusNode,focusOffset:o.focusOffset}}),{priority:"lowest"});this.listenTo(n,"keyup",((e,n)=>{if(t){const e=n.domTarget.ownerDocument.defaultView.getSelection();e.collapse(t.anchorNode,t.anchorOffset);e.extend(t.focusNode,t.focusOffset);t=null}}))}}}class Oy extends nC{static get requires(){return[x_,Ly]}static get pluginName(){return"Typing"}}const Ry=new Map;function jy(t,e,n){let o=Ry.get(t);if(!o){o=new Map;Ry.set(t,o)}o.set(e,n)}function Fy(t,e){const n=Ry.get(t);if(n&&n.has(e)){return n.get(e)}return Vy}function Vy(t){return[t]}function Uy(t,e,n={}){const o=Fy(t.constructor,e.constructor);try{t=t.clone();return o(t,e,n)}catch(t){throw t}}function Hy(t,e,n){t=t.slice();e=e.slice();const o=new Gy(n.document,n.useRelations,n.forceWeakRemove);o.setOriginalOperations(t);o.setOriginalOperations(e);const i=o.originalOperations;if(t.length==0||e.length==0){return{operationsA:t,operationsB:e,originalOperations:i}}const r=new WeakMap;for(const e of t){r.set(e,0)}const s={nextBaseVersionA:t[t.length-1].baseVersion+1,nextBaseVersionB:e[e.length-1].baseVersion+1,originalOperationsACount:t.length,originalOperationsBCount:e.length};let a=0;while(a{if(t.key===e.key&&t.range.start.hasSameParentAs(e.range.start)){const o=t.range.getDifference(e.range).map((e=>new Ag(e,t.key,t.oldValue,t.newValue,0)));const i=t.range.getIntersection(e.range);if(i){if(n.aIsStrong){o.push(new Ag(i,e.key,e.newValue,t.newValue,0))}}if(o.length==0){return[new Zg(0)]}return o}else{return[t]}}));jy(Ag,yg,((t,e)=>{if(t.range.start.hasSameParentAs(e.position)&&t.range.containsPosition(e.position)){const n=t.range._getTransformedByInsertion(e.position,e.howMany,!e.shouldReceiveAttributes);const o=n.map((e=>new Ag(e,t.key,t.oldValue,t.newValue,t.baseVersion)));if(e.shouldReceiveAttributes){const n=qy(e,t.key,t.oldValue);if(n){o.unshift(n)}}return o}t.range=t.range._getTransformedByInsertion(e.position,e.howMany,false)[0];return[t]}));function qy(t,e,n){const o=t.nodes;const i=o.getNode(0).getAttribute(e);if(i==n){return null}const r=new ef(t.position,t.position.getShiftedBy(t.howMany));return new Ag(r,e,i,n,0)}jy(Ag,Mg,((t,e)=>{const n=[];if(t.range.start.hasSameParentAs(e.deletionPosition)){if(t.range.containsPosition(e.deletionPosition)||t.range.start.isEqual(e.deletionPosition)){n.push(ef._createFromPositionAndShift(e.graveyardPosition,1))}}const o=t.range._getTransformedByMergeOperation(e);if(!o.isCollapsed){n.push(o)}return n.map((e=>new Ag(e,t.key,t.oldValue,t.newValue,t.baseVersion)))}));jy(Ag,vg,((t,e)=>{const n=Yy(t.range,e);return n.map((e=>new Ag(e,t.key,t.oldValue,t.newValue,t.baseVersion)))}));function Yy(t,e){const n=ef._createFromPositionAndShift(e.sourcePosition,e.howMany);let o=null;let i=[];if(n.containsRange(t,true)){o=t}else if(t.start.hasSameParentAs(n.start)){i=t.getDifference(n);o=t.getIntersection(n)}else{i=[t]}const r=[];for(let t of i){t=t._getTransformedByDeletion(e.sourcePosition,e.howMany);const n=e.getMovedRangeStart();const o=t.start.hasSameParentAs(n);t=t._getTransformedByInsertion(n,e.howMany,o);r.push(...t)}if(o){r.push(o._getTransformedByMove(e.sourcePosition,e.targetPosition,e.howMany,false)[0])}return r}jy(Ag,Tg,((t,e)=>{if(t.range.end.isEqual(e.insertionPosition)){if(!e.graveyardPosition){t.range.end.offset++}return[t]}if(t.range.start.hasSameParentAs(e.splitPosition)&&t.range.containsPosition(e.splitPosition)){const n=t.clone();n.range=new ef(e.moveTargetPosition.clone(),t.range.end._getCombined(e.splitPosition,e.moveTargetPosition));t.range.end=e.splitPosition.clone();t.range.end.stickiness="toPrevious";return[t,n]}t.range=t.range._getTransformedBySplitOperation(e);return[t]}));jy(yg,Ag,((t,e)=>{const n=[t];if(t.shouldReceiveAttributes&&t.position.hasSameParentAs(e.range.start)&&e.range.containsPosition(t.position)){const o=qy(t,e.key,e.newValue);if(o){n.push(o)}}return n}));jy(yg,yg,((t,e,n)=>{if(t.position.isEqual(e.position)&&n.aIsStrong){return[t]}t.position=t.position._getTransformedByInsertOperation(e);return[t]}));jy(yg,vg,((t,e)=>{t.position=t.position._getTransformedByMoveOperation(e);return[t]}));jy(yg,Tg,((t,e)=>{t.position=t.position._getTransformedBySplitOperation(e);return[t]}));jy(yg,Mg,((t,e)=>{t.position=t.position._getTransformedByMergeOperation(e);return[t]}));jy(xg,yg,((t,e)=>{if(t.oldRange){t.oldRange=t.oldRange._getTransformedByInsertOperation(e)[0]}if(t.newRange){t.newRange=t.newRange._getTransformedByInsertOperation(e)[0]}return[t]}));jy(xg,xg,((t,e,n)=>{if(t.name==e.name){if(n.aIsStrong){t.oldRange=e.newRange?e.newRange.clone():null}else{return[new Zg(0)]}}return[t]}));jy(xg,Mg,((t,e)=>{if(t.oldRange){t.oldRange=t.oldRange._getTransformedByMergeOperation(e)}if(t.newRange){t.newRange=t.newRange._getTransformedByMergeOperation(e)}return[t]}));jy(xg,vg,((t,e,n)=>{if(t.oldRange){t.oldRange=ef._createFromRanges(t.oldRange._getTransformedByMoveOperation(e))}if(t.newRange){if(n.abRelation){const o=ef._createFromRanges(t.newRange._getTransformedByMoveOperation(e));if(n.abRelation.side=="left"&&e.targetPosition.isEqual(t.newRange.start)){t.newRange.start.path=n.abRelation.path;t.newRange.end=o.end;return[t]}else if(n.abRelation.side=="right"&&e.targetPosition.isEqual(t.newRange.end)){t.newRange.start=o.start;t.newRange.end.path=n.abRelation.path;return[t]}}t.newRange=ef._createFromRanges(t.newRange._getTransformedByMoveOperation(e))}return[t]}));jy(xg,Tg,((t,e,n)=>{if(t.oldRange){t.oldRange=t.oldRange._getTransformedBySplitOperation(e)}if(t.newRange){if(n.abRelation){const o=t.newRange._getTransformedBySplitOperation(e);if(t.newRange.start.isEqual(e.splitPosition)&&n.abRelation.wasStartBeforeMergedElement){t.newRange.start=Jh._createAt(e.insertionPosition)}else if(t.newRange.start.isEqual(e.splitPosition)&&!n.abRelation.wasInLeftElement){t.newRange.start=Jh._createAt(e.moveTargetPosition)}if(t.newRange.end.isEqual(e.splitPosition)&&n.abRelation.wasInRightElement){t.newRange.end=Jh._createAt(e.moveTargetPosition)}else if(t.newRange.end.isEqual(e.splitPosition)&&n.abRelation.wasEndBeforeMergedElement){t.newRange.end=Jh._createAt(e.insertionPosition)}else{t.newRange.end=o.end}return[t]}t.newRange=t.newRange._getTransformedBySplitOperation(e)}return[t]}));jy(Mg,yg,((t,e)=>{if(t.sourcePosition.hasSameParentAs(e.position)){t.howMany+=e.howMany}t.sourcePosition=t.sourcePosition._getTransformedByInsertOperation(e);t.targetPosition=t.targetPosition._getTransformedByInsertOperation(e);return[t]}));jy(Mg,Mg,((t,e,n)=>{if(t.sourcePosition.isEqual(e.sourcePosition)&&t.targetPosition.isEqual(e.targetPosition)){if(!n.bWasUndone){return[new Zg(0)]}else{const n=e.graveyardPosition.path.slice();n.push(0);t.sourcePosition=new Jh(e.graveyardPosition.root,n);t.howMany=0;return[t]}}if(t.sourcePosition.isEqual(e.sourcePosition)&&!t.targetPosition.isEqual(e.targetPosition)&&!n.bWasUndone&&n.abRelation!="splitAtSource"){const o=t.targetPosition.root.rootName=="$graveyard";const i=e.targetPosition.root.rootName=="$graveyard";const r=o&&!i;const s=i&&!o;const a=s||!r&&n.aIsStrong;if(a){const n=e.targetPosition._getTransformedByMergeOperation(e);const o=t.targetPosition._getTransformedByMergeOperation(e);return[new vg(n,t.howMany,o,0)]}else{return[new Zg(0)]}}if(t.sourcePosition.hasSameParentAs(e.targetPosition)){t.howMany+=e.howMany}t.sourcePosition=t.sourcePosition._getTransformedByMergeOperation(e);t.targetPosition=t.targetPosition._getTransformedByMergeOperation(e);if(!t.graveyardPosition.isEqual(e.graveyardPosition)||!n.aIsStrong){t.graveyardPosition=t.graveyardPosition._getTransformedByMergeOperation(e)}return[t]}));jy(Mg,vg,((t,e,n)=>{const o=ef._createFromPositionAndShift(e.sourcePosition,e.howMany);if(e.type=="remove"&&!n.bWasUndone&&!n.forceWeakRemove){if(t.deletionPosition.hasSameParentAs(e.sourcePosition)&&o.containsPosition(t.sourcePosition)){return[new Zg(0)]}}if(t.sourcePosition.hasSameParentAs(e.targetPosition)){t.howMany+=e.howMany}if(t.sourcePosition.hasSameParentAs(e.sourcePosition)){t.howMany-=e.howMany}t.sourcePosition=t.sourcePosition._getTransformedByMoveOperation(e);t.targetPosition=t.targetPosition._getTransformedByMoveOperation(e);if(!t.graveyardPosition.isEqual(e.targetPosition)){t.graveyardPosition=t.graveyardPosition._getTransformedByMoveOperation(e)}return[t]}));jy(Mg,Tg,((t,e,n)=>{if(e.graveyardPosition){t.graveyardPosition=t.graveyardPosition._getTransformedByDeletion(e.graveyardPosition,1);if(t.deletionPosition.isEqual(e.graveyardPosition)){t.howMany=e.howMany}}if(t.targetPosition.isEqual(e.splitPosition)){const o=e.howMany!=0;const i=e.graveyardPosition&&t.deletionPosition.isEqual(e.graveyardPosition);if(o||i||n.abRelation=="mergeTargetNotMoved"){t.sourcePosition=t.sourcePosition._getTransformedBySplitOperation(e);return[t]}}if(t.sourcePosition.isEqual(e.splitPosition)){if(n.abRelation=="mergeSourceNotMoved"){t.howMany=0;t.targetPosition=t.targetPosition._getTransformedBySplitOperation(e);return[t]}if(n.abRelation=="mergeSameElement"||t.sourcePosition.offset>0){t.sourcePosition=e.moveTargetPosition.clone();t.targetPosition=t.targetPosition._getTransformedBySplitOperation(e);return[t]}}if(t.sourcePosition.hasSameParentAs(e.splitPosition)){t.howMany=e.splitPosition.offset}t.sourcePosition=t.sourcePosition._getTransformedBySplitOperation(e);t.targetPosition=t.targetPosition._getTransformedBySplitOperation(e);return[t]}));jy(vg,yg,((t,e)=>{const n=ef._createFromPositionAndShift(t.sourcePosition,t.howMany);const o=n._getTransformedByInsertOperation(e,false)[0];t.sourcePosition=o.start;t.howMany=o.end.offset-o.start.offset;if(!t.targetPosition.isEqual(e.position)){t.targetPosition=t.targetPosition._getTransformedByInsertOperation(e)}return[t]}));jy(vg,vg,((t,e,n)=>{const o=ef._createFromPositionAndShift(t.sourcePosition,t.howMany);const i=ef._createFromPositionAndShift(e.sourcePosition,e.howMany);let r=n.aIsStrong;let s=!n.aIsStrong;if(n.abRelation=="insertBefore"||n.baRelation=="insertAfter"){s=true}else if(n.abRelation=="insertAfter"||n.baRelation=="insertBefore"){s=false}let a;if(t.targetPosition.isEqual(e.targetPosition)&&s){a=t.targetPosition._getTransformedByDeletion(e.sourcePosition,e.howMany)}else{a=t.targetPosition._getTransformedByMove(e.sourcePosition,e.targetPosition,e.howMany)}if(Qy(t,e)&&Qy(e,t)){return[e.getReversed()]}const c=o.containsPosition(e.targetPosition);if(c&&o.containsRange(i,true)){o.start=o.start._getTransformedByMove(e.sourcePosition,e.targetPosition,e.howMany);o.end=o.end._getTransformedByMove(e.sourcePosition,e.targetPosition,e.howMany);return $y([o],a)}const l=i.containsPosition(t.targetPosition);if(l&&i.containsRange(o,true)){o.start=o.start._getCombined(e.sourcePosition,e.getMovedRangeStart());o.end=o.end._getCombined(e.sourcePosition,e.getMovedRangeStart());return $y([o],a)}const d=Ls(t.sourcePosition.getParentPath(),e.sourcePosition.getParentPath());if(d=="prefix"||d=="extension"){o.start=o.start._getTransformedByMove(e.sourcePosition,e.targetPosition,e.howMany);o.end=o.end._getTransformedByMove(e.sourcePosition,e.targetPosition,e.howMany);return $y([o],a)}if(t.type=="remove"&&e.type!="remove"&&!n.aWasUndone&&!n.forceWeakRemove){r=true}else if(t.type!="remove"&&e.type=="remove"&&!n.bWasUndone&&!n.forceWeakRemove){r=false}const u=[];const h=o.getDifference(i);for(const t of h){t.start=t.start._getTransformedByDeletion(e.sourcePosition,e.howMany);t.end=t.end._getTransformedByDeletion(e.sourcePosition,e.howMany);const n=Ls(t.start.getParentPath(),e.getMovedRangeStart().getParentPath())=="same";const o=t._getTransformedByInsertion(e.getMovedRangeStart(),e.howMany,n);u.push(...o)}const f=o.getIntersection(i);if(f!==null&&r){f.start=f.start._getCombined(e.sourcePosition,e.getMovedRangeStart());f.end=f.end._getCombined(e.sourcePosition,e.getMovedRangeStart());if(u.length===0){u.push(f)}else if(u.length==1){if(i.start.isBefore(o.start)||i.start.isEqual(o.start)){u.unshift(f)}else{u.push(f)}}else{u.splice(1,0,f)}}if(u.length===0){return[new Zg(t.baseVersion)]}return $y(u,a)}));jy(vg,Tg,((t,e,n)=>{let o=t.targetPosition.clone();if(!t.targetPosition.isEqual(e.insertionPosition)||!e.graveyardPosition||n.abRelation=="moveTargetAfter"){o=t.targetPosition._getTransformedBySplitOperation(e)}const i=ef._createFromPositionAndShift(t.sourcePosition,t.howMany);if(i.end.isEqual(e.insertionPosition)){if(!e.graveyardPosition){t.howMany++}t.targetPosition=o;return[t]}if(i.start.hasSameParentAs(e.splitPosition)&&i.containsPosition(e.splitPosition)){let t=new ef(e.splitPosition,i.end);t=t._getTransformedBySplitOperation(e);const n=[new ef(i.start,e.splitPosition),t];return $y(n,o)}if(t.targetPosition.isEqual(e.splitPosition)&&n.abRelation=="insertAtSource"){o=e.moveTargetPosition}if(t.targetPosition.isEqual(e.insertionPosition)&&n.abRelation=="insertBetween"){o=t.targetPosition}const r=i._getTransformedBySplitOperation(e);const s=[r];if(e.graveyardPosition){const o=i.start.isEqual(e.graveyardPosition)||i.containsPosition(e.graveyardPosition);if(t.howMany>1&&o&&!n.aWasUndone){s.push(ef._createFromPositionAndShift(e.insertionPosition,1))}}return $y(s,o)}));jy(vg,Mg,((t,e,n)=>{const o=ef._createFromPositionAndShift(t.sourcePosition,t.howMany);if(e.deletionPosition.hasSameParentAs(t.sourcePosition)&&o.containsPosition(e.sourcePosition)){if(t.type=="remove"&&!n.forceWeakRemove){if(!n.aWasUndone){const n=[];let o=e.graveyardPosition.clone();let i=e.targetPosition._getTransformedByMergeOperation(e);if(t.howMany>1){n.push(new vg(t.sourcePosition,t.howMany-1,t.targetPosition,0));o=o._getTransformedByMove(t.sourcePosition,t.targetPosition,t.howMany-1);i=i._getTransformedByMove(t.sourcePosition,t.targetPosition,t.howMany-1)}const r=e.deletionPosition._getCombined(t.sourcePosition,t.targetPosition);const s=new vg(o,1,r,0);const a=s.getMovedRangeStart().path.slice();a.push(0);const c=new Jh(s.targetPosition.root,a);i=i._getTransformedByMove(o,r,1);const l=new vg(i,e.howMany,c,0);n.push(s);n.push(l);return n}}else{if(t.howMany==1){if(!n.bWasUndone){return[new Zg(0)]}else{t.sourcePosition=e.graveyardPosition.clone();t.targetPosition=t.targetPosition._getTransformedByMergeOperation(e);return[t]}}}}const i=ef._createFromPositionAndShift(t.sourcePosition,t.howMany);const r=i._getTransformedByMergeOperation(e);t.sourcePosition=r.start;t.howMany=r.end.offset-r.start.offset;t.targetPosition=t.targetPosition._getTransformedByMergeOperation(e);return[t]}));jy(Dg,yg,((t,e)=>{t.position=t.position._getTransformedByInsertOperation(e);return[t]}));jy(Dg,Mg,((t,e)=>{if(t.position.isEqual(e.deletionPosition)){t.position=e.graveyardPosition.clone();t.position.stickiness="toNext";return[t]}t.position=t.position._getTransformedByMergeOperation(e);return[t]}));jy(Dg,vg,((t,e)=>{t.position=t.position._getTransformedByMoveOperation(e);return[t]}));jy(Dg,Dg,((t,e,n)=>{if(t.position.isEqual(e.position)){if(n.aIsStrong){t.oldName=e.newName}else{return[new Zg(0)]}}return[t]}));jy(Dg,Tg,((t,e)=>{const n=t.position.path;const o=e.splitPosition.getParentPath();if(Ls(n,o)=="same"&&!e.graveyardPosition){const e=new Dg(t.position.getShiftedBy(1),t.oldName,t.newName,0);return[t,e]}t.position=t.position._getTransformedBySplitOperation(e);return[t]}));jy(Eg,Eg,((t,e,n)=>{if(t.root===e.root&&t.key===e.key){if(!n.aIsStrong||t.newValue===e.newValue){return[new Zg(0)]}else{t.oldValue=e.newValue}}return[t]}));jy(Tg,yg,((t,e)=>{if(t.splitPosition.hasSameParentAs(e.position)&&t.splitPosition.offset{if(!t.graveyardPosition&&!n.bWasUndone&&t.splitPosition.hasSameParentAs(e.sourcePosition)){const n=e.graveyardPosition.path.slice();n.push(0);const o=new Jh(e.graveyardPosition.root,n);const i=Tg.getInsertionPosition(new Jh(e.graveyardPosition.root,n));const r=new Tg(o,0,null,0);r.insertionPosition=i;t.splitPosition=t.splitPosition._getTransformedByMergeOperation(e);t.insertionPosition=Tg.getInsertionPosition(t.splitPosition);t.graveyardPosition=r.insertionPosition.clone();t.graveyardPosition.stickiness="toNext";return[r,t]}if(t.splitPosition.hasSameParentAs(e.deletionPosition)&&!t.splitPosition.isAfter(e.deletionPosition)){t.howMany--}if(t.splitPosition.hasSameParentAs(e.targetPosition)){t.howMany+=e.howMany}t.splitPosition=t.splitPosition._getTransformedByMergeOperation(e);t.insertionPosition=Tg.getInsertionPosition(t.splitPosition);if(t.graveyardPosition){t.graveyardPosition=t.graveyardPosition._getTransformedByMergeOperation(e)}return[t]}));jy(Tg,vg,((t,e,n)=>{const o=ef._createFromPositionAndShift(e.sourcePosition,e.howMany);if(t.graveyardPosition){const i=o.start.isEqual(t.graveyardPosition)||o.containsPosition(t.graveyardPosition);if(!n.bWasUndone&&i){const n=t.splitPosition._getTransformedByMoveOperation(e);const o=t.graveyardPosition._getTransformedByMoveOperation(e);const i=o.path.slice();i.push(0);const r=new Jh(o.root,i);const s=new vg(n,t.howMany,r,0);return[s]}t.graveyardPosition=t.graveyardPosition._getTransformedByMoveOperation(e)}if(t.splitPosition.hasSameParentAs(e.sourcePosition)&&o.containsPosition(t.splitPosition)){const n=e.howMany-(t.splitPosition.offset-e.sourcePosition.offset);t.howMany-=n;if(t.splitPosition.hasSameParentAs(e.targetPosition)&&t.splitPosition.offset{if(t.splitPosition.isEqual(e.splitPosition)){if(!t.graveyardPosition&&!e.graveyardPosition){return[new Zg(0)]}if(t.graveyardPosition&&e.graveyardPosition&&t.graveyardPosition.isEqual(e.graveyardPosition)){return[new Zg(0)]}if(n.abRelation=="splitBefore"){t.howMany=0;t.graveyardPosition=t.graveyardPosition._getTransformedBySplitOperation(e);return[t]}}if(t.graveyardPosition&&e.graveyardPosition&&t.graveyardPosition.isEqual(e.graveyardPosition)){const o=t.splitPosition.root.rootName=="$graveyard";const i=e.splitPosition.root.rootName=="$graveyard";const r=o&&!i;const s=i&&!o;const a=s||!r&&n.aIsStrong;if(a){const n=[];if(e.howMany){n.push(new vg(e.moveTargetPosition,e.howMany,e.splitPosition,0))}if(t.howMany){n.push(new vg(t.splitPosition,t.howMany,t.moveTargetPosition,0))}return n}else{return[new Zg(0)]}}if(t.graveyardPosition){t.graveyardPosition=t.graveyardPosition._getTransformedBySplitOperation(e)}if(t.splitPosition.isEqual(e.insertionPosition)&&n.abRelation=="splitBefore"){t.howMany++;return[t]}if(e.splitPosition.isEqual(t.insertionPosition)&&n.baRelation=="splitBefore"){const n=e.insertionPosition.path.slice();n.push(0);const o=new Jh(e.insertionPosition.root,n);const i=new vg(t.insertionPosition,1,o,0);return[t,i]}if(t.splitPosition.hasSameParentAs(e.splitPosition)&&t.splitPosition.offsetthis.clearStack()))}refresh(){this.isEnabled=this._stack.length>0}addBatch(t){const e=this.editor.model.document.selection;const n={ranges:e.hasOwnRange?Array.from(e.getRanges()):[],isBackward:e.isBackward};this._stack.push({batch:t,selection:n});this.refresh()}clearStack(){this._stack=[];this.refresh()}_restoreSelection(t,e,n){const o=this.editor.model;const i=o.document;const r=[];const s=t.map((t=>t.getTransformedByOperations(n)));const a=s.flat();for(const t of s){const e=t.filter((t=>t.root!=i.graveyard)).filter((t=>!Xy(t,a)));if(!e.length){continue}Zy(e);r.push(e[0])}if(r.length){o.change((t=>{t.setSelection(r,{backward:e})}))}}_undo(t,e){const n=this.editor.model;const o=n.document;this._createdBatches.add(e);const i=t.operations.slice().filter((t=>t.isDocumentOperation));i.reverse();for(const t of i){const i=t.baseVersion+1;const r=Array.from(o.history.getOperations(i));const s=Hy([t.getReversed()],r,{useRelations:true,document:this.editor.model.document,padWithNoOps:false,forceWeakRemove:true});const a=s.operationsA;for(const i of a){e.addOperation(i);n.applyOperation(i);o.history.setOperationAsUndone(t,i)}}}}function Zy(t){t.sort(((t,e)=>t.start.isBefore(e.start)?-1:1));for(let e=1;ee!==t&&e.containsRange(t,true)))}class tx extends Jy{execute(t=null){const e=t?this._stack.findIndex((e=>e.batch==t)):this._stack.length-1;const n=this._stack.splice(e,1)[0];const o=this.editor.model.createBatch("transparent");this.editor.model.enqueueChange(o,(()=>{this._undo(n.batch,o);const t=this.editor.model.document.history.getOperations(n.batch.baseVersion);this._restoreSelection(n.selection.ranges,n.selection.isBackward,t);this.fire("revert",n.batch,o)}));this.refresh()}}class ex extends Jy{execute(){const t=this._stack.pop();const e=this.editor.model.createBatch("transparent");this.editor.model.enqueueChange(e,(()=>{const n=t.batch.operations[t.batch.operations.length-1];const o=n.baseVersion+1;const i=this.editor.model.document.history.getOperations(o);this._restoreSelection(t.selection.ranges,t.selection.isBackward,i);this._undo(t.batch,e)}));this.refresh()}}class nx extends nC{static get pluginName(){return"UndoEditing"}constructor(t){super(t);this._batchRegistry=new WeakSet}init(){const t=this.editor;this._undoCommand=new tx(t);this._redoCommand=new ex(t);t.commands.add("undo",this._undoCommand);t.commands.add("redo",this._redoCommand);this.listenTo(t.model,"applyOperation",((t,e)=>{const n=e[0];if(!n.isDocumentOperation){return}const o=n.batch;const i=this._redoCommand._createdBatches.has(o);const r=this._undoCommand._createdBatches.has(o);const s=this._batchRegistry.has(o);if(s||o.type=="transparent"&&!i&&!r){return}else{if(i){this._undoCommand.addBatch(o)}else if(!r){this._undoCommand.addBatch(o);this._redoCommand.clearStack()}}this._batchRegistry.add(o)}),{priority:"highest"});this.listenTo(this._undoCommand,"revert",((t,e,n)=>{this._redoCommand.addBatch(n)}));t.keystrokes.set("CTRL+Z","undo");t.keystrokes.set("CTRL+Y","redo");t.keystrokes.set("CTRL+SHIFT+Z","redo")}}var ox='';var ix='';class rx extends nC{init(){const t=this.editor;const e=t.locale;const n=t.t;const o=e.uiLanguageDirection=="ltr"?ox:ix;const i=e.uiLanguageDirection=="ltr"?ix:ox;this._addButton("undo",n("Undo"),"CTRL+Z",o);this._addButton("redo",n("Redo"),"CTRL+Y",i)}_addButton(t,e,n,o){const i=this.editor;i.ui.componentFactory.add(t,(r=>{const s=i.commands.get(t);const a=new cw(r);a.set({label:e,icon:o,keystroke:n,tooltip:true});a.bind("isEnabled").to(s,"isEnabled");this.listenTo(a,"execute",(()=>{i.execute(t);i.editing.view.focus()}));return a}))}}class sx extends nC{static get requires(){return[nx,rx]}static get pluginName(){return"Undo"}}class ax extends nC{static get requires(){return[z_,Cy,By,Dy,Oy,sx]}static get pluginName(){return"Essentials"}}class cx extends iC{constructor(t,e){super(t);this.attributeKey=e}refresh(){const t=this.editor.model;const e=t.document;this.value=e.selection.getAttribute(this.attributeKey);this.isEnabled=t.schema.checkAttributeInSelection(e.selection,this.attributeKey)}execute(t={}){const e=this.editor.model;const n=e.document;const o=n.selection;const i=t.value;e.change((t=>{if(o.isCollapsed){if(i){t.setSelectionAttribute(this.attributeKey,i)}else{t.removeSelectionAttribute(this.attributeKey)}}else{const n=e.schema.getValidRanges(o.getRanges(),this.attributeKey);for(const e of n){if(i){t.setAttribute(this.attributeKey,i,e)}else{t.removeAttribute(this.attributeKey,e)}}}}))}}var lx='';class dx extends cw{constructor(t){super(t);const e=this.bindTemplate;this.set("color");this.set("hasBorder");this.icon=lx;this.extendTemplate({attributes:{style:{backgroundColor:e.to("color")},class:["ck","ck-color-grid__tile",e.if("hasBorder","ck-color-table__color-tile_bordered")]}})}render(){super.render();this.iconView.fillColor="hsl(0, 0%, 100%)"}}var ux=n(30);var hx={injectType:"singletonStyleTag",attributes:{"data-cke":true}};hx.insert="head";hx.singleton=true;var fx=rk()(ux["a"],hx);var mx=ux["a"].locals||{};class gx extends tb{constructor(t,e){super(t);const n=e&&e.colorDefinitions||[];const o={};if(e&&e.columns){o.gridTemplateColumns=`repeat( ${e.columns}, 1fr)`}this.set("selectedColor");this.items=this.createCollection();this.focusTracker=new tk;this.keystrokes=new Vp;this._focusCycler=new Db({focusables:this.items,focusTracker:this.focusTracker,keystrokeHandler:this.keystrokes,actions:{focusPrevious:"arrowleft",focusNext:"arrowright"}});this.items.on("add",((t,e)=>{e.isOn=e.color===this.selectedColor}));n.forEach((t=>{const e=new dx;e.set({color:t.color,label:t.label,tooltip:true,hasBorder:t.options.hasBorder});e.on("execute",(()=>{this.fire("execute",{value:t.color,hasBorder:t.options.hasBorder,label:t.label})}));this.items.add(e)}));this.setTemplate({tag:"div",children:this.items,attributes:{class:["ck","ck-color-grid"],style:o}});this.on("change:selectedColor",((t,e,n)=>{for(const t of this.items){t.isOn=t.color===n}}))}focus(){if(this.items.length){this.items.first.focus()}}focusLast(){if(this.items.length){this.items.last.focus()}}render(){super.render();for(const t of this.items){this.focusTracker.add(t.element)}this.items.on("add",((t,e)=>{this.focusTracker.add(e.element)}));this.items.on("remove",((t,e)=>{this.focusTracker.remove(e.element)}));this.keystrokes.listenTo(this.element)}}class px extends vs{constructor(t){super(t);this.set("isEmpty",true);this.on("change",(()=>{this.set("isEmpty",this.length===0)}))}add(t,e){if(this.find((e=>e.color===t.color))){return}super.add(t,e)}hasColor(t){return!!this.find((e=>e.color===t))}}_s(px,Jc);var kx='';var bx=n(31);var wx={injectType:"singletonStyleTag",attributes:{"data-cke":true}};wx.insert="head";wx.singleton=true;var Cx=rk()(bx["a"],wx);var Ax=bx["a"].locals||{};class _x extends tb{constructor(t,{colors:e,columns:n,removeButtonLabel:o,documentColorsLabel:i,documentColorsCount:r}){super(t);this.items=this.createCollection();this.colorDefinitions=e;this.focusTracker=new tk;this.keystrokes=new Vp;this.set("selectedColor");this.removeButtonLabel=o;this.columns=n;this.documentColors=new px;this.documentColorsCount=r;this._focusCycler=new Db({focusables:this.items,focusTracker:this.focusTracker,keystrokeHandler:this.keystrokes,actions:{focusPrevious:"arrowup",focusNext:"arrowdown"}});this._documentColorsLabel=i;this.setTemplate({tag:"div",attributes:{class:["ck","ck-color-table"]},children:this.items});this.items.add(this._removeColorButton())}updateDocumentColors(t,e){const n=t.document;const o=this.documentColorsCount;this.documentColors.clear();for(const i of n.getRootNames()){const r=n.getRoot(i);const s=t.createRangeIn(r);for(const t of s.getItems()){if(t.is("$textProxy")&&t.hasAttribute(e)){this._addColorToDocumentColors(t.getAttribute(e));if(this.documentColors.length>=o){return}}}}}updateSelectedColors(){const t=this.documentColorsGrid;const e=this.staticColorsGrid;const n=this.selectedColor;e.selectedColor=n;if(t){t.selectedColor=n}}render(){super.render();for(const t of this.items){this.focusTracker.add(t.element)}this.keystrokes.listenTo(this.element)}appendGrids(){if(this.staticColorsGrid){return}this.staticColorsGrid=this._createStaticColorsGrid();this.items.add(this.staticColorsGrid);if(this.documentColorsCount){const t=yk.bind(this.documentColors,this.documentColors);const e=new gb(this.locale);e.text=this._documentColorsLabel;e.extendTemplate({attributes:{class:["ck","ck-color-grid__label",t.if("isEmpty","ck-hidden")]}});this.items.add(e);this.documentColorsGrid=this._createDocumentColorsGrid();this.items.add(this.documentColorsGrid)}}focus(){this._focusCycler.focusFirst()}focusLast(){this._focusCycler.focusLast()}_removeColorButton(){const t=new cw;t.set({withText:true,icon:kx,tooltip:true,label:this.removeButtonLabel});t.class="ck-color-table__remove-color";t.on("execute",(()=>{this.fire("execute",{value:null})}));return t}_createStaticColorsGrid(){const t=new gx(this.locale,{colorDefinitions:this.colorDefinitions,columns:this.columns});t.delegate("execute").to(this);return t}_createDocumentColorsGrid(){const t=yk.bind(this.documentColors,this.documentColors);const e=new gx(this.locale,{columns:this.columns});e.delegate("execute").to(this);e.extendTemplate({attributes:{class:t.if("isEmpty","ck-hidden")}});e.items.bindTo(this.documentColors).using((t=>{const e=new dx;e.set({color:t.color,hasBorder:t.options&&t.options.hasBorder});if(t.label){e.set({label:t.label,tooltip:true})}e.on("execute",(()=>{this.fire("execute",{value:t.color})}));return e}));this.documentColors.on("change:isEmpty",((t,n,o)=>{if(o){e.selectedColor=null}}));return e}_addColorToDocumentColors(t){const e=this.colorDefinitions.find((e=>e.color===t));if(!e){this.documentColors.add({color:t,label:t,options:{hasBorder:false}})}else{this.documentColors.add(Object.assign({},e))}}}const vx="fontSize";const yx="fontFamily";const xx="fontColor";const Dx="fontBackgroundColor";function Ex(t,e){const n={model:{key:t,values:[]},view:{},upcastAlso:{}};for(const t of e){n.model.values.push(t.model);n.view[t.model]=t.view;if(t.upcastAlso){n.upcastAlso[t.model]=t.upcastAlso}}return n}function Mx(t){return e=>Ix(e.getStyle(t))}function Tx(t){return(e,{writer:n})=>n.createAttributeElement("span",{style:`${t}:${e}`},{priority:7})}function Sx({dropdownView:t,colors:e,columns:n,removeButtonLabel:o,documentColorsLabel:i,documentColorsCount:r}){const s=t.locale;const a=new _x(s,{colors:e,columns:n,removeButtonLabel:o,documentColorsLabel:i,documentColorsCount:r});t.colorTableView=a;t.panelView.children.add(a);a.delegate("execute").to(t,"execute");return a}function Ix(t){return t.replace(/\s/g,"")}class Nx extends cx{constructor(t){super(t,xx)}}class Bx extends nC{static get pluginName(){return"FontColorEditing"}constructor(t){super(t);t.config.define(xx,{colors:[{color:"hsl(0, 0%, 0%)",label:"Black"},{color:"hsl(0, 0%, 30%)",label:"Dim grey"},{color:"hsl(0, 0%, 60%)",label:"Grey"},{color:"hsl(0, 0%, 90%)",label:"Light grey"},{color:"hsl(0, 0%, 100%)",label:"White",hasBorder:true},{color:"hsl(0, 75%, 60%)",label:"Red"},{color:"hsl(30, 75%, 60%)",label:"Orange"},{color:"hsl(60, 75%, 60%)",label:"Yellow"},{color:"hsl(90, 75%, 60%)",label:"Light green"},{color:"hsl(120, 75%, 60%)",label:"Green"},{color:"hsl(150, 75%, 60%)",label:"Aquamarine"},{color:"hsl(180, 75%, 60%)",label:"Turquoise"},{color:"hsl(210, 75%, 60%)",label:"Light blue"},{color:"hsl(240, 75%, 60%)",label:"Blue"},{color:"hsl(270, 75%, 60%)",label:"Purple"}],columns:5});t.conversion.for("upcast").elementToAttribute({view:{name:"span",styles:{color:/[\s\S]+/}},model:{key:xx,value:Mx("color")}});t.conversion.for("downcast").attributeToElement({model:xx,view:Tx("color")});t.commands.add(xx,new Nx(t));t.model.schema.extend("$text",{allowAttributes:xx});t.model.schema.setAttributeProperties(xx,{isFormatting:true,copyOnEnter:true})}}function Px(t,e){const n=t.t;const o={Black:n("Black"),"Dim grey":n("Dim grey"),Grey:n("Grey"),"Light grey":n("Light grey"),White:n("White"),Red:n("Red"),Orange:n("Orange"),Yellow:n("Yellow"),"Light green":n("Light green"),Green:n("Green"),Aquamarine:n("Aquamarine"),Turquoise:n("Turquoise"),"Light blue":n("Light blue"),Blue:n("Blue"),Purple:n("Purple")};return e.map((t=>{const e=o[t.label];if(e&&e!=t.label){t.label=e}return t}))}function zx(t){return t.map(Lx).filter((t=>!!t))}function Lx(t){if(typeof t==="string"){return{model:t,label:t,hasBorder:false,view:{name:"span",styles:{color:t}}}}else{return{model:t.color,label:t.label||t.color,hasBorder:t.hasBorder===undefined?false:t.hasBorder,view:{name:"span",styles:{color:`${t.color}`}}}}}class Ox extends nC{constructor(t,{commandName:e,icon:n,componentName:o,dropdownLabel:i}){super(t);this.commandName=e;this.componentName=o;this.icon=n;this.dropdownLabel=i;this.columns=t.config.get(`${this.componentName}.columns`);this.colorTableView=undefined}init(){const t=this.editor;const e=t.locale;const n=e.t;const o=t.commands.get(this.commandName);const i=zx(t.config.get(this.componentName).colors);const r=Px(e,i);const s=t.config.get(`${this.componentName}.documentColors`);t.ui.componentFactory.add(this.componentName,(e=>{const i=Nw(e);this.colorTableView=Sx({dropdownView:i,colors:r.map((t=>({label:t.label,color:t.model,options:{hasBorder:t.hasBorder}}))),columns:this.columns,removeButtonLabel:n("Remove color"),documentColorsLabel:s!==0?n("Document colors"):undefined,documentColorsCount:s===undefined?this.columns:s});this.colorTableView.bind("selectedColor").to(o,"value");i.buttonView.set({label:this.dropdownLabel,icon:this.icon,tooltip:true});i.extendTemplate({attributes:{class:"ck-color-ui-dropdown"}});i.bind("isEnabled").to(o);i.on("execute",((e,n)=>{t.execute(this.commandName,n);t.editing.view.focus()}));i.on("change:isOpen",((e,n,o)=>{i.colorTableView.appendGrids();if(o){if(s!==0){this.colorTableView.updateDocumentColors(t.model,this.componentName)}this.colorTableView.updateSelectedColors()}}));return i}))}}var Rx='';class jx extends Ox{constructor(t){const e=t.locale.t;super(t,{commandName:xx,componentName:xx,icon:Rx,dropdownLabel:e("Font Color")})}static get pluginName(){return"FontColorUI"}}class Fx extends nC{static get requires(){return[Bx,jx]}static get pluginName(){return"FontColor"}}class Vx extends cx{constructor(t){super(t,yx)}}function Ux(t){return t.map(Hx).filter((t=>!!t))}function Hx(t){if(typeof t==="object"){return t}if(t==="default"){return{title:"Default",model:undefined}}if(typeof t!=="string"){return}return Gx(t)}function Gx(t){const e=t.replace(/"|'/g,"").split(",");const n=e[0];const o=e.map(Kx).join(", ");return{title:n,model:o,view:{name:"span",styles:{"font-family":o},priority:7}}}function Kx(t){t=t.trim();if(t.indexOf(" ")>0){t=`'${t}'`}return t}class Wx extends nC{static get pluginName(){return"FontFamilyEditing"}constructor(t){super(t);t.config.define(yx,{options:["default","Arial, Helvetica, sans-serif","Courier New, Courier, monospace","Georgia, serif","Lucida Sans Unicode, Lucida Grande, sans-serif","Tahoma, Geneva, sans-serif","Times New Roman, Times, serif","Trebuchet MS, Helvetica, sans-serif","Verdana, Geneva, sans-serif"],supportAllValues:false})}init(){const t=this.editor;t.model.schema.extend("$text",{allowAttributes:yx});t.model.schema.setAttributeProperties(yx,{isFormatting:true,copyOnEnter:true});const e=Ux(t.config.get("fontFamily.options")).filter((t=>t.model));const n=Ex(yx,e);if(t.config.get("fontFamily.supportAllValues")){this._prepareAnyValueConverters()}else{t.conversion.attributeToElement(n)}t.commands.add(yx,new Vx(t))}_prepareAnyValueConverters(){const t=this.editor;t.conversion.for("downcast").attributeToElement({model:yx,view:(t,{writer:e})=>e.createAttributeElement("span",{style:"font-family:"+t},{priority:7})});t.conversion.for("upcast").attributeToAttribute({model:{key:yx,value:t=>t.getStyle("font-family")},view:{name:"span",styles:{"font-family":/.*/}}})}}class qx{constructor(t,e){if(e){Wc(this,e)}if(t){this.set(t)}}}_s(qx,Jc);var Yx='';class Qx extends nC{init(){const t=this.editor;const e=t.t;const n=this._getLocalizedOptions();const o=t.commands.get(yx);t.ui.componentFactory.add(yx,(i=>{const r=Nw(i);Pw(r,$x(n,o));r.buttonView.set({label:e("Font Family"),icon:Yx,tooltip:true});r.extendTemplate({attributes:{class:"ck-font-family-dropdown"}});r.bind("isEnabled").to(o);this.listenTo(r,"execute",(e=>{t.execute(e.source.commandName,{value:e.source.commandParam});t.editing.view.focus()}));return r}))}_getLocalizedOptions(){const t=this.editor;const e=t.t;const n=Ux(t.config.get(yx).options);return n.map((t=>{if(t.title==="Default"){t.title=e("Default")}return t}))}}function $x(t,e){const n=new vs;for(const o of t){const t={type:"button",model:new qx({commandName:yx,commandParam:o.model,label:o.title,withText:true})};t.model.bind("isOn").to(e,"value",(t=>{if(t===o.model){return true}if(!t||!o.model){return false}return t.split(",")[0].replace(/'/g,"").toLowerCase()===o.model.toLowerCase()}));if(o.view&&o.view.styles){t.model.set("labelStyle",`font-family: ${o.view.styles["font-family"]}`)}n.add(t)}return n}class Jx extends nC{static get requires(){return[Wx,Qx]}static get pluginName(){return"FontFamily"}}class Zx extends cx{constructor(t){super(t,vx)}}function Xx(t){return t.map((t=>eD(t))).filter((t=>!!t))}const tD={get tiny(){return{title:"Tiny",model:"tiny",view:{name:"span",classes:"text-tiny",priority:7}}},get small(){return{title:"Small",model:"small",view:{name:"span",classes:"text-small",priority:7}}},get big(){return{title:"Big",model:"big",view:{name:"span",classes:"text-big",priority:7}}},get huge(){return{title:"Huge",model:"huge",view:{name:"span",classes:"text-huge",priority:7}}}};function eD(t){if(rD(t)){return oD(t)}const e=iD(t);if(e){return oD(e)}if(t==="default"){return{model:undefined,title:"Default"}}if(sD(t)){return}return nD(t)}function nD(t){if(typeof t==="number"||typeof t==="string"){t={title:String(t),model:`${parseFloat(t)}px`}}t.view={name:"span",styles:{"font-size":t.model}};return oD(t)}function oD(t){if(!t.view.priority){t.view.priority=7}return t}function iD(t){return tD[t]||tD[t.model]}function rD(t){return typeof t==="object"&&t.title&&t.model&&t.view}function sD(t){let e;if(typeof t==="object"){if(!t.model){throw new ss["a"]("font-size-invalid-definition",null,t)}else{e=parseFloat(t.model)}}else{e=parseFloat(t)}return isNaN(e)}class aD extends nC{static get pluginName(){return"FontSizeEditing"}constructor(t){super(t);t.config.define(vx,{options:["tiny","small","default","big","huge"],supportAllValues:false})}init(){const t=this.editor;t.model.schema.extend("$text",{allowAttributes:vx});t.model.schema.setAttributeProperties(vx,{isFormatting:true,copyOnEnter:true});const e=t.config.get("fontSize.supportAllValues");const n=Xx(this.editor.config.get("fontSize.options")).filter((t=>t.model));const o=Ex(vx,n);if(e){this._prepareAnyValueConverters(o)}else{t.conversion.attributeToElement(o)}t.commands.add(vx,new Zx(t))}_prepareAnyValueConverters(t){const e=this.editor;const n=t.model.values.filter((t=>!String(t).match(/[\d.]+[\w%]+/)));if(n.length){throw new ss["a"]("font-size-invalid-use-of-named-presets",null,{presets:n})}e.conversion.for("downcast").attributeToElement({model:vx,view:(t,{writer:e})=>{if(!t){return}return e.createAttributeElement("span",{style:"font-size:"+t},{priority:7})}});e.conversion.for("upcast").attributeToAttribute({model:{key:vx,value:t=>t.getStyle("font-size")},view:{name:"span",styles:{"font-size":/.*/}}})}}var cD='';var lD=n(32);var dD={injectType:"singletonStyleTag",attributes:{"data-cke":true}};dD.insert="head";dD.singleton=true;var uD=rk()(lD["a"],dD);var hD=lD["a"].locals||{};class fD extends nC{init(){const t=this.editor;const e=t.t;const n=this._getLocalizedOptions();const o=t.commands.get(vx);t.ui.componentFactory.add(vx,(i=>{const r=Nw(i);Pw(r,mD(n,o));r.buttonView.set({label:e("Font Size"),icon:cD,tooltip:true});r.extendTemplate({attributes:{class:["ck-font-size-dropdown"]}});r.bind("isEnabled").to(o);this.listenTo(r,"execute",(e=>{t.execute(e.source.commandName,{value:e.source.commandParam});t.editing.view.focus()}));return r}))}_getLocalizedOptions(){const t=this.editor;const e=t.t;const n={Default:e("Default"),Tiny:e("Tiny"),Small:e("Small"),Big:e("Big"),Huge:e("Huge")};const o=Xx(t.config.get(vx).options);return o.map((t=>{const e=n[t.title];if(e&&e!=t.title){t=Object.assign({},t,{title:e})}return t}))}}function mD(t,e){const n=new vs;for(const o of t){const t={type:"button",model:new qx({commandName:vx,commandParam:o.model,label:o.title,class:"ck-fontsize-option",withText:true})};if(o.view&&o.view.styles){t.model.set("labelStyle",`font-size:${o.view.styles["font-size"]}`)}if(o.view&&o.view.classes){t.model.set("class",`${t.model.class} ${o.view.classes}`)}t.model.bind("isOn").to(e,"value",(t=>t===o.model));n.add(t)}return n}class gD extends nC{static get requires(){return[aD,fD]}static get pluginName(){return"FontSize"}}class pD extends iC{refresh(){const t=this.editor.model;const e=t.document;const n=sC(e.selection.getSelectedBlocks());this.value=!!n&&n.is("element","paragraph");this.isEnabled=!!n&&kD(n,t.schema)}execute(t={}){const e=this.editor.model;const n=e.document;e.change((o=>{const i=(t.selection||n.selection).getSelectedBlocks();for(const t of i){if(!t.is("element","paragraph")&&kD(t,e.schema)){o.rename(t,"paragraph")}}}))}}function kD(t,e){return e.checkChild(t.parent,"paragraph")&&!e.isObject(t)}class bD extends iC{execute(t){const e=this.editor.model;let n=t.position;e.change((t=>{const o=t.createElement("paragraph");if(!e.schema.checkChild(n.parent,o)){const i=e.schema.findAllowedParent(n,o);if(!i){return}n=t.split(n,i).position}e.insertContent(o,n);t.setSelection(o,"in")}))}}class wD extends nC{static get pluginName(){return"Paragraph"}init(){const t=this.editor;const e=t.model;t.commands.add("paragraph",new pD(t));t.commands.add("insertParagraph",new bD(t));e.schema.register("paragraph",{inheritAllFrom:"$block"});t.conversion.elementToElement({model:"paragraph",view:"p"});t.conversion.for("upcast").elementToElement({model:(t,{writer:e})=>{if(!wD.paragraphLikeElements.has(t.name)){return null}if(t.isEmpty){return null}return e.createElement("paragraph")},view:/.+/,converterPriority:"low"})}}wD.paragraphLikeElements=new Set(["blockquote","dd","div","dt","h1","h2","h3","h4","h5","h6","li","p","td","th"]);class CD extends iC{constructor(t,e){super(t);this.modelElements=e}refresh(){const t=sC(this.editor.model.document.selection.getSelectedBlocks());this.value=!!t&&this.modelElements.includes(t.name)&&t.name;this.isEnabled=!!t&&this.modelElements.some((e=>AD(t,e,this.editor.model.schema)))}execute(t){const e=this.editor.model;const n=e.document;const o=t.value;e.change((t=>{const i=Array.from(n.selection.getSelectedBlocks()).filter((t=>AD(t,o,e.schema)));for(const e of i){if(!e.is("element",o)){t.rename(e,o)}}}))}}function AD(t,e,n){return n.checkChild(t.parent,e)&&!n.isObject(t)}const _D="paragraph";class vD extends nC{static get pluginName(){return"HeadingEditing"}constructor(t){super(t);t.config.define("heading",{options:[{model:"paragraph",title:"Paragraph",class:"ck-heading_paragraph"},{model:"heading1",view:"h2",title:"Heading 1",class:"ck-heading_heading1"},{model:"heading2",view:"h3",title:"Heading 2",class:"ck-heading_heading2"},{model:"heading3",view:"h4",title:"Heading 3",class:"ck-heading_heading3"}]})}static get requires(){return[wD]}init(){const t=this.editor;const e=t.config.get("heading.options");const n=[];for(const o of e){if(o.model!==_D){t.model.schema.register(o.model,{inheritAllFrom:"$block"});t.conversion.elementToElement(o);n.push(o.model)}}this._addDefaultH1Conversion(t);t.commands.add("heading",new CD(t,n))}afterInit(){const t=this.editor;const e=t.commands.get("enter");const n=t.config.get("heading.options");if(e){this.listenTo(e,"afterExecute",((e,o)=>{const i=t.model.document.selection.getFirstPosition().parent;const r=n.some((t=>i.is("element",t.model)));if(r&&!i.is("element",_D)&&i.childCount===0){o.writer.rename(i,_D)}}))}}_addDefaultH1Conversion(t){t.conversion.for("upcast").elementToElement({model:"heading1",view:"h1",converterPriority:is.get("low")+1})}}function yD(t){const e=t.t;const n={Paragraph:e("Paragraph"),"Heading 1":e("Heading 1"),"Heading 2":e("Heading 2"),"Heading 3":e("Heading 3"),"Heading 4":e("Heading 4"),"Heading 5":e("Heading 5"),"Heading 6":e("Heading 6")};return t.config.get("heading.options").map((t=>{const e=n[t.title];if(e&&e!=t.title){t.title=e}return t}))}var xD=n(33);var DD={injectType:"singletonStyleTag",attributes:{"data-cke":true}};DD.insert="head";DD.singleton=true;var ED=rk()(xD["a"],DD);var MD=xD["a"].locals||{};class TD extends nC{init(){const t=this.editor;const e=t.t;const n=yD(t);const o=e("Choose heading");const i=e("Heading");t.ui.componentFactory.add("heading",(e=>{const r={};const s=new vs;const a=t.commands.get("heading");const c=t.commands.get("paragraph");const l=[a];for(const t of n){const e={type:"button",model:new qx({label:t.title,class:t.class,withText:true})};if(t.model==="paragraph"){e.model.bind("isOn").to(c,"value");e.model.set("commandName","paragraph");l.push(c)}else{e.model.bind("isOn").to(a,"value",(e=>e===t.model));e.model.set({commandName:"heading",commandValue:t.model})}s.add(e);r[t.model]=t.title}const d=Nw(e);Pw(d,s);d.buttonView.set({isOn:false,withText:true,tooltip:i});d.extendTemplate({attributes:{class:["ck-heading-dropdown"]}});d.bind("isEnabled").toMany(l,"isEnabled",((...t)=>t.some((t=>t))));d.buttonView.bind("label").to(a,"value",c,"value",((t,e)=>{const n=t||e&&"paragraph";return r[n]?r[n]:o}));this.listenTo(d,"execute",(e=>{t.execute(e.source.commandName,e.source.commandValue?{value:e.source.commandValue}:undefined);t.editing.view.focus()}));return d}))}}class SD extends nC{static get requires(){return[vD,TD]}static get pluginName(){return"Heading"}}class ID extends iC{refresh(){this.isEnabled=ND(this.editor.model)}execute(){const t=this.editor.model;t.change((e=>{const n=e.createElement("horizontalLine");t.insertContent(n);let o=n.nextSibling;const i=o&&t.schema.checkChild(o,"$text");if(!i&&t.schema.checkChild(n.parent,"paragraph")){o=e.createElement("paragraph");t.insertContent(o,e.createPositionAfter(n))}if(o){e.setSelection(o,0)}}))}}function ND(t){const e=t.schema;const n=t.document.selection;return BD(n,e,t)&&!PD(n,e)}function BD(t,e,n){const o=zD(t,n);return e.checkChild(o,"horizontalLine")}function PD(t,e){const n=t.getSelectedElement();return n&&e.isObject(n)}function zD(t,e){const n=BA(t,e);const o=n.parent;if(o.isEmpty&&!o.is("element","$root")){return o.parent}return o}var LD=n(34);var OD={injectType:"singletonStyleTag",attributes:{"data-cke":true}};OD.insert="head";OD.singleton=true;var RD=rk()(LD["a"],OD);var jD=LD["a"].locals||{};class FD extends nC{static get pluginName(){return"HorizontalLineEditing"}init(){const t=this.editor;const e=t.model.schema;const n=t.t;const o=t.conversion;e.register("horizontalLine",{isObject:true,allowWhere:"$block"});o.for("dataDowncast").elementToElement({model:"horizontalLine",view:(t,{writer:e})=>e.createEmptyElement("hr")});o.for("editingDowncast").elementToElement({model:"horizontalLine",view:(t,{writer:e})=>{const o=n("Horizontal line");const i=e.createContainerElement("div");const r=e.createEmptyElement("hr");e.addClass("ck-horizontal-line",i);e.setCustomProperty("hr",true,i);e.insert(e.createPositionAt(i,0),r);return VD(i,e,o)}});o.for("upcast").elementToElement({view:"hr",model:"horizontalLine"});t.commands.add("horizontalLine",new ID(t))}}function VD(t,e,n){e.setCustomProperty("horizontalLine",true,t);return MA(t,e,{label:n})}var UD='';class HD extends nC{init(){const t=this.editor;const e=t.t;t.ui.componentFactory.add("horizontalLine",(n=>{const o=t.commands.get("horizontalLine");const i=new cw(n);i.set({label:e("Horizontal line"),icon:UD,tooltip:true});i.bind("isEnabled").to(o,"isEnabled");this.listenTo(i,"execute",(()=>{t.execute("horizontalLine");t.editing.view.focus()}));return i}))}}class GD extends nC{static get requires(){return[FD,HD]}static get pluginName(){return"HorizontalLine"}}var KD='';var WD=n(35);var qD={injectType:"singletonStyleTag",attributes:{"data-cke":true}};qD.insert="head";qD.singleton=true;var YD=rk()(WD["a"],qD);var QD=WD["a"].locals||{};const $D=["before","after"];const JD=(new DOMParser).parseFromString(KD,"image/svg+xml").firstChild;const ZD="ck-widget__type-around_disabled";class XD extends nC{static get pluginName(){return"WidgetTypeAround"}constructor(t){super(t);this._currentFakeCaretModelElement=null}init(){const t=this.editor;const e=t.editing.view;this.on("change:isEnabled",((n,o,i)=>{e.change((t=>{for(const n of e.document.roots){if(i){t.removeClass(ZD,n)}else{t.addClass(ZD,n)}}}));if(!i){t.model.change((t=>{t.removeSelectionAttribute(wA)}))}}));this._enableTypeAroundUIInjection();this._enableInsertingParagraphsOnButtonClick();this._enableInsertingParagraphsOnEnterKeypress();this._enableInsertingParagraphsOnTypingKeystroke();this._enableTypeAroundFakeCaretActivationUsingKeyboardArrows();this._enableDeleteIntegration();this._enableInsertContentIntegration()}destroy(){this._currentFakeCaretModelElement=null}_insertParagraph(t,e){const n=this.editor;const o=n.editing.view;n.execute("insertParagraph",{position:n.model.createPositionAt(t,e)});o.focus();o.scrollToTheSelection()}_listenToIfEnabled(t,e,n,o){this.listenTo(t,e,((...t)=>{if(this.isEnabled){n(...t)}}),o)}_insertParagraphAccordingToFakeCaretPosition(){const t=this.editor;const e=t.model;const n=e.document.selection;const o=yA(n);if(!o){return false}const i=n.getSelectedElement();this._insertParagraph(i,o);return true}_enableTypeAroundUIInjection(){const t=this.editor;const e=t.model.schema;const n=t.locale.t;const o={before:n("Insert paragraph before block"),after:n("Insert paragraph after block")};t.editing.downcastDispatcher.on("insert",((t,n,i)=>{const r=i.mapper.toViewElement(n.item);if(CA(r,n.item,e)){tE(i.writer,o,r)}}),{priority:"low"})}_enableTypeAroundFakeCaretActivationUsingKeyboardArrows(){const t=this.editor;const e=t.model;const n=e.document.selection;const o=e.schema;const i=t.editing.view;this._listenToIfEnabled(i.document,"keydown",((t,e)=>{if(Fl(e.keyCode)){this._handleArrowKeyPress(t,e)}}),{priority:is.get("high")+10});this._listenToIfEnabled(n,"change:range",((e,n)=>{if(!n.directChange){return}t.model.change((t=>{t.removeSelectionAttribute(wA)}))}));this._listenToIfEnabled(e.document,"change:data",(()=>{const e=n.getSelectedElement();if(e){const n=t.editing.mapper.toViewElement(e);if(CA(n,e,o)){return}}t.model.change((t=>{t.removeSelectionAttribute(wA)}))}));this._listenToIfEnabled(t.editing.downcastDispatcher,"selection",((t,e,n)=>{const i=n.writer;if(this._currentFakeCaretModelElement){const t=n.mapper.toViewElement(this._currentFakeCaretModelElement);if(t){i.removeClass($D.map(r),t);this._currentFakeCaretModelElement=null}}const s=e.selection.getSelectedElement();if(!s){return}const a=n.mapper.toViewElement(s);if(!CA(a,s,o)){return}const c=yA(e.selection);if(!c){return}i.addClass(r(c),a);this._currentFakeCaretModelElement=s}));this._listenToIfEnabled(t.ui.focusTracker,"change:isFocused",((e,n,o)=>{if(!o){t.model.change((t=>{t.removeSelectionAttribute(wA)}))}}));function r(t){return`ck-widget_type-around_show-fake-caret_${t}`}}_handleArrowKeyPress(t,e){const n=this.editor;const o=n.model;const i=o.document.selection;const r=o.schema;const s=n.editing.view;const a=e.keyCode;const c=Ul(a,n.locale.contentLanguageDirection);const l=s.document.selection.getSelectedElement();const d=n.editing.mapper.toModelElement(l);let u;if(CA(l,d,r)){u=this._handleArrowKeyPressOnSelectedWidget(c)}else if(i.isCollapsed){u=this._handleArrowKeyPressWhenSelectionNextToAWidget(c)}if(u){e.preventDefault();t.stop()}}_handleArrowKeyPressOnSelectedWidget(t){const e=this.editor;const n=e.model;const o=n.document.selection;const i=yA(o);return n.change((e=>{if(i){const n=i===(t?"after":"before");if(!n){e.removeSelectionAttribute(wA);return true}}else{e.setSelectionAttribute(wA,t?"after":"before");return true}return false}))}_handleArrowKeyPressWhenSelectionNextToAWidget(t){const e=this.editor;const n=e.model;const o=n.schema;const i=e.plugins.get("Widget");const r=i._getObjectElementNextToSelection(t);const s=e.editing.mapper.toViewElement(r);if(CA(s,r,o)){n.change((e=>{i._setSelectionOverElement(r);e.setSelectionAttribute(wA,t?"before":"after")}));return true}return false}_enableInsertingParagraphsOnButtonClick(){const t=this.editor;const e=t.editing.view;this._listenToIfEnabled(e.document,"mousedown",((n,o)=>{const i=AA(o.domTarget);if(!i){return}const r=_A(i);const s=vA(i,e.domConverter);const a=t.editing.mapper.toModelElement(s);this._insertParagraph(a,r);o.preventDefault();n.stop()}))}_enableInsertingParagraphsOnEnterKeypress(){const t=this.editor;const e=t.editing.view;this._listenToIfEnabled(e.document,"enter",((n,o)=>{const i=e.document.selection.getSelectedElement();const r=t.editing.mapper.toModelElement(i);const s=t.model.schema;let a;if(this._insertParagraphAccordingToFakeCaretPosition()){a=true}else if(CA(i,r,s)){this._insertParagraph(r,o.isSoft?"before":"after");a=true}if(a){o.preventDefault();n.stop()}}))}_enableInsertingParagraphsOnTypingKeystroke(){const t=this.editor;const e=t.editing.view;const n=[Ll.enter,Ll.delete,Ll.backspace];this._listenToIfEnabled(e.document,"keydown",((t,e)=>{if(!n.includes(e.keyCode)&&!g_(e)){this._insertParagraphAccordingToFakeCaretPosition()}}),{priority:is.get("high")+1})}_enableDeleteIntegration(){const t=this.editor;const e=t.editing.view;const n=t.model;const o=n.schema;this._listenToIfEnabled(e.document,"delete",((e,i)=>{const r=yA(n.document.selection);if(!r){return}const s=i.direction;const a=n.document.selection.getSelectedElement();const c=r==="before";const l=s=="forward";const d=c===l;if(d){t.execute("delete",{selection:n.createSelection(a,"on")})}else{const e=o.getNearestSelectionRange(n.createPositionAt(a,r),s);if(e){if(!e.isCollapsed){n.change((n=>{n.setSelection(e);t.execute(l?"forwardDelete":"delete")}))}else{const i=n.createSelection(e.start);n.modifySelection(i,{direction:s});if(!i.focus.isEqual(e.start)){n.change((n=>{n.setSelection(e);t.execute(l?"forwardDelete":"delete")}))}else{const t=oE(o,e.start.parent);n.deleteContent(n.createSelection(t,"on"),{doNotAutoparagraph:true})}}}}i.preventDefault();e.stop()}),{priority:is.get("high")+1})}_enableInsertContentIntegration(){const t=this.editor;const e=this.editor.model;const n=e.document.selection;this._listenToIfEnabled(t.model,"insertContent",((t,[o,i])=>{if(i&&!i.is("documentSelection")){return}const r=yA(n);if(!r){return}t.stop();return e.change((t=>{const i=n.getSelectedElement();const s=e.createPositionAt(i,r);const a=t.createSelection(s);const c=e.insertContent(o,a);t.setSelection(a);return c}))}),{priority:"high"})}}function tE(t,e,n){const o=t.createUIElement("div",{class:"ck ck-reset_all ck-widget__type-around"},(function(t){const n=this.toDomElement(t);eE(n,e);nE(n);return n}));t.insert(t.createPositionAt(n,"end"),o)}function eE(t,e){for(const n of $D){const o=new yk({tag:"div",attributes:{class:["ck","ck-widget__type-around__button",`ck-widget__type-around__button_${n}`],title:e[n]},children:[t.ownerDocument.importNode(JD,true)]});t.appendChild(o.render())}}function nE(t){const e=new yk({tag:"div",attributes:{class:["ck","ck-widget__type-around__fake-caret"]}});t.appendChild(e.render())}function oE(t,e){let n=e;for(const o of e.getAncestors({parentFirst:true})){if(o.childCount>1||t.isLimit(o)){break}n=o}return n}var iE=n(36);var rE={injectType:"singletonStyleTag",attributes:{"data-cke":true}};rE.insert="head";rE.singleton=true;var sE=rk()(iE["a"],rE);var aE=iE["a"].locals||{};function cE(t){const e=t.model;return(n,o)=>{const i=o.keyCode==Ll.arrowup;const r=o.keyCode==Ll.arrowdown;const s=o.shiftKey;const a=e.document.selection;if(!i&&!r){return}const c=r;if(s&&fE(a,c)){return}const l=lE(t,a,c);if(!l||l.isCollapsed){return}if(hE(t,l,c)){e.change((t=>{const n=c?l.end:l.start;if(s){const o=e.createSelection(a.anchor);o.setFocus(n);t.setSelection(o)}else{t.setSelection(n)}}));n.stop();o.preventDefault();o.stopPropagation()}}}function lE(t,e,n){const o=t.model;if(n){const t=e.isCollapsed?e.focus:e.getLastPosition();const n=dE(o,t,"forward");if(!n){return null}const i=o.createRange(t,n);const r=uE(o.schema,i,"backward");if(r&&t.isBefore(r)){return o.createRange(t,r)}return null}else{const t=e.isCollapsed?e.focus:e.getFirstPosition();const n=dE(o,t,"backward");if(!n){return null}const i=o.createRange(n,t);const r=uE(o.schema,i,"forward");if(r&&t.isAfter(r)){return o.createRange(r,t)}return null}}function dE(t,e,n){const o=t.schema;const i=t.createRangeIn(e.root);const r=n=="forward"?"elementStart":"elementEnd";for(const{previousPosition:t,item:s,type:a}of i.getWalker({startPosition:e,direction:n})){if(o.isLimit(s)&&!o.isInline(s)){return t}if(a==r&&o.isBlock(s)){return null}}return null}function uE(t,e,n){const o=n=="backward"?e.end:e.start;if(t.checkChild(o,"$text")){return o}for(const{nextPosition:o}of e.getWalker({direction:n})){if(t.checkChild(o,"$text")){return o}}}function hE(t,e,n){const o=t.model;const i=t.view.domConverter;if(n){const t=o.createSelection(e.start);o.modifySelection(t);if(!t.focus.isAtEnd&&!e.start.isEqual(t.focus)){e=o.createRange(t.focus,e.end)}}const r=t.mapper.toViewRange(e);const s=i.viewRangeToDom(r);const a=Eh.getDomRangeRects(s);let c;for(const t of a){if(c===undefined){c=Math.round(t.bottom);continue}if(Math.round(t.top)>=c){return false}c=Math.max(c,Math.round(t.bottom))}return true}function fE(t,e){return!t.isCollapsed&&t.isBackward==e}class mE extends nC{static get pluginName(){return"Widget"}static get requires(){return[XD]}init(){const t=this.editor.editing.view;const e=t.document;this._previouslySelected=new Set;this.editor.editing.downcastDispatcher.on("selection",((t,e,n)=>{this._clearPreviouslySelectedWidgets(n.writer);const o=n.writer;const i=o.document.selection;const r=i.getSelectedElement();let s=null;for(const t of i.getRanges()){for(const e of t){const t=e.item;if(EA(t)&&!pE(t,s)){o.addClass(DA,t);this._previouslySelected.add(t);s=t;if(t==r){o.setSelection(i.getRanges(),{fake:true,label:IA(r)})}}}}}),{priority:"low"});t.addObserver(e_);this.listenTo(e,"mousedown",((...t)=>this._onMousedown(...t)));this.listenTo(e,"keydown",((...t)=>{this._handleSelectionChangeOnArrowKeyPress(...t)}),{priority:"high"});this.listenTo(e,"keydown",((...t)=>{this._preventDefaultOnArrowKeyPress(...t)}),{priority:is.get("high")-20});this.listenTo(e,"keydown",cE(this.editor.editing));this.listenTo(e,"delete",((t,e)=>{if(this._handleDelete(e.direction=="forward")){e.preventDefault();t.stop()}}),{priority:"high"})}_onMousedown(t,e){const n=this.editor;const o=n.editing.view;const i=o.document;let r=e.target;if(gE(r)){if((El.isSafari||El.isGecko)&&e.domEvent.detail>=3){const t=n.editing.mapper;const o=r.is("attributeElement")?r.findAncestor((t=>!t.is("attributeElement"))):r;const i=t.toModelElement(o);e.preventDefault();this.editor.model.change((t=>{t.setSelection(i,"in")}))}return}if(!EA(r)){r=r.findAncestor(EA);if(!r){return}}e.preventDefault();if(!i.isFocused){o.focus()}const s=n.editing.mapper.toModelElement(r);this._setSelectionOverElement(s)}_handleSelectionChangeOnArrowKeyPress(t,e){const n=e.keyCode;if(!Fl(n)){return}const o=this.editor.model;const i=o.schema;const r=o.document.selection;const s=r.getSelectedElement();const a=Ul(n,this.editor.locale.contentLanguageDirection);if(s&&i.isObject(s)){const n=a?r.getLastPosition():r.getFirstPosition();const s=i.getNearestSelectionRange(n,a?"forward":"backward");if(s){o.change((t=>{t.setSelection(s)}));e.preventDefault();t.stop()}return}if(!r.isCollapsed){return}const c=this._getObjectElementNextToSelection(a);if(c&&i.isObject(c)){this._setSelectionOverElement(c);e.preventDefault();t.stop()}}_preventDefaultOnArrowKeyPress(t,e){const n=e.keyCode;if(!Fl(n)){return}const o=this.editor.model;const i=o.schema;const r=o.document.selection.getSelectedElement();if(r&&i.isObject(r)){e.preventDefault();t.stop()}}_handleDelete(t){if(this.editor.isReadOnly){return}const e=this.editor.model.document;const n=e.selection;if(!n.isCollapsed){return}const o=this._getObjectElementNextToSelection(t);if(o){this.editor.model.change((t=>{let e=n.anchor.parent;while(e.isEmpty){const n=e;e=n.parent;t.remove(n)}this._setSelectionOverElement(o)}));return true}}_setSelectionOverElement(t){this.editor.model.change((e=>{e.setSelection(e.createRangeOn(t))}))}_getObjectElementNextToSelection(t){const e=this.editor.model;const n=e.schema;const o=e.document.selection;const i=e.createSelection(o);e.modifySelection(i,{direction:t?"forward":"backward"});const r=t?i.focus.nodeBefore:i.focus.nodeAfter;if(!!r&&n.isObject(r)){return r}return null}_clearPreviouslySelectedWidgets(t){for(const e of this._previouslySelected){t.removeClass(DA,e)}this._previouslySelected.clear()}}function gE(t){while(t){if(t.is("editableElement")&&!t.is("rootElement")){return true}if(EA(t)){return false}t=t.parent}return false}function pE(t,e){if(!e){return false}return Array.from(t.getAncestors()).includes(e)}class kE extends iC{refresh(){const t=this.editor.model.document.selection.getSelectedElement();this.isEnabled=VA(t);if(VA(t)&&t.hasAttribute("alt")){this.value=t.getAttribute("alt")}else{this.value=false}}execute(t){const e=this.editor.model;const n=e.document.selection.getSelectedElement();e.change((e=>{e.setAttribute("alt",t.newValue,n)}))}}class bE extends nC{static get pluginName(){return"ImageTextAlternativeEditing"}init(){this.editor.commands.add("imageTextAlternative",new kE(this.editor))}}var wE=n(37);var CE={injectType:"singletonStyleTag",attributes:{"data-cke":true}};CE.insert="head";CE.singleton=true;var AE=rk()(wE["a"],CE);var _E=wE["a"].locals||{};class vE extends tb{constructor(t,e){super(t);const n=`ck-labeled-field-view-${ns()}`;const o=`ck-labeled-field-view-status-${ns()}`;this.fieldView=e(this,n,o);this.set("label");this.set("isEnabled",true);this.set("isEmpty",true);this.set("isFocused",false);this.set("errorText",null);this.set("infoText",null);this.set("class");this.set("placeholder");this.labelView=this._createLabelView(n);this.statusView=this._createStatusView(o);this.bind("_statusText").to(this,"errorText",this,"infoText",((t,e)=>t||e));const i=this.bindTemplate;this.setTemplate({tag:"div",attributes:{class:["ck","ck-labeled-field-view",i.to("class"),i.if("isEnabled","ck-disabled",(t=>!t)),i.if("isEmpty","ck-labeled-field-view_empty"),i.if("isFocused","ck-labeled-field-view_focused"),i.if("placeholder","ck-labeled-field-view_placeholder"),i.if("errorText","ck-error")]},children:[{tag:"div",attributes:{class:["ck","ck-labeled-field-view__input-wrapper"]},children:[this.fieldView,this.labelView]},this.statusView]})}_createLabelView(t){const e=new gb(this.locale);e.for=t;e.bind("text").to(this,"label");return e}_createStatusView(t){const e=new tb(this.locale);const n=this.bindTemplate;e.setTemplate({tag:"div",attributes:{class:["ck","ck-labeled-field-view__status",n.if("errorText","ck-labeled-field-view__status_error"),n.if("_statusText","ck-hidden",(t=>!t))],id:t,role:n.if("errorText","alert")},children:[{text:n.to("_statusText")}]});return e}focus(){this.fieldView.focus()}}var yE=n(38);var xE={injectType:"singletonStyleTag",attributes:{"data-cke":true}};xE.insert="head";xE.singleton=true;var DE=rk()(yE["a"],xE);var EE=yE["a"].locals||{};class ME extends tb{constructor(t){super(t);this.set("value");this.set("id");this.set("placeholder");this.set("isReadOnly",false);this.set("hasError",false);this.set("ariaDescribedById");this.focusTracker=new tk;this.bind("isFocused").to(this.focusTracker);this.set("isEmpty",true);const e=this.bindTemplate;this.setTemplate({tag:"input",attributes:{type:"text",class:["ck","ck-input","ck-input-text",e.if("isFocused","ck-input_focused"),e.if("isEmpty","ck-input-text_empty"),e.if("hasError","ck-error")],id:e.to("id"),placeholder:e.to("placeholder"),readonly:e.to("isReadOnly"),"aria-invalid":e.if("hasError",true),"aria-describedby":e.to("ariaDescribedById")},on:{input:e.to("input"),change:e.to(this._updateIsEmpty.bind(this))}})}render(){super.render();this.focusTracker.add(this.element);this._setDomElementValue(this.value);this._updateIsEmpty();this.on("change:value",((t,e,n)=>{this._setDomElementValue(n);this._updateIsEmpty()}))}select(){this.element.select()}focus(){this.element.focus()}_updateIsEmpty(){this.isEmpty=TE(this.element)}_setDomElementValue(t){this.element.value=!t&&t!==0?"":t}}function TE(t){return!t.value}function SE(t,e,n){const o=new ME(t.locale);o.set({id:e,ariaDescribedById:n});o.bind("isReadOnly").to(t,"isEnabled",(t=>!t));o.bind("hasError").to(t,"errorText",(t=>!!t));o.on("input",(()=>{t.errorText=null}));t.bind("isEmpty","isFocused","placeholder").to(o);return o}function IE(t,e,n){const o=Nw(t.locale);o.set({id:e,ariaDescribedById:n});o.bind("isEnabled").to(t);return o}function NE(t){t.set("_isCssTransitionsDisabled",false);t.disableCssTransitions=()=>{t._isCssTransitionsDisabled=true};t.enableCssTransitions=()=>{t._isCssTransitionsDisabled=false};t.extendTemplate({attributes:{class:[t.bindTemplate.if("_isCssTransitionsDisabled","ck-transitions-disabled")]}})}function BE({view:t}){t.listenTo(t.element,"submit",((e,n)=>{n.preventDefault();t.fire("submit")}),{useCapture:true})}var PE='';var zE='';var LE=n(39);var OE={injectType:"singletonStyleTag",attributes:{"data-cke":true}};OE.insert="head";OE.singleton=true;var RE=rk()(LE["a"],OE);var jE=LE["a"].locals||{};var FE=n(40);var VE={injectType:"singletonStyleTag",attributes:{"data-cke":true}};VE.insert="head";VE.singleton=true;var UE=rk()(FE["a"],VE);var HE=FE["a"].locals||{};class GE extends tb{constructor(t){super(t);const e=this.locale.t;this.focusTracker=new tk;this.keystrokes=new Vp;this.labeledInput=this._createLabeledInputView();this.saveButtonView=this._createButton(e("Save"),PE,"ck-button-save");this.saveButtonView.type="submit";this.cancelButtonView=this._createButton(e("Cancel"),zE,"ck-button-cancel","cancel");this._focusables=new Ak;this._focusCycler=new Db({focusables:this._focusables,focusTracker:this.focusTracker,keystrokeHandler:this.keystrokes,actions:{focusPrevious:"shift + tab",focusNext:"tab"}});this.setTemplate({tag:"form",attributes:{class:["ck","ck-text-alternative-form","ck-responsive-form"],tabindex:"-1"},children:[this.labeledInput,this.saveButtonView,this.cancelButtonView]});NE(this)}render(){super.render();this.keystrokes.listenTo(this.element);BE({view:this});[this.labeledInput,this.saveButtonView,this.cancelButtonView].forEach((t=>{this._focusables.add(t);this.focusTracker.add(t.element)}))}_createButton(t,e,n,o){const i=new cw(this.locale);i.set({label:t,icon:e,tooltip:true});i.extendTemplate({attributes:{class:n}});if(o){i.delegate("execute").to(this,o)}return i}_createLabeledInputView(){const t=this.locale.t;const e=new vE(this.locale,SE);e.label=t("Text alternative");return e}}var KE='';var WE='';var qE=n(41);var YE={injectType:"singletonStyleTag",attributes:{"data-cke":true}};YE.insert="head";YE.singleton=true;var QE=rk()(qE["a"],YE);var $E=qE["a"].locals||{};var JE=n(42);var ZE={injectType:"singletonStyleTag",attributes:{"data-cke":true}};ZE.insert="head";ZE.singleton=true;var XE=rk()(JE["a"],ZE);var tM=JE["a"].locals||{};const eM=wb("px");class nM extends nC{static get pluginName(){return"ContextualBalloon"}constructor(t){super(t);this.positionLimiter=()=>{const t=this.editor.editing.view;const e=t.document;const n=e.selection.editableElement;if(n){return t.domConverter.mapViewToDom(n.root)}return null};this.set("visibleView",null);this.view=new mA(t.locale);t.ui.view.body.add(this.view);t.ui.focusTracker.add(this.view.element);this._viewToStack=new Map;this._idToStack=new Map;this.set("_numberOfStacks",0);this.set("_singleViewMode",false);this._rotatorView=this._createRotatorView();this._fakePanelsView=this._createFakePanelsView()}hasView(t){return Array.from(this._viewToStack.keys()).includes(t)}add(t){if(this.hasView(t.view)){throw new ss["a"]("contextualballoon-add-view-exist",[this,t])}const e=t.stackId||"main";if(!this._idToStack.has(e)){this._idToStack.set(e,new Map([[t.view,t]]));this._viewToStack.set(t.view,this._idToStack.get(e));this._numberOfStacks=this._idToStack.size;if(!this._visibleStack||t.singleViewMode){this.showStack(e)}return}const n=this._idToStack.get(e);if(t.singleViewMode){this.showStack(e)}n.set(t.view,t);this._viewToStack.set(t.view,n);if(n===this._visibleStack){this._showView(t)}}remove(t){if(!this.hasView(t)){throw new ss["a"]("contextualballoon-remove-view-not-exist",[this,t])}const e=this._viewToStack.get(t);if(this._singleViewMode&&this.visibleView===t){this._singleViewMode=false}if(this.visibleView===t){if(e.size===1){if(this._idToStack.size>1){this._showNextStack()}else{this.view.hide();this.visibleView=null;this._rotatorView.hideView()}}else{this._showView(Array.from(e.values())[e.size-2])}}if(e.size===1){this._idToStack.delete(this._getStackId(e));this._numberOfStacks=this._idToStack.size}else{e.delete(t)}this._viewToStack.delete(t)}updatePosition(t){if(t){this._visibleStack.get(this.visibleView).position=t}this.view.pin(this._getBalloonPosition());this._fakePanelsView.updatePosition()}showStack(t){this.visibleStack=t;const e=this._idToStack.get(t);if(!e){throw new ss["a"]("contextualballoon-showstack-stack-not-exist",this)}if(this._visibleStack===e){return}this._showView(Array.from(e.values()).pop())}get _visibleStack(){return this._viewToStack.get(this.visibleView)}_getStackId(t){const e=Array.from(this._idToStack.entries()).find((e=>e[1]===t));return e[0]}_showNextStack(){const t=Array.from(this._idToStack.values());let e=t.indexOf(this._visibleStack)+1;if(!t[e]){e=0}this.showStack(this._getStackId(t[e]))}_showPrevStack(){const t=Array.from(this._idToStack.values());let e=t.indexOf(this._visibleStack)-1;if(!t[e]){e=t.length-1}this.showStack(this._getStackId(t[e]))}_createRotatorView(){const t=new oM(this.editor.locale);const e=this.editor.locale.t;this.view.content.add(t);t.bind("isNavigationVisible").to(this,"_numberOfStacks",this,"_singleViewMode",((t,e)=>!e&&t>1));t.on("change:isNavigationVisible",(()=>this.updatePosition()),{priority:"low"});t.bind("counter").to(this,"visibleView",this,"_numberOfStacks",((t,n)=>{if(n<2){return""}const o=Array.from(this._idToStack.values()).indexOf(this._visibleStack)+1;return e("%0 of %1",[o,n])}));t.buttonNextView.on("execute",(()=>{if(t.focusTracker.isFocused){this.editor.editing.view.focus()}this._showNextStack()}));t.buttonPrevView.on("execute",(()=>{if(t.focusTracker.isFocused){this.editor.editing.view.focus()}this._showPrevStack()}));return t}_createFakePanelsView(){const t=new iM(this.editor.locale,this.view);t.bind("numberOfPanels").to(this,"_numberOfStacks",this,"_singleViewMode",((t,e)=>{const n=!e&&t>=2;return n?Math.min(t-1,2):0}));t.listenTo(this.view,"change:top",(()=>t.updatePosition()));t.listenTo(this.view,"change:left",(()=>t.updatePosition()));this.editor.ui.view.body.add(t);return t}_showView({view:t,balloonClassName:e="",withArrow:n=true,singleViewMode:o=false}){this.view.class=e;this.view.withArrow=n;this._rotatorView.showView(t);this.visibleView=t;this.view.pin(this._getBalloonPosition());this._fakePanelsView.updatePosition();if(o){this._singleViewMode=true}}_getBalloonPosition(){let t=Array.from(this._visibleStack.values()).pop().position;if(t&&!t.limiter){t=Object.assign({},t,{limiter:this.positionLimiter})}return t}}class oM extends tb{constructor(t){super(t);const e=t.t;const n=this.bindTemplate;this.set("isNavigationVisible",true);this.focusTracker=new tk;this.buttonPrevView=this._createButtonView(e("Previous"),KE);this.buttonNextView=this._createButtonView(e("Next"),WE);this.content=this.createCollection();this.setTemplate({tag:"div",attributes:{class:["ck","ck-balloon-rotator"],"z-index":"-1"},children:[{tag:"div",attributes:{class:["ck-balloon-rotator__navigation",n.to("isNavigationVisible",(t=>t?"":"ck-hidden"))]},children:[this.buttonPrevView,{tag:"span",attributes:{class:["ck-balloon-rotator__counter"]},children:[{text:n.to("counter")}]},this.buttonNextView]},{tag:"div",attributes:{class:"ck-balloon-rotator__content"},children:this.content}]})}render(){super.render();this.focusTracker.add(this.element)}showView(t){this.hideView();this.content.add(t)}hideView(){this.content.clear()}_createButtonView(t,e){const n=new cw(this.locale);n.set({label:t,icon:e,tooltip:true});return n}}class iM extends tb{constructor(t,e){super(t);const n=this.bindTemplate;this.set("top",0);this.set("left",0);this.set("height",0);this.set("width",0);this.set("numberOfPanels",0);this.content=this.createCollection();this._balloonPanelView=e;this.setTemplate({tag:"div",attributes:{class:["ck-fake-panel",n.to("numberOfPanels",(t=>t?"":"ck-hidden"))],style:{top:n.to("top",eM),left:n.to("left",eM),width:n.to("width",eM),height:n.to("height",eM)}},children:this.content});this.on("change:numberOfPanels",((t,e,n,o)=>{if(n>o){this._addPanels(n-o)}else{this._removePanels(o-n)}this.updatePosition()}))}_addPanels(t){while(t--){const t=new tb;t.setTemplate({tag:"div"});this.content.add(t);this.registerChild(t)}}_removePanels(t){while(t--){const t=this.content.last;this.content.remove(t);this.deregisterChild(t);t.destroy()}}updatePosition(){if(this.numberOfPanels){const{top:t,left:e}=this._balloonPanelView;const{width:n,height:o}=new Eh(this._balloonPanelView.element);Object.assign(this,{top:t,left:e,width:n,height:o})}}}var rM='';function sM(t){const e=t.plugins.get("ContextualBalloon");if(FA(t.editing.view.document.selection)){const n=aM(t);e.updatePosition(n)}}function aM(t){const e=t.editing.view;const n=mA.defaultPositions;return{target:e.domConverter.viewToDom(e.document.selection.getSelectedElement()),positions:[n.northArrowSouth,n.northArrowSouthWest,n.northArrowSouthEast,n.southArrowNorth,n.southArrowNorthWest,n.southArrowNorthEast]}}class cM extends nC{static get requires(){return[nM]}static get pluginName(){return"ImageTextAlternativeUI"}init(){this._createButton();this._createForm()}destroy(){super.destroy();this._form.destroy()}_createButton(){const t=this.editor;const e=t.t;t.ui.componentFactory.add("imageTextAlternative",(n=>{const o=t.commands.get("imageTextAlternative");const i=new cw(n);i.set({label:e("Change image text alternative"),icon:rM,tooltip:true});i.bind("isEnabled").to(o,"isEnabled");this.listenTo(i,"execute",(()=>{this._showForm()}));return i}))}_createForm(){const t=this.editor;const e=t.editing.view;const n=e.document;this._balloon=this.editor.plugins.get("ContextualBalloon");this._form=new GE(t.locale);this._form.render();this.listenTo(this._form,"submit",(()=>{t.execute("imageTextAlternative",{newValue:this._form.labeledInput.fieldView.element.value});this._hideForm(true)}));this.listenTo(this._form,"cancel",(()=>{this._hideForm(true)}));this._form.keystrokes.set("Esc",((t,e)=>{this._hideForm(true);e()}));this.listenTo(t.ui,"update",(()=>{if(!FA(n.selection)){this._hideForm(true)}else if(this._isVisible){sM(t)}}));vw({emitter:this._form,activator:()=>this._isVisible,contextElements:[this._balloon.view.element],callback:()=>this._hideForm()})}_showForm(){if(this._isVisible){return}const t=this.editor;const e=t.commands.get("imageTextAlternative");const n=this._form.labeledInput;this._form.disableCssTransitions();if(!this._isInBalloon){this._balloon.add({view:this._form,position:aM(t)})}n.fieldView.value=n.fieldView.element.value=e.value||"";this._form.labeledInput.fieldView.select();this._form.enableCssTransitions()}_hideForm(t){if(!this._isInBalloon){return}if(this._form.focusTracker.isFocused){this._form.saveButtonView.focus()}this._balloon.remove(this._form);if(t){this.editor.editing.view.focus()}}get _isVisible(){return this._balloon.visibleView===this._form}get _isInBalloon(){return this._balloon.hasView(this._form)}}class lM extends nC{static get requires(){return[bE,cM]}static get pluginName(){return"ImageTextAlternative"}}var dM=n(43);var uM={injectType:"singletonStyleTag",attributes:{"data-cke":true}};uM.insert="head";uM.singleton=true;var hM=rk()(dM["a"],uM);var fM=dM["a"].locals||{};class mM extends nC{static get requires(){return[XA,mE,lM]}static get pluginName(){return"Image"}}function gM(t,e){return n=>{const o=n.createEditableElement("figcaption");n.setCustomProperty("imageCaption",true,o);uk({view:t,element:o,text:e});return NA(o,n)}}function pM(t){return!!t.getCustomProperty("imageCaption")}function kM(t){for(const e of t.getChildren()){if(!!e&&e.is("element","caption")){return e}}return null}function bM(t){const e=t.parent;if(t.name=="figcaption"&&e&&e.name=="figure"&&e.hasClass("image")){return{name:true}}return null}class wM extends nC{static get pluginName(){return"ImageCaptionEditing"}init(){const t=this.editor;const e=t.editing.view;const n=t.model.schema;const o=t.data;const i=t.editing;const r=t.t;n.register("caption",{allowIn:"image",allowContentOf:"$block",isLimit:true});t.model.document.registerPostFixer((t=>this._insertMissingModelCaptionElement(t)));t.conversion.for("upcast").elementToElement({view:bM,model:"caption"});const s=t=>t.createContainerElement("figcaption");o.downcastDispatcher.on("insert:caption",CM(s,false));const a=gM(e,r("Enter image caption"));i.downcastDispatcher.on("insert:caption",CM(a));i.downcastDispatcher.on("insert",this._fixCaptionVisibility((t=>t.item)),{priority:"high"});i.downcastDispatcher.on("remove",this._fixCaptionVisibility((t=>t.position.parent)),{priority:"high"});e.document.registerPostFixer((t=>this._updateCaptionVisibility(t)))}_updateCaptionVisibility(t){const e=this.editor.editing.mapper;const n=this._lastSelectedCaption;let o;const i=this.editor.model.document.selection;const r=i.getSelectedElement();if(r&&r.is("element","image")){const t=kM(r);o=e.toViewElement(t)}const s=i.getFirstPosition();const a=_M(s.parent);if(a){o=e.toViewElement(a)}if(o){if(n){if(n===o){return yM(o,t)}else{vM(n,t);this._lastSelectedCaption=o;return yM(o,t)}}else{this._lastSelectedCaption=o;return yM(o,t)}}else{if(n){const e=vM(n,t);this._lastSelectedCaption=null;return e}else{return false}}}_fixCaptionVisibility(t){return(e,n,o)=>{const i=t(n);const r=_M(i);const s=this.editor.editing.mapper;const a=o.writer;if(r){const t=s.toViewElement(r);if(t){if(r.childCount){a.removeClass("ck-hidden",t)}else{a.addClass("ck-hidden",t)}}}}}_insertMissingModelCaptionElement(t){const e=this.editor.model;const n=e.document.differ.getChanges();const o=[];for(const t of n){if(t.type=="insert"&&t.name!="$text"){const n=t.position.nodeAfter;if(n.is("element","image")&&!kM(n)){o.push(n)}if(!n.is("element","image")&&n.childCount){for(const t of e.createRangeIn(n).getItems()){if(t.is("element","image")&&!kM(t)){o.push(t)}}}}}for(const e of o){t.appendElement("caption",e)}return!!o.length}}function CM(t,e=true){return(n,o,i)=>{const r=o.item;if(!r.childCount&&!e){return}if(VA(r.parent)){if(!i.consumable.consume(o.item,"insert")){return}const e=i.mapper.toViewElement(o.range.start.parent);const n=t(i.writer);const s=i.writer;if(!r.childCount){s.addClass("ck-hidden",n)}AM(n,o.item,e,i)}}}function AM(t,e,n,o){const i=o.writer.createPositionAt(n,"end");o.writer.insert(i,t);o.mapper.bindElements(e,t)}function _M(t){const e=t.getAncestors({includeSelf:true});const n=e.find((t=>t.name=="caption"));if(n&&n.parent&&n.parent.name=="image"){return n}return null}function vM(t,e){if(!t.childCount&&!t.hasClass("ck-hidden")){e.addClass("ck-hidden",t);return true}return false}function yM(t,e){if(t.hasClass("ck-hidden")){e.removeClass("ck-hidden",t);return true}return false}var xM=n(44);var DM={injectType:"singletonStyleTag",attributes:{"data-cke":true}};DM.insert="head";DM.singleton=true;var EM=rk()(xM["a"],DM);var MM=xM["a"].locals||{};class TM extends nC{static get requires(){return[wM]}static get pluginName(){return"ImageCaption"}}class SM extends iC{refresh(){const t=this.editor.model.document.selection.getSelectedElement();this.isEnabled=VA(t);if(!t||!t.hasAttribute("width")){this.value=null}else{this.value={width:t.getAttribute("width"),height:null}}}execute(t){const e=this.editor.model;const n=e.document.selection.getSelectedElement();this.value={width:t.width,height:null};if(n){e.change((e=>{e.setAttribute("width",t.width,n)}))}}}class IM extends nC{static get pluginName(){return"ImageResizeEditing"}constructor(t){super(t);t.config.define("image",{resizeUnit:"%",resizeOptions:[{name:"imageResize:original",value:null,icon:"original"},{name:"imageResize:25",value:"25",icon:"small"},{name:"imageResize:50",value:"50",icon:"medium"},{name:"imageResize:75",value:"75",icon:"large"}]})}init(){const t=this.editor;const e=new SM(t);this._registerSchema();this._registerConverters();t.commands.add("imageResize",e)}_registerSchema(){this.editor.model.schema.extend("image",{allowAttributes:"width"});this.editor.model.schema.setAttributeProperties("width",{isFormatting:true})}_registerConverters(){const t=this.editor;t.conversion.for("downcast").add((t=>t.on("attribute:width:image",((t,e,n)=>{if(!n.consumable.consume(e.item,t.name)){return}const o=n.writer;const i=n.mapper.toViewElement(e.item);if(e.attributeNewValue!==null){o.setStyle("width",e.attributeNewValue,i);o.addClass("image_resized",i)}else{o.removeStyle("width",i);o.removeClass("image_resized",i)}}))));t.conversion.for("upcast").attributeToAttribute({view:{name:"figure",styles:{width:/.+/}},model:{key:"width",value:t=>t.getStyle("width")}})}}var NM='';var BM='';var PM='';var zM='';const LM={small:NM,medium:BM,large:PM,original:zM};class OM extends nC{static get requires(){return[IM]}static get pluginName(){return"ImageResizeButtons"}constructor(t){super(t);this._resizeUnit=t.config.get("image.resizeUnit")}init(){const t=this.editor;const e=t.config.get("image.resizeOptions");const n=t.commands.get("imageResize");this.bind("isEnabled").to(n);for(const t of e){this._registerImageResizeButton(t)}this._registerImageResizeDropdown(e)}_registerImageResizeButton(t){const e=this.editor;const{name:n,value:o,icon:i}=t;const r=o?o+this._resizeUnit:null;e.ui.componentFactory.add(n,(n=>{const o=new cw(n);const s=e.commands.get("imageResize");const a=this._getOptionLabelValue(t,true);if(!LM[i]){throw new ss["a"]("imageresizebuttons-missing-icon",e,t)}o.set({label:a,icon:LM[i],tooltip:a,isToggleable:true});o.bind("isEnabled").to(this);o.bind("isOn").to(s,"value",RM(r));this.listenTo(o,"execute",(()=>{e.execute("imageResize",{width:r})}));return o}))}_registerImageResizeDropdown(t){const e=this.editor;const n=e.t;const o=t.find((t=>!t.value));e.ui.componentFactory.add("imageResize",(i=>{const r=e.commands.get("imageResize");const s=Nw(i,dw);const a=s.buttonView;a.set({tooltip:n("Resize image"),commandValue:o.value,icon:BM,isToggleable:true,label:this._getOptionLabelValue(o),withText:true,class:"ck-resize-image-button"});a.bind("label").to(r,"value",(t=>{if(t&&t.width){return t.width}else{return this._getOptionLabelValue(o)}}));s.bind("isOn").to(r);s.bind("isEnabled").to(this);Pw(s,this._getResizeDropdownListItemDefinitions(t,r));s.listView.ariaLabel=n("Image resize list");this.listenTo(s,"execute",(t=>{e.execute(t.source.commandName,{width:t.source.commandValue});e.editing.view.focus()}));return s}))}_getOptionLabelValue(t,e){const n=this.editor.t;if(t.label){return t.label}else if(e){if(t.value){return n("Resize image to %0",t.value+this._resizeUnit)}else{return n("Resize image to the original size")}}else{if(t.value){return t.value+this._resizeUnit}else{return n("Original")}}}_getResizeDropdownListItemDefinitions(t,e){const n=new vs;t.map((t=>{const o=t.value?t.value+this._resizeUnit:null;const i={type:"button",model:new qx({commandName:"imageResize",commandValue:o,label:this._getOptionLabelValue(t),withText:true,icon:null})};i.model.bind("isOn").to(e,"value",RM(o));n.add(i)}));return n}}function RM(t){return e=>{if(t===null&&e===t){return true}return e&&e.width===t}}class jM{constructor(t){this.set("activeHandlePosition",null);this.set("proposedWidthPercents",null);this.set("proposedWidth",null);this.set("proposedHeight",null);this.set("proposedHandleHostWidth",null);this.set("proposedHandleHostHeight",null);this._options=t;this._referenceCoordinates=null}begin(t,e,n){const o=new Eh(e);this.activeHandlePosition=HM(t);this._referenceCoordinates=VM(e,GM(this.activeHandlePosition));this.originalWidth=o.width;this.originalHeight=o.height;this.aspectRatio=o.width/o.height;const i=n.style.width;if(i&&i.match(/^\d+\.?\d*%$/)){this.originalWidthPercents=parseFloat(i)}else{this.originalWidthPercents=FM(n,o)}}update(t){this.proposedWidth=t.width;this.proposedHeight=t.height;this.proposedWidthPercents=t.widthPercents;this.proposedHandleHostWidth=t.handleHostWidth;this.proposedHandleHostHeight=t.handleHostHeight}}_s(jM,Jc);function FM(t,e){const n=t.parentElement;const o=parseFloat(n.ownerDocument.defaultView.getComputedStyle(n).width);return e.width/o*100}function VM(t,e){const n=new Eh(t);const o=e.split("-");const i={x:o[1]=="right"?n.right:n.left,y:o[0]=="bottom"?n.bottom:n.top};i.x+=t.ownerDocument.defaultView.scrollX;i.y+=t.ownerDocument.defaultView.scrollY;return i}function UM(t){return`ck-widget__resizer__handle-${t}`}function HM(t){const e=["top-left","top-right","bottom-right","bottom-left"];for(const n of e){if(t.classList.contains(UM(n))){return n}}}function GM(t){const e=t.split("-");const n={top:"bottom",bottom:"top",left:"right",right:"left"};return`${n[e[0]]}-${n[e[1]]}`}class KM{constructor(t){this._options=t;this._domResizerWrapper=null;this._viewResizerWrapper=null;this.set("isEnabled",true);this.decorate("begin");this.decorate("cancel");this.decorate("commit");this.decorate("updateSize");this.on("commit",(t=>{if(!this.state.proposedWidth&&!this.state.proposedWidthPercents){this._cleanup();t.stop()}}),{priority:"high"});this.on("change:isEnabled",(()=>{if(this.isEnabled){this.redraw()}}))}attach(){const t=this;const e=this._options.viewElement;const n=this._options.editor.editing.view;n.change((n=>{const o=n.createUIElement("div",{class:"ck ck-reset_all ck-widget__resizer"},(function(e){const n=this.toDomElement(e);t._appendHandles(n);t._appendSizeUI(n);t._domResizerWrapper=n;t.on("change:isEnabled",((t,e,o)=>{n.style.display=o?"":"none"}));n.style.display=t.isEnabled?"":"none";return n}));n.insert(n.createPositionAt(e,"end"),o);n.addClass("ck-widget_with-resizer",e);this._viewResizerWrapper=o}))}begin(t){this.state=new jM(this._options);this._sizeUI.bindToState(this._options,this.state);this._initialViewWidth=this._options.viewElement.getStyle("width");this.state.begin(t,this._getHandleHost(),this._getResizeHost())}updateSize(t){const e=this._proposeNewSize(t);const n=this._options.editor.editing.view;n.change((t=>{const n=this._options.unit||"%";const o=(n==="%"?e.widthPercents:e.width)+n;t.setStyle("width",o,this._options.viewElement)}));const o=this._getHandleHost();const i=new Eh(o);e.handleHostWidth=Math.round(i.width);e.handleHostHeight=Math.round(i.height);const r=new Eh(o);e.width=Math.round(r.width);e.height=Math.round(r.height);this.redraw(i);this.state.update(e)}commit(){const t=this._options.unit||"%";const e=(t==="%"?this.state.proposedWidthPercents:this.state.proposedWidth)+t;this._options.editor.editing.view.change((()=>{this._cleanup();this._options.onCommit(e)}))}cancel(){this._cleanup()}destroy(){this.cancel()}redraw(t){const e=this._domResizerWrapper;if(!QM(e)){return}const n=e.parentElement;const o=this._getHandleHost();const i=this._viewResizerWrapper;const r=[i.getStyle("width"),i.getStyle("height"),i.getStyle("left"),i.getStyle("top")];let s;if(n.isSameNode(o)){const e=t||new Eh(o);s=[e.width+"px",e.height+"px",undefined,undefined]}else{s=[o.offsetWidth+"px",o.offsetHeight+"px",o.offsetLeft+"px",o.offsetTop+"px"]}if(Ls(r,s)!=="same"){this._options.editor.editing.view.change((t=>{t.setStyle({width:s[0],height:s[1],left:s[2],top:s[3]},i)}))}}containsHandle(t){return this._domResizerWrapper.contains(t)}static isResizeHandle(t){return t.classList.contains("ck-widget__resizer__handle")}_cleanup(){this._sizeUI.dismiss();this._sizeUI.isVisible=false;const t=this._options.editor.editing.view;t.change((t=>{t.setStyle("width",this._initialViewWidth,this._options.viewElement)}))}_proposeNewSize(t){const e=this.state;const n=YM(t);const o=this._options.isCentered?this._options.isCentered(this):true;const i={x:e._referenceCoordinates.x-(n.x+e.originalWidth),y:n.y-e.originalHeight-e._referenceCoordinates.y};if(o&&e.activeHandlePosition.endsWith("-right")){i.x=n.x-(e._referenceCoordinates.x+e.originalWidth)}if(o){i.x*=2}const r={width:Math.abs(e.originalWidth+i.x),height:Math.abs(e.originalHeight+i.y)};r.dominant=r.width/e.aspectRatio>r.height?"width":"height";r.max=r[r.dominant];const s={width:r.width,height:r.height};if(r.dominant=="width"){s.height=s.width/e.aspectRatio}else{s.width=s.height*e.aspectRatio}return{width:Math.round(s.width),height:Math.round(s.height),widthPercents:Math.min(Math.round(e.originalWidthPercents/e.originalWidth*s.width*100)/100,100)}}_getResizeHost(){const t=this._domResizerWrapper.parentElement;return this._options.getResizeHost(t)}_getHandleHost(){const t=this._domResizerWrapper.parentElement;return this._options.getHandleHost(t)}_appendHandles(t){const e=["top-left","top-right","bottom-right","bottom-left"];for(const n of e){t.appendChild(new yk({tag:"div",attributes:{class:`ck-widget__resizer__handle ${qM(n)}`}}).render())}}_appendSizeUI(t){const e=new WM;e.render();this._sizeUI=e;t.appendChild(e.element)}}_s(KM,Jc);class WM extends tb{constructor(){super();const t=this.bindTemplate;this.setTemplate({tag:"div",attributes:{class:["ck","ck-size-view",t.to("activeHandlePosition",(t=>t?`ck-orientation-${t}`:""))],style:{display:t.if("isVisible","none",(t=>!t))}},children:[{text:t.to("label")}]})}bindToState(t,e){this.bind("isVisible").to(e,"proposedWidth",e,"proposedHeight",((t,e)=>t!==null&&e!==null));this.bind("label").to(e,"proposedHandleHostWidth",e,"proposedHandleHostHeight",e,"proposedWidthPercents",((e,n,o)=>{if(t.unit==="px"){return`${e}×${n}`}else{return`${o}%`}}));this.bind("activeHandlePosition").to(e)}dismiss(){this.unbind();this.isVisible=false}}function qM(t){return`ck-widget__resizer__handle-${t}`}function YM(t){return{x:t.pageX,y:t.pageY}}function QM(t){return t&&t.ownerDocument&&t.ownerDocument.contains(t)}var $M="Expected a function";function JM(t,e,n){var o=true,i=true;if(typeof t!="function"){throw new TypeError($M)}if(ct(n)){o="leading"in n?!!n.leading:o;i="trailing"in n?!!n.trailing:i}return bh(t,e,{leading:o,maxWait:e,trailing:i})}var ZM=JM;var XM=n(45);var tT={injectType:"singletonStyleTag",attributes:{"data-cke":true}};tT.insert="head";tT.singleton=true;var eT=rk()(XM["a"],tT);var nT=XM["a"].locals||{};class oT extends nC{static get pluginName(){return"WidgetResize"}init(){this.set("visibleResizer",null);this.set("_activeResizer",null);this._resizers=new Map;const t=jd.window.document;this.editor.model.schema.setAttributeProperties("width",{isFormatting:true});this.editor.editing.view.addObserver(e_);this._observer=Object.create(Jd);this.listenTo(this.editor.editing.view.document,"mousedown",this._mouseDownListener.bind(this),{priority:"high"});this._observer.listenTo(t,"mousemove",this._mouseMoveListener.bind(this));this._observer.listenTo(t,"mouseup",this._mouseUpListener.bind(this));const e=()=>{if(this.visibleResizer){this.visibleResizer.redraw()}};const n=ZM(e,200);this.on("change:visibleResizer",e);this.editor.ui.on("update",n);this._observer.listenTo(jd.window,"resize",n);const o=this.editor.editing.view.document.selection;o.on("change",(()=>{const t=o.getSelectedElement();this.visibleResizer=this.getResizerByViewElement(t)||null}))}destroy(){this._observer.stopListening();for(const t of this._resizers.values()){t.destroy()}}attachTo(t){const e=new KM(t);const n=this.editor.plugins;e.attach();if(n.has("WidgetToolbarRepository")){const t=n.get("WidgetToolbarRepository");e.on("begin",(()=>{t.forceDisabled("resize")}),{priority:"lowest"});e.on("cancel",(()=>{t.clearForceDisabled("resize")}),{priority:"highest"});e.on("commit",(()=>{t.clearForceDisabled("resize")}),{priority:"highest"})}this._resizers.set(t.viewElement,e);const o=this.editor.editing.view.document.selection;const i=o.getSelectedElement();if(this.getResizerByViewElement(i)==e){this.visibleResizer=e}return e}getResizerByViewElement(t){return this._resizers.get(t)}_getResizerByHandle(t){for(const e of this._resizers.values()){if(e.containsHandle(t)){return e}}}_mouseDownListener(t,e){const n=e.domTarget;if(!KM.isResizeHandle(n)){return}this._activeResizer=this._getResizerByHandle(n);if(this._activeResizer){this._activeResizer.begin(n);t.stop();e.preventDefault()}}_mouseMoveListener(t,e){if(this._activeResizer){this._activeResizer.updateSize(e)}}_mouseUpListener(){if(this._activeResizer){this._activeResizer.commit();this._activeResizer=null}}}_s(oT,Jc);class iT extends nC{static get requires(){return[oT]}static get pluginName(){return"ImageResizeHandles"}init(){const t=this.editor.commands.get("imageResize");this.bind("isEnabled").to(t);this._setupResizerCreator()}_setupResizerCreator(){const t=this.editor;const e=t.editing.view;e.addObserver(oA);this.listenTo(e.document,"imageLoaded",((n,o)=>{if(!o.target.matches("figure.image.ck-widget > img")){return}const i=t.editing.view.domConverter.domToView(o.target);const r=i.findAncestor("figure");let s=this.editor.plugins.get(oT).getResizerByViewElement(r);if(s){s.redraw();return}const a=t.editing.mapper;const c=a.toModelElement(r);s=t.plugins.get(oT).attachTo({unit:t.config.get("image.resizeUnit"),modelElement:c,viewElement:r,editor:t,getHandleHost(t){return t.querySelector("img")},getResizeHost(t){return t},isCentered(){const t=c.getAttribute("imageStyle");return!t||t=="full"||t=="alignCenter"},onCommit(e){t.execute("imageResize",{width:e})}});s.on("updateSize",(()=>{if(!r.hasClass("image_resized")){e.change((t=>{t.addClass("image_resized",r)}))}}));s.bind("isEnabled").to(this)}))}}var rT=n(46);var sT={injectType:"singletonStyleTag",attributes:{"data-cke":true}};sT.insert="head";sT.singleton=true;var aT=rk()(rT["a"],sT);var cT=rT["a"].locals||{};class lT extends nC{static get requires(){return[IM,iT,OM]}static get pluginName(){return"ImageResize"}}class dT extends iC{constructor(t,e){super(t);this.defaultStyle=false;this.styles=e.reduce(((t,e)=>{t[e.name]=e;if(e.isDefault){this.defaultStyle=e.name}return t}),{})}refresh(){const t=this.editor.model.document.selection.getSelectedElement();this.isEnabled=VA(t);if(!t){this.value=false}else if(t.hasAttribute("imageStyle")){const e=t.getAttribute("imageStyle");this.value=this.styles[e]?e:false}else{this.value=this.defaultStyle}}execute(t){const e=t.value;const n=this.editor.model;const o=n.document.selection.getSelectedElement();n.change((t=>{if(this.styles[e].isDefault){t.removeAttribute("imageStyle",o)}else{t.setAttribute("imageStyle",e,o)}}))}}function uT(t){return(e,n,o)=>{if(!o.consumable.consume(n.item,e.name)){return}const i=fT(n.attributeNewValue,t);const r=fT(n.attributeOldValue,t);const s=o.mapper.toViewElement(n.item);const a=o.writer;if(r){a.removeClass(r.className,s)}if(i){a.addClass(i.className,s)}}}function hT(t){const e=t.filter((t=>!t.isDefault));return(t,n,o)=>{if(!n.modelRange){return}const i=n.viewItem;const r=sC(n.modelRange.getItems());if(!o.schema.checkAttribute(r,"imageStyle")){return}for(const t of e){if(o.consumable.consume(i,{classes:t.className})){o.writer.setAttribute("imageStyle",t.name,r)}}}}function fT(t,e){for(const n of e){if(n.name===t){return n}}}var mT='';var gT='';var pT='';var kT='';const bT={full:{name:"full",title:"Full size image",icon:mT,isDefault:true},side:{name:"side",title:"Side image",icon:kT,className:"image-style-side"},alignLeft:{name:"alignLeft",title:"Left aligned image",icon:gT,className:"image-style-align-left"},alignCenter:{name:"alignCenter",title:"Centered image",icon:pT,className:"image-style-align-center"},alignRight:{name:"alignRight",title:"Right aligned image",icon:kT,className:"image-style-align-right"}};const wT={full:mT,left:gT,right:kT,center:pT};function CT(t=[]){return t.map(AT)}function AT(t){if(typeof t=="string"){const e=t;if(bT[e]){t=Object.assign({},bT[e])}else{Object(ss["c"])("image-style-not-found",{name:e});t={name:e}}}else if(bT[t.name]){const e=bT[t.name];const n=Object.assign({},t);for(const o in e){if(!Object.prototype.hasOwnProperty.call(t,o)){n[o]=e[o]}}t=n}if(typeof t.icon=="string"&&wT[t.icon]){t.icon=wT[t.icon]}return t}class _T extends nC{static get pluginName(){return"ImageStyleEditing"}init(){const t=this.editor;const e=t.model.schema;const n=t.data;const o=t.editing;t.config.define("image.styles",["full","side"]);const i=CT(t.config.get("image.styles"));e.extend("image",{allowAttributes:"imageStyle"});const r=uT(i);o.downcastDispatcher.on("attribute:imageStyle:image",r);n.downcastDispatcher.on("attribute:imageStyle:image",r);n.upcastDispatcher.on("element:figure",hT(i),{priority:"low"});t.commands.add("imageStyle",new dT(t,i))}}var vT=n(47);var yT={injectType:"singletonStyleTag",attributes:{"data-cke":true}};yT.insert="head";yT.singleton=true;var xT=rk()(vT["a"],yT);var DT=vT["a"].locals||{};class ET extends nC{static get pluginName(){return"ImageStyleUI"}get localizedDefaultStylesTitles(){const t=this.editor.t;return{"Full size image":t("Full size image"),"Side image":t("Side image"),"Left aligned image":t("Left aligned image"),"Centered image":t("Centered image"),"Right aligned image":t("Right aligned image")}}init(){const t=this.editor;const e=t.config.get("image.styles");const n=MT(CT(e),this.localizedDefaultStylesTitles);for(const t of n){this._createButton(t)}}_createButton(t){const e=this.editor;const n=`imageStyle:${t.name}`;e.ui.componentFactory.add(n,(n=>{const o=e.commands.get("imageStyle");const i=new cw(n);i.set({label:t.title,icon:t.icon,tooltip:true,isToggleable:true});i.bind("isEnabled").to(o,"isEnabled");i.bind("isOn").to(o,"value",(e=>e===t.name));this.listenTo(i,"execute",(()=>{e.execute("imageStyle",{value:t.name});e.editing.view.focus()}));return i}))}}function MT(t,e){for(const n of t){if(e[n.title]){n.title=e[n.title]}}return t}class TT extends nC{static get requires(){return[_T,ET]}static get pluginName(){return"ImageStyle"}}class ST extends tb{constructor(t){super(t);this.buttonView=new cw(t);this._fileInputView=new IT(t);this._fileInputView.bind("acceptedType").to(this);this._fileInputView.bind("allowMultipleFiles").to(this);this._fileInputView.delegate("done").to(this);this.setTemplate({tag:"span",attributes:{class:"ck-file-dialog-button"},children:[this.buttonView,this._fileInputView]});this.buttonView.on("execute",(()=>{this._fileInputView.open()}))}focus(){this.buttonView.focus()}}class IT extends tb{constructor(t){super(t);this.set("acceptedType");this.set("allowMultipleFiles",false);const e=this.bindTemplate;this.setTemplate({tag:"input",attributes:{class:["ck-hidden"],type:"file",tabindex:"-1",accept:e.to("acceptedType"),multiple:e.to("allowMultipleFiles")},on:{change:e.to((()=>{if(this.element&&this.element.files&&this.element.files.length){this.fire("done",this.element.files)}this.element.value=""}))}})}open(){this.element.click()}}function NT(t){const e=t.map((t=>t.replace("+","\\+")));return new RegExp(`^image\\/(${e.join("|")})$`)}function BT(t){return new Promise(((e,n)=>{const o=t.getAttribute("src");fetch(o).then((t=>t.blob())).then((t=>{const n=zT(t,o);const i=n.replace("image/","");const r=`image.${i}`;const s=new File([t],r,{type:n});e(s)})).catch(n)}))}function PT(t){if(!t.is("element","img")||!t.getAttribute("src")){return false}return t.getAttribute("src").match(/^data:image\/\w+;base64,/g)||t.getAttribute("src").match(/^blob:/g)}function zT(t,e){if(t.type){return t.type}else if(e.match(/data:(image\/\w+);base64/)){return e.match(/data:(image\/\w+);base64/)[1].toLowerCase()}else{return"image/jpeg"}}var LT='';class OT extends nC{static get pluginName(){return"ImageUploadUI"}init(){const t=this.editor;const e=t.t;t.ui.componentFactory.add("imageUpload",(n=>{const o=new ST(n);const i=t.commands.get("imageUpload");const r=t.config.get("image.upload.types");const s=NT(r);o.set({acceptedType:r.map((t=>`image/${t}`)).join(","),allowMultipleFiles:true});o.buttonView.set({label:e("Insert image"),icon:LT,tooltip:true});o.buttonView.bind("isEnabled").to(i);o.on("done",((e,n)=>{const o=Array.from(n).filter((t=>s.test(t.type)));if(o.length){t.execute("imageUpload",{file:o})}}));return o}))}}var RT='';var jT=n(48);var FT={injectType:"singletonStyleTag",attributes:{"data-cke":true}};FT.insert="head";FT.singleton=true;var VT=rk()(jT["a"],FT);var UT=jT["a"].locals||{};var HT=n(49);var GT={injectType:"singletonStyleTag",attributes:{"data-cke":true}};GT.insert="head";GT.singleton=true;var KT=rk()(HT["a"],GT);var WT=HT["a"].locals||{};var qT=n(50);var YT={injectType:"singletonStyleTag",attributes:{"data-cke":true}};YT.insert="head";YT.singleton=true;var QT=rk()(qT["a"],YT);var $T=qT["a"].locals||{};class JT extends nC{constructor(t){super(t);this.placeholder="data:image/svg+xml;utf8,"+encodeURIComponent(RT)}init(){const t=this.editor;t.editing.downcastDispatcher.on("attribute:uploadStatus:image",((...t)=>this.uploadStatusChange(...t)))}uploadStatusChange(t,e,n){const o=this.editor;const i=e.item;const r=i.getAttribute("uploadId");if(!n.consumable.consume(e.item,t.name)){return}const s=o.plugins.get(NC);const a=r?e.attributeNewValue:null;const c=this.placeholder;const l=o.editing.mapper.toViewElement(i);const d=n.writer;if(a=="reading"){ZT(l,d);tS(c,l,d);return}if(a=="uploading"){const t=s.loaders.get(r);ZT(l,d);if(!t){tS(c,l,d)}else{eS(l,d);nS(l,d,t,o.editing.view);lS(l,d,t)}return}if(a=="complete"&&s.loaders.get(r)){iS(l,d,o.editing.view)}oS(l,d);eS(l,d);XT(l,d)}}function ZT(t,e){if(!t.hasClass("ck-appear")){e.addClass("ck-appear",t)}}function XT(t,e){e.removeClass("ck-appear",t)}function tS(t,e,n){if(!e.hasClass("ck-image-upload-placeholder")){n.addClass("ck-image-upload-placeholder",e)}const o=GA(e);if(o.getAttribute("src")!==t){n.setAttribute("src",t,o)}if(!aS(e,"placeholder")){n.insert(n.createPositionAfter(o),sS(n))}}function eS(t,e){if(t.hasClass("ck-image-upload-placeholder")){e.removeClass("ck-image-upload-placeholder",t)}cS(t,e,"placeholder")}function nS(t,e,n,o){const i=rS(e);e.insert(e.createPositionAt(t,"end"),i);n.on("change:uploadedPercent",((t,e,n)=>{o.change((t=>{t.setStyle("width",n+"%",i)}))}))}function oS(t,e){cS(t,e,"progressBar")}function iS(t,e,n){const o=e.createUIElement("div",{class:"ck-image-upload-complete-icon"});e.insert(e.createPositionAt(t,"end"),o);setTimeout((()=>{n.change((t=>t.remove(t.createRangeOn(o))))}),3e3)}function rS(t){const e=t.createUIElement("div",{class:"ck-progress-bar"});t.setCustomProperty("progressBar",true,e);return e}function sS(t){const e=t.createUIElement("div",{class:"ck-upload-placeholder-loader"});t.setCustomProperty("placeholder",true,e);return e}function aS(t,e){for(const n of t.getChildren()){if(n.getCustomProperty(e)){return n}}}function cS(t,e,n){const o=aS(t,n);if(o){e.remove(e.createRangeOn(o))}}function lS(t,e,n){if(n.data){const o=GA(t);e.setAttribute("src",n.data,o)}}class dS{constructor(t){this.document=t}createDocumentFragment(t){return new Jl(this.document,t)}createElement(t,e,n){return new jc(this.document,t,e,n)}createText(t){return new Vs(this.document,t)}clone(t,e=false){return t._clone(e)}appendChild(t,e){return e._appendChild(t)}insertChild(t,e,n){return n._insertChild(t,e)}removeChildren(t,e,n){return n._removeChildren(t,e)}remove(t){const e=t.parent;if(e){return this.removeChildren(e.getChildIndex(t),1,e)}return[]}replace(t,e){const n=t.parent;if(n){const o=n.getChildIndex(t);this.removeChildren(o,1,n);this.insertChild(o,e,n);return true}return false}unwrapElement(t){const e=t.parent;if(e){const n=e.getChildIndex(t);this.remove(t);this.insertChild(n,t.getChildren(),e)}}rename(t,e){const n=new jc(this.document,t,e.getAttributes(),e.getChildren());return this.replace(e,n)?n:null}setAttribute(t,e,n){n._setAttribute(t,e)}removeAttribute(t,e){e._removeAttribute(t)}addClass(t,e){e._addClass(t)}removeClass(t,e){e._removeClass(t)}setStyle(t,e,n){if(P(t)&&n===undefined){n=e}n._setStyle(t,e)}removeStyle(t,e){e._removeStyle(t)}setCustomProperty(t,e,n){n._setCustomProperty(t,e)}removeCustomProperty(t,e){return e._removeCustomProperty(t)}createPositionAt(t,e){return hl._createAt(t,e)}createPositionAfter(t){return hl._createAfter(t)}createPositionBefore(t){return hl._createBefore(t)}createRange(t,e){return new fl(t,e)}createRangeOn(t){return fl._createOn(t)}createRangeIn(t){return fl._createIn(t)}createSelection(t,e,n){return new pl(t,e,n)}}class uS extends iC{refresh(){const t=this.editor.model.document.selection.getSelectedElement();const e=t&&t.name==="image"||false;this.isEnabled=HA(this.editor.model)||e}execute(t){const e=this.editor;const n=e.model;const o=e.plugins.get(NC);for(const e of xs(t.file)){hS(n,o,e)}}}function hS(t,e,n){const o=e.createLoader(n);if(!o){return}UA(t,{uploadId:o.id})}class fS extends nC{static get requires(){return[NC,ey,z_]}static get pluginName(){return"ImageUploadEditing"}constructor(t){super(t);t.config.define("image",{upload:{types:["jpeg","png","gif","bmp","webp","tiff"]}})}init(){const t=this.editor;const e=t.model.document;const n=t.model.schema;const o=t.conversion;const i=t.plugins.get(NC);const r=NT(t.config.get("image.upload.types"));n.extend("image",{allowAttributes:["uploadId","uploadStatus"]});t.commands.add("imageUpload",new uS(t));o.for("upcast").attributeToAttribute({view:{name:"img",key:"uploadId"},model:"uploadId"});this.listenTo(t.editing.view.document,"clipboardInput",((e,n)=>{if(mS(n.dataTransfer)){return}const o=Array.from(n.dataTransfer.files).filter((t=>{if(!t){return false}return r.test(t.type)}));const i=n.targetRanges.map((e=>t.editing.mapper.toModelRange(e)));t.model.change((n=>{n.setSelection(i);if(o.length){e.stop();t.model.enqueueChange("default",(()=>{t.execute("imageUpload",{file:o})}))}}))}));this.listenTo(t.plugins.get(z_),"inputTransformation",((e,n)=>{const o=Array.from(t.editing.view.createRangeIn(n.content)).filter((t=>PT(t.item)&&!t.item.getAttribute("uploadProcessed"))).map((t=>({promise:BT(t.item),imageElement:t.item})));if(!o.length){return}const r=new dS(t.editing.view.document);for(const t of o){r.setAttribute("uploadProcessed",true,t.imageElement);const e=i.createLoader(t.promise);if(e){r.setAttribute("src","",t.imageElement);r.setAttribute("uploadId",e.id,t.imageElement)}}}));t.editing.view.document.on("dragover",((t,e)=>{e.preventDefault()}));e.on("change",(()=>{const n=e.differ.getChanges({includeChangesInGraveyard:true});for(const e of n){if(e.type=="insert"&&e.name!="$text"){const n=e.position.nodeAfter;const o=e.position.root.rootName=="$graveyard";for(const e of gS(t,n)){const t=e.getAttribute("uploadId");if(!t){continue}const n=i.loaders.get(t);if(!n){continue}if(o){n.abort()}else if(n.status=="idle"){this._readAndUpload(n,e)}}}}}))}_readAndUpload(t,e){const n=this.editor;const o=n.model;const i=n.locale.t;const r=n.plugins.get(NC);const s=n.plugins.get(ey);o.enqueueChange("transparent",(t=>{t.setAttribute("uploadStatus","reading",e)}));return t.read().then((()=>{const i=t.upload();if(El.isSafari){const t=n.editing.mapper.toViewElement(e);const o=GA(t);n.editing.view.once("render",(()=>{if(!o.parent){return}const t=n.editing.view.domConverter.mapViewToDom(o.parent);if(!t){return}const e=t.style.display;t.style.display="none";t._ckHack=t.offsetHeight;t.style.display=e}))}o.enqueueChange("transparent",(t=>{t.setAttribute("uploadStatus","uploading",e)}));return i})).then((t=>{o.enqueueChange("transparent",(n=>{n.setAttributes({uploadStatus:"complete",src:t.default},e);this._parseAndSetSrcsetAttributeOnImage(t,e,n)}));a()})).catch((n=>{if(t.status!=="error"&&t.status!=="aborted"){throw n}if(t.status=="error"&&n){s.showWarning(n,{title:i("Upload failed"),namespace:"upload"})}a();o.enqueueChange("transparent",(t=>{t.remove(e)}))}));function a(){o.enqueueChange("transparent",(t=>{t.removeAttribute("uploadId",e);t.removeAttribute("uploadStatus",e)}));r.destroyLoader(t)}}_parseAndSetSrcsetAttributeOnImage(t,e,n){let o=0;const i=Object.keys(t).filter((t=>{const e=parseInt(t,10);if(!isNaN(e)){o=Math.max(o,e);return true}})).map((e=>`${t[e]} ${e}w`)).join(", ");if(i!=""){n.setAttribute("srcset",{data:i,width:o},e)}}}function mS(t){return Array.from(t.types).includes("text/html")&&t.getData("text/html")!==""}function gS(t,e){return Array.from(t.model.createRangeOn(e)).filter((t=>t.item.is("element","image"))).map((t=>t.item))}class pS extends nC{static get pluginName(){return"ImageUpload"}static get requires(){return[fS,OT,JT]}}class kS extends iC{constructor(t){super(t);this._childCommands=[]}refresh(){}execute(...t){const e=this._getFirstEnabledCommand();return e.execute(t)}registerChildCommand(t){this._childCommands.push(t);t.on("change:isEnabled",(()=>this._checkEnabled()));this._checkEnabled()}_checkEnabled(){this.isEnabled=!!this._getFirstEnabledCommand()}_getFirstEnabledCommand(){return this._childCommands.find((t=>t.isEnabled))}}class bS extends nC{static get pluginName(){return"IndentEditing"}init(){const t=this.editor;t.commands.add("indent",new kS(t));t.commands.add("outdent",new kS(t))}}var wS='';var CS='';class AS extends nC{static get pluginName(){return"IndentUI"}init(){const t=this.editor;const e=t.locale;const n=t.t;const o=e.uiLanguageDirection=="ltr"?wS:CS;const i=e.uiLanguageDirection=="ltr"?CS:wS;this._defineButton("indent",n("Increase indent"),o);this._defineButton("outdent",n("Decrease indent"),i)}_defineButton(t,e,n){const o=this.editor;o.ui.componentFactory.add(t,(i=>{const r=o.commands.get(t);const s=new cw(i);s.set({label:e,icon:n,tooltip:true});s.bind("isOn","isEnabled").to(r,"value","isEnabled");this.listenTo(s,"execute",(()=>{o.execute(t);o.editing.view.focus()}));return s}))}}class _S extends nC{static get pluginName(){return"Indent"}static get requires(){return[bS,AS]}}const vS="italic";class yS extends nC{static get pluginName(){return"ItalicEditing"}init(){const t=this.editor;t.model.schema.extend("$text",{allowAttributes:vS});t.model.schema.setAttributeProperties(vS,{isFormatting:true,copyOnEnter:true});t.conversion.attributeToElement({model:vS,view:"i",upcastAlso:["em",{styles:{"font-style":"italic"}}]});t.commands.add(vS,new YC(t,vS));t.keystrokes.set("CTRL+I",vS)}}var xS='';const DS="italic";class ES extends nC{init(){const t=this.editor;const e=t.t;t.ui.componentFactory.add(DS,(n=>{const o=t.commands.get(DS);const i=new cw(n);i.set({label:e("Italic"),icon:xS,keystroke:"CTRL+I",tooltip:true,isToggleable:true});i.bind("isOn","isEnabled").to(o,"value","isEnabled");this.listenTo(i,"execute",(()=>{t.execute(DS);t.editing.view.focus()}));return i}))}}class MS extends nC{static get requires(){return[yS,ES]}static get pluginName(){return"Italic"}}class TS extends nh{constructor(t){super(t);this.domEventType="click"}onDomEvent(t){this.fire(t.type,t)}}var SS=n(51);var IS={injectType:"singletonStyleTag",attributes:{"data-cke":true}};IS.insert="head";IS.singleton=true;var NS=rk()(SS["a"],IS);var BS=SS["a"].locals||{};class PS extends tb{constructor(t,e){super(t);const n=t.t;this.focusTracker=new tk;this.keystrokes=new Vp;this.urlInputView=this._createUrlInput();this.saveButtonView=this._createButton(n("Save"),PE,"ck-button-save");this.saveButtonView.type="submit";this.cancelButtonView=this._createButton(n("Cancel"),zE,"ck-button-cancel","cancel");this._manualDecoratorSwitches=this._createManualDecoratorSwitches(e);this.children=this._createFormChildren(e.manualDecorators);this._focusables=new Ak;this._focusCycler=new Db({focusables:this._focusables,focusTracker:this.focusTracker,keystrokeHandler:this.keystrokes,actions:{focusPrevious:"shift + tab",focusNext:"tab"}});const o=["ck","ck-link-form","ck-responsive-form"];if(e.manualDecorators.length){o.push("ck-link-form_layout-vertical","ck-vertical-form")}this.setTemplate({tag:"form",attributes:{class:o,tabindex:"-1"},children:this.children});NE(this)}getDecoratorSwitchesState(){return Array.from(this._manualDecoratorSwitches).reduce(((t,e)=>{t[e.name]=e.isOn;return t}),{})}render(){super.render();BE({view:this});const t=[this.urlInputView,...this._manualDecoratorSwitches,this.saveButtonView,this.cancelButtonView];t.forEach((t=>{this._focusables.add(t);this.focusTracker.add(t.element)}));this.keystrokes.listenTo(this.element)}focus(){this._focusCycler.focusFirst()}_createUrlInput(){const t=this.locale.t;const e=new vE(this.locale,SE);e.label=t("Link URL");return e}_createButton(t,e,n,o){const i=new cw(this.locale);i.set({label:t,icon:e,tooltip:true});i.extendTemplate({attributes:{class:n}});if(o){i.delegate("execute").to(this,o)}return i}_createManualDecoratorSwitches(t){const e=this.createCollection();for(const n of t.manualDecorators){const o=new _w(this.locale);o.set({name:n.id,label:n.label,withText:true});o.bind("isOn").toMany([n,t],"value",((t,e)=>e===undefined&&t===undefined?n.defaultValue:t));o.on("execute",(()=>{n.set("value",!o.isOn)}));e.add(o)}return e}_createFormChildren(t){const e=this.createCollection();e.add(this.urlInputView);if(t.length){const t=new tb;t.setTemplate({tag:"ul",children:this._manualDecoratorSwitches.map((t=>({tag:"li",children:[t],attributes:{class:["ck","ck-list__item"]}}))),attributes:{class:["ck","ck-reset","ck-list"]}});e.add(t)}e.add(this.saveButtonView);e.add(this.cancelButtonView);return e}}var zS='';var LS='';var OS=n(52);var RS={injectType:"singletonStyleTag",attributes:{"data-cke":true}};RS.insert="head";RS.singleton=true;var jS=rk()(OS["a"],RS);var FS=OS["a"].locals||{};class VS extends tb{constructor(t){super(t);const e=t.t;this.focusTracker=new tk;this.keystrokes=new Vp;this.previewButtonView=this._createPreviewButton();this.unlinkButtonView=this._createButton(e("Unlink"),zS,"unlink");this.editButtonView=this._createButton(e("Edit link"),LS,"edit");this.set("href");this._focusables=new Ak;this._focusCycler=new Db({focusables:this._focusables,focusTracker:this.focusTracker,keystrokeHandler:this.keystrokes,actions:{focusPrevious:"shift + tab",focusNext:"tab"}});this.setTemplate({tag:"div",attributes:{class:["ck","ck-link-actions","ck-responsive-form"],tabindex:"-1"},children:[this.previewButtonView,this.editButtonView,this.unlinkButtonView]})}render(){super.render();const t=[this.previewButtonView,this.editButtonView,this.unlinkButtonView];t.forEach((t=>{this._focusables.add(t);this.focusTracker.add(t.element)}));this.keystrokes.listenTo(this.element)}focus(){this._focusCycler.focusFirst()}_createButton(t,e,n){const o=new cw(this.locale);o.set({label:t,icon:e,tooltip:true});o.delegate("execute").to(this,n);return o}_createPreviewButton(){const t=new cw(this.locale);const e=this.bindTemplate;const n=this.t;t.set({withText:true,tooltip:n("Open link in new tab")});t.extendTemplate({attributes:{class:["ck","ck-link-actions__preview"],href:e.to("href",(t=>t&&Bv(t))),target:"_blank",rel:"noopener noreferrer"}});t.bind("label").to(this,"href",(t=>t||n("This link has no URL")));t.bind("isEnabled").to(this,"href",(t=>!!t));t.template.tag="a";t.template.eventListeners={};return t}}var US='';const HS="link-ui";class GS extends nC{static get requires(){return[nM]}static get pluginName(){return"LinkUI"}init(){const t=this.editor;t.editing.view.addObserver(TS);this.actionsView=this._createActionsView();this.formView=this._createFormView();this._balloon=t.plugins.get(nM);this._createToolbarLinkButton();this._enableUserBalloonInteractions();t.conversion.for("editingDowncast").markerToHighlight({model:HS,view:{classes:["ck-fake-link-selection"]}});t.conversion.for("editingDowncast").markerToElement({model:HS,view:{name:"span",classes:["ck-fake-link-selection","ck-fake-link-selection_collapsed"]}})}destroy(){super.destroy();this.formView.destroy()}_createActionsView(){const t=this.editor;const e=new VS(t.locale);const n=t.commands.get("link");const o=t.commands.get("unlink");e.bind("href").to(n,"value");e.editButtonView.bind("isEnabled").to(n);e.unlinkButtonView.bind("isEnabled").to(o);this.listenTo(e,"edit",(()=>{this._addFormView()}));this.listenTo(e,"unlink",(()=>{t.execute("unlink");this._hideUI()}));e.keystrokes.set("Esc",((t,e)=>{this._hideUI();e()}));e.keystrokes.set(Sv,((t,e)=>{this._addFormView();e()}));return e}_createFormView(){const t=this.editor;const e=t.commands.get("link");const n=t.config.get("link.defaultProtocol");const o=new PS(t.locale,e);o.urlInputView.fieldView.bind("value").to(e,"value");o.urlInputView.bind("isReadOnly").to(e,"isEnabled",(t=>!t));o.saveButtonView.bind("isEnabled").to(e);this.listenTo(o,"submit",(()=>{const{value:e}=o.urlInputView.fieldView.element;const i=jv(e,n);t.execute("link",i,o.getDecoratorSwitchesState());this._closeFormView()}));this.listenTo(o,"cancel",(()=>{this._closeFormView()}));o.keystrokes.set("Esc",((t,e)=>{this._closeFormView();e()}));return o}_createToolbarLinkButton(){const t=this.editor;const e=t.commands.get("link");const n=t.t;t.keystrokes.set(Sv,((t,n)=>{n();if(e.isEnabled){this._showUI(true)}}));t.ui.componentFactory.add("link",(t=>{const o=new cw(t);o.isEnabled=true;o.label=n("Link");o.icon=US;o.keystroke=Sv;o.tooltip=true;o.isToggleable=true;o.bind("isEnabled").to(e,"isEnabled");o.bind("isOn").to(e,"value",(t=>!!t));this.listenTo(o,"execute",(()=>this._showUI(true)));return o}))}_enableUserBalloonInteractions(){const t=this.editor.editing.view.document;this.listenTo(t,"click",(()=>{const t=this._getSelectedLinkElement();if(t){this._showUI()}}));this.editor.keystrokes.set("Tab",((t,e)=>{if(this._areActionsVisible&&!this.actionsView.focusTracker.isFocused){this.actionsView.focus();e()}}),{priority:"high"});this.editor.keystrokes.set("Esc",((t,e)=>{if(this._isUIVisible){this._hideUI();e()}}));vw({emitter:this.formView,activator:()=>this._isUIInPanel,contextElements:[this._balloon.view.element],callback:()=>this._hideUI()})}_addActionsView(){if(this._areActionsInPanel){return}this._balloon.add({view:this.actionsView,position:this._getBalloonPositionData()})}_addFormView(){if(this._isFormInPanel){return}const t=this.editor;const e=t.commands.get("link");this.formView.disableCssTransitions();this._balloon.add({view:this.formView,position:this._getBalloonPositionData()});if(this._balloon.visibleView===this.formView){this.formView.urlInputView.fieldView.select()}this.formView.enableCssTransitions();this.formView.urlInputView.fieldView.element.value=e.value||""}_closeFormView(){const t=this.editor.commands.get("link");t.restoreManualDecoratorStates();if(t.value!==undefined){this._removeFormView()}else{this._hideUI()}}_removeFormView(){if(this._isFormInPanel){this.formView.saveButtonView.focus();this._balloon.remove(this.formView);this.editor.editing.view.focus();this._hideFakeVisualSelection()}}_showUI(t=false){if(!this._getSelectedLinkElement()){this._showFakeVisualSelection();this._addActionsView();if(t){this._balloon.showStack("main")}this._addFormView()}else{if(this._areActionsVisible){this._addFormView()}else{this._addActionsView()}if(t){this._balloon.showStack("main")}}this._startUpdatingUI()}_hideUI(){if(!this._isUIInPanel){return}const t=this.editor;this.stopListening(t.ui,"update");this.stopListening(this._balloon,"change:visibleView");t.editing.view.focus();this._removeFormView();this._balloon.remove(this.actionsView);this._hideFakeVisualSelection()}_startUpdatingUI(){const t=this.editor;const e=t.editing.view.document;let n=this._getSelectedLinkElement();let o=r();const i=()=>{const t=this._getSelectedLinkElement();const e=r();if(n&&!t||!n&&e!==o){this._hideUI()}else if(this._isUIVisible){this._balloon.updatePosition(this._getBalloonPositionData())}n=t;o=e};function r(){return e.selection.focus.getAncestors().reverse().find((t=>t.is("element")))}this.listenTo(t.ui,"update",i);this.listenTo(this._balloon,"change:visibleView",i)}get _isFormInPanel(){return this._balloon.hasView(this.formView)}get _areActionsInPanel(){return this._balloon.hasView(this.actionsView)}get _areActionsVisible(){return this._balloon.visibleView===this.actionsView}get _isUIInPanel(){return this._isFormInPanel||this._areActionsInPanel}get _isUIVisible(){const t=this._balloon.visibleView;return t==this.formView||this._areActionsVisible}_getBalloonPositionData(){const t=this.editor.editing.view;const e=this.editor.model;const n=t.document;let o=null;if(e.markers.has(HS)){const e=Array.from(this.editor.editing.mapper.markerNameToElements(HS));const n=t.createRange(t.createPositionBefore(e[0]),t.createPositionAfter(e[e.length-1]));o=t.domConverter.viewRangeToDom(n)}else{const e=this._getSelectedLinkElement();const i=n.selection.getFirstRange();o=e?t.domConverter.mapViewToDom(e):t.domConverter.viewRangeToDom(i)}return{target:o}}_getSelectedLinkElement(){const t=this.editor.editing.view;const e=t.document.selection;if(e.isCollapsed){return KS(e.getFirstPosition())}else{const n=e.getFirstRange().getTrimmed();const o=KS(n.start);const i=KS(n.end);if(!o||o!=i){return null}if(t.createRangeIn(o).getTrimmed().isEqual(n)){return o}else{return null}}}_showFakeVisualSelection(){const t=this.editor.model;t.change((e=>{const n=t.document.selection.getFirstRange();if(t.markers.has(HS)){e.updateMarker(HS,{range:n})}else{if(n.start.isAtEnd){const o=t.document.selection.focus;const i=WS(n,o,e);e.addMarker(HS,{usingOperation:false,affectsData:false,range:i})}else{e.addMarker(HS,{usingOperation:false,affectsData:false,range:n})}}}))}_hideFakeVisualSelection(){const t=this.editor.model;if(t.markers.has(HS)){t.change((t=>{t.removeMarker(HS)}))}}}function KS(t){return t.getAncestors().find((t=>Iv(t)))}function WS(t,e,n){const o=[t.start.path[0]+1,0];const i=n.createPositionFromPath(t.start.root,o,"toNext");const r=n.createRange(i,t.end);if(r.start.path[0]>t.end.path[0]){return n.createRange(e)}if(i.isAtStart&&i.isAtEnd){return WS(r,e,n)}return r}function qS(t,e){let n=t.start;const o=Array.from(t.getItems()).reduce(((t,o)=>{if(!(o.is("$text")||o.is("$textProxy"))){n=e.createPositionAfter(o);return""}return t+o.data}),"");return{text:o,range:e.createRange(n,t.end)}}class YS{constructor(t,e){this.model=t;this.testCallback=e;this.hasMatch=false;this.set("isEnabled",true);this.on("change:isEnabled",(()=>{if(this.isEnabled){this._startListening()}else{this.stopListening(t.document.selection);this.stopListening(t.document)}}));this._startListening()}_startListening(){const t=this.model;const e=t.document;this.listenTo(e.selection,"change:range",((t,{directChange:n})=>{if(!n){return}if(!e.selection.isCollapsed){if(this.hasMatch){this.fire("unmatched");this.hasMatch=false}return}this._evaluateTextBeforeSelection("selection")}));this.listenTo(e,"change:data",((t,e)=>{if(e.type=="transparent"){return}this._evaluateTextBeforeSelection("data",{batch:e})}))}_evaluateTextBeforeSelection(t,e={}){const n=this.model;const o=n.document;const i=o.selection;const r=n.createRange(n.createPositionAt(i.focus.parent,0),i.focus);const{text:s,range:a}=qS(r,n);const c=this.testCallback(s);if(!c&&this.hasMatch){this.fire("unmatched")}this.hasMatch=!!c;if(c){const n=Object.assign(e,{text:s,range:a});if(typeof c=="object"){Object.assign(n,c)}this.fire(`matched:${t}`,n)}}}_s(YS,Jc);const QS=4;const $S=new RegExp("(^|\\s)"+"("+"("+"(?:(?:(?:https?|ftp):)?\\/\\/)"+"(?:\\S+(?::\\S*)?@)?"+"(?:"+"(?![-_])(?:[-\\w\\u00a1-\\uffff]{0,63}[^-_]\\.)+"+"(?:[a-z\\u00a1-\\uffff]{2,})"+")"+"(?::\\d{2,5})?"+"(?:[/?#]\\S*)?"+")"+"|"+"("+"(www.|(\\S+@))"+"((?![-_])(?:[-\\w\\u00a1-\\uffff]{0,63}[^-_]\\.))+"+"(?:[a-z\\u00a1-\\uffff]{2,})"+")"+")$","i");const JS=2;class ZS extends nC{static get pluginName(){return"AutoLink"}init(){const t=this.editor;const e=t.model.document.selection;e.on("change:range",(()=>{this.isEnabled=!e.anchor.parent.is("element","codeBlock")}));this._enableTypingHandling()}afterInit(){this._enableEnterHandling();this._enableShiftEnterHandling()}_enableTypingHandling(){const t=this.editor;const e=new YS(t.model,(t=>{if(!XS(t)){return}const e=tI(t.substr(0,t.length-1));if(e){return{url:e}}}));const n=t.plugins.get("Input");e.on("matched:data",((e,o)=>{const{batch:i,range:r,url:s}=o;if(!n.isInput(i)){return}const a=r.end.getShiftedBy(-1);const c=a.getShiftedBy(-s.length);const l=t.model.createRange(c,a);this._applyAutoLink(s,l)}));e.bind("isEnabled").to(this)}_enableEnterHandling(){const t=this.editor;const e=t.model;const n=t.commands.get("enter");if(!n){return}n.on("execute",(()=>{const t=e.document.selection.getFirstPosition();if(!t.parent.previousSibling){return}const n=e.createRangeIn(t.parent.previousSibling);this._checkAndApplyAutoLinkOnRange(n)}))}_enableShiftEnterHandling(){const t=this.editor;const e=t.model;const n=t.commands.get("shiftEnter");if(!n){return}n.on("execute",(()=>{const t=e.document.selection.getFirstPosition();const n=e.createRange(e.createPositionAt(t.parent,0),t.getShiftedBy(-1));this._checkAndApplyAutoLinkOnRange(n)}))}_checkAndApplyAutoLinkOnRange(t){const e=this.editor.model;const{text:n,range:o}=qS(t,e);const i=tI(n);if(i){const t=e.createRange(o.end.getShiftedBy(-i.length),o.end);this._applyAutoLink(i,t)}}_applyAutoLink(t,e){const n=this.editor.model;if(!this.isEnabled||!eI(e,n)){return}n.enqueueChange((n=>{const o=this.editor.config.get("link.defaultProtocol");const i=jv(t,o);n.setAttribute("linkHref",i,e)}))}}function XS(t){return t.length>QS&&t[t.length-1]===" "&&t[t.length-2]!==" "}function tI(t){const e=$S.exec(t);return e?e[JS]:null}function eI(t,e){return e.schema.checkAttributeInSelection(e.createSelection(t),"linkHref")}class nI extends nC{static get requires(){return[Jv,GS,ZS]}static get pluginName(){return"Link"}}class oI extends iC{constructor(t,e){super(t);this.type=e}refresh(){this.value=this._getValue();this.isEnabled=this._checkEnabled()}execute(){const t=this.editor.model;const e=t.document;const n=Array.from(e.selection.getSelectedBlocks()).filter((e=>rI(e,t.schema)));const o=this.value===true;t.change((t=>{if(o){let e=n[n.length-1].nextSibling;let o=Number.POSITIVE_INFINITY;let i=[];while(e&&e.name=="listItem"&&e.getAttribute("listIndent")!==0){const t=e.getAttribute("listIndent");if(t=n){if(r>i.getAttribute("listIndent")){r=i.getAttribute("listIndent")}if(i.getAttribute("listIndent")==r){t[e?"unshift":"push"](i)}i=i[e?"previousSibling":"nextSibling"]}}}function rI(t,e){return e.checkChild(t.parent,"listItem")&&!e.isObject(t)}class sI extends iC{constructor(t,e){super(t);this._indentBy=e=="forward"?1:-1}refresh(){this.isEnabled=this._checkEnabled()}execute(){const t=this.editor.model;const e=t.document;let n=Array.from(e.selection.getSelectedBlocks());t.change((t=>{const e=n[n.length-1];let o=e.nextSibling;while(o&&o.name=="listItem"&&o.getAttribute("listIndent")>e.getAttribute("listIndent")){n.push(o);o=o.nextSibling}if(this._indentBy<0){n=n.reverse()}for(const e of n){const n=e.getAttribute("listIndent")+this._indentBy;if(n<0){t.rename(e,"paragraph")}else{t.setAttribute("listIndent",n,e)}}this.fire("_executeCleanup",n)}))}_checkEnabled(){const t=sC(this.editor.model.document.selection.getSelectedBlocks());if(!t||!t.is("element","listItem")){return false}if(this._indentBy>0){const e=t.getAttribute("listIndent");const n=t.getAttribute("listType");let o=t.previousSibling;while(o&&o.is("element","listItem")&&o.getAttribute("listIndent")>=e){if(o.getAttribute("listIndent")==e){return o.getAttribute("listType")==n}o=o.previousSibling}return false}return true}}function aI(t){const e=t.createContainerElement("li");e.getFillerOffset=pI;return e}function cI(t,e){const n=e.mapper;const o=e.writer;const i=t.getAttribute("listType")=="numbered"?"ol":"ul";const r=aI(o);const s=o.createContainerElement(i,null);o.insert(o.createPositionAt(s,0),r);n.bindElements(t,r);return r}function lI(t,e,n,o){const i=e.parent;const r=n.mapper;const s=n.writer;let a=r.toViewPosition(o.createPositionBefore(t));const c=hI(t.previousSibling,{sameIndent:true,smallerIndent:true,listIndent:t.getAttribute("listIndent")});const l=t.previousSibling;if(c&&c.getAttribute("listIndent")==t.getAttribute("listIndent")){const t=r.toViewElement(c);a=s.breakContainer(s.createPositionAfter(t))}else{if(l&&l.name=="listItem"){a=r.toViewPosition(o.createPositionAt(l,"end"));const t=r.findMappedViewAncestor(a);const e=mI(t);if(e){a=s.createPositionBefore(e)}else{a=s.createPositionAt(t,"end")}}else{a=r.toViewPosition(o.createPositionBefore(t))}}a=uI(a);s.insert(a,i);if(l&&l.name=="listItem"){const t=r.toViewElement(l);const n=s.createRange(s.createPositionAt(t,0),a);const o=n.getWalker({ignoreElementEnd:true});for(const t of o){if(t.item.is("element","li")){const n=s.breakContainer(s.createPositionBefore(t.item));const i=t.item.parent;const r=s.createPositionAt(e,"end");dI(s,r.nodeBefore,r.nodeAfter);s.move(s.createRangeOn(i),r);o.position=n}}}else{const n=i.nextSibling;if(n&&(n.is("element","ul")||n.is("element","ol"))){let o=null;for(const e of n.getChildren()){const n=r.toModelElement(e);if(n&&n.getAttribute("listIndent")>t.getAttribute("listIndent")){o=e}else{break}}if(o){s.breakContainer(s.createPositionAfter(o));s.move(s.createRangeOn(o.parent),s.createPositionAt(e,"end"))}}}dI(s,i,i.nextSibling);dI(s,i.previousSibling,i)}function dI(t,e,n){if(!e||!n||e.name!="ul"&&e.name!="ol"){return null}if(e.name!=n.name||e.getAttribute("class")!==n.getAttribute("class")){return null}return t.mergeContainers(t.createPositionAfter(e))}function uI(t){return t.getLastMatchingPosition((t=>t.item.is("uiElement")))}function hI(t,e){const n=!!e.sameIndent;const o=!!e.smallerIndent;const i=e.listIndent;let r=t;while(r&&r.name=="listItem"){const t=r.getAttribute("listIndent");if(n&&i==t||o&&i>t){return r}if(e.direction==="forward"){r=r.nextSibling}else{r=r.previousSibling}}return null}function fI(t,e,n,o){t.ui.componentFactory.add(e,(i=>{const r=t.commands.get(e);const s=new cw(i);s.set({label:n,icon:o,tooltip:true,isToggleable:true});s.bind("isOn","isEnabled").to(r,"value","isEnabled");s.on("execute",(()=>{t.execute(e);t.editing.view.focus()}));return s}))}function mI(t){for(const e of t.getChildren()){if(e.name=="ul"||e.name=="ol"){return e}}return null}function gI(t,e){const n=[];const o=t.parent;const i={ignoreElementEnd:true,startPosition:t,shallow:true,direction:e};const r=o.getAttribute("listIndent");const s=[...new Qh(i)].filter((t=>t.item.is("element"))).map((t=>t.item));for(const t of s){if(!t.is("element","listItem")){break}if(t.getAttribute("listIndent")r){continue}if(t.getAttribute("listType")!==o.getAttribute("listType")){break}if(t.getAttribute("listStyle")!==o.getAttribute("listStyle")){break}if(e==="backward"){n.unshift(t)}else{n.push(t)}}return n}function pI(){const t=!this.isEmpty&&(this.getChild(0).name=="ul"||this.getChild(0).name=="ol");if(this.isEmpty||t){return 0}return Gc.call(this)}function kI(t){return(e,n,o)=>{const i=o.consumable;if(!i.test(n.item,"insert")||!i.test(n.item,"attribute:listType")||!i.test(n.item,"attribute:listIndent")){return}i.consume(n.item,"insert");i.consume(n.item,"attribute:listType");i.consume(n.item,"attribute:listIndent");const r=n.item;const s=cI(r,o);lI(r,s,o,t)}}function bI(t){return(e,n,o)=>{const i=o.mapper.toViewPosition(n.position);const r=i.getLastMatchingPosition((t=>!t.item.is("element","li")));const s=r.nodeAfter;const a=o.writer;a.breakContainer(a.createPositionBefore(s));a.breakContainer(a.createPositionAfter(s));const c=s.parent;const l=c.previousSibling;const d=a.createRangeOn(c);const u=a.remove(d);if(l&&l.nextSibling){dI(a,l,l.nextSibling)}const h=o.mapper.toModelElement(s);BI(h.getAttribute("listIndent")+1,n.position,d.start,s,o,t);for(const t of a.createRangeIn(u).getItems()){o.mapper.unbindViewElement(t)}e.stop()}}function wI(t,e,n){if(!n.consumable.consume(e.item,"attribute:listType")){return}const o=n.mapper.toViewElement(e.item);const i=n.writer;i.breakContainer(i.createPositionBefore(o));i.breakContainer(i.createPositionAfter(o));const r=o.parent;const s=e.attributeNewValue=="numbered"?"ol":"ul";i.rename(s,r)}function CI(t,e,n){const o=n.mapper.toViewElement(e.item);const i=o.parent;const r=n.writer;dI(r,i,i.nextSibling);dI(r,i.previousSibling,i);for(const t of e.item.getChildren()){n.consumable.consume(t,"insert")}}function AI(t){return(e,n,o)=>{if(!o.consumable.consume(n.item,"attribute:listIndent")){return}const i=o.mapper.toViewElement(n.item);const r=o.writer;r.breakContainer(r.createPositionBefore(i));r.breakContainer(r.createPositionAfter(i));const s=i.parent;const a=s.previousSibling;const c=r.createRangeOn(s);r.remove(c);if(a&&a.nextSibling){dI(r,a,a.nextSibling)}BI(n.attributeOldValue+1,n.range.start,c.start,i,o,t);lI(n.item,i,o,t);for(const t of n.item.getChildren()){o.consumable.consume(t,"insert")}}}function _I(t,e,n){if(e.item.name!="listItem"){let t=n.mapper.toViewPosition(e.range.start);const o=n.writer;const i=[];while(t.parent.name=="ul"||t.parent.name=="ol"){t=o.breakContainer(t);if(t.parent.name!="li"){break}const e=t;const n=o.createPositionAt(t.parent,"end");if(!e.isEqual(n)){const t=o.remove(o.createRange(e,n));i.push(t)}t=o.createPositionAfter(t.parent)}if(i.length>0){for(let e=0;e0){const e=dI(o,n,n.nextSibling);if(e&&e.parent==n){t.offset--}}}dI(o,t.nodeBefore,t.nodeAfter)}}}function vI(t,e,n){const o=n.mapper.toViewPosition(e.position);const i=o.nodeBefore;const r=o.nodeAfter;dI(n.writer,i,r)}function yI(t,e,n){if(n.consumable.consume(e.viewItem,{name:true})){const t=n.writer;const o=t.createElement("listItem");const i=zI(e.viewItem);t.setAttribute("listIndent",i,o);const r=e.viewItem.parent&&e.viewItem.parent.name=="ol"?"numbered":"bulleted";t.setAttribute("listType",r,o);if(!n.safeInsert(o,e.modelCursor)){return}const s=II(o,e.viewItem.getChildren(),n);e.modelRange=t.createRange(e.modelCursor,s);n.updateConversionResult(o,e)}}function xI(t,e,n){if(n.consumable.test(e.viewItem,{name:true})){const t=Array.from(e.viewItem.getChildren());for(const e of t){const t=!(e.is("element","li")||PI(e));if(t){e._remove()}}}}function DI(t,e,n){if(n.consumable.test(e.viewItem,{name:true})){if(e.viewItem.childCount===0){return}const t=[...e.viewItem.getChildren()];let n=false;let o=true;for(const e of t){if(n&&!PI(e)){e._remove()}if(e.is("$text")){if(o){e._data=e.data.replace(/^\s+/,"")}if(!e.nextSibling||PI(e.nextSibling)){e._data=e.data.replace(/\s+$/,"")}}else if(PI(e)){n=true}o=false}}}function EI(t){return(e,n)=>{if(n.isPhantom){return}const o=n.modelPosition.nodeBefore;if(o&&o.is("element","listItem")){const e=n.mapper.toViewElement(o);const i=e.getAncestors().find(PI);const r=t.createPositionAt(e,0).getWalker();for(const t of r){if(t.type=="elementStart"&&t.item.is("element","li")){n.viewPosition=t.previousPosition;break}else if(t.type=="elementEnd"&&t.item==i){n.viewPosition=t.nextPosition;break}}}}}function MI(t){return(e,n)=>{const o=n.viewPosition;const i=o.parent;const r=n.mapper;if(i.name=="ul"||i.name=="ol"){if(!o.isAtEnd){const e=r.toModelElement(o.nodeAfter);n.modelPosition=t.createPositionBefore(e)}else{const e=r.toModelElement(o.nodeBefore);const i=r.getModelLength(o.nodeBefore);n.modelPosition=t.createPositionBefore(e).getShiftedBy(i)}e.stop()}else if(i.name=="li"&&o.nodeBefore&&(o.nodeBefore.name=="ul"||o.nodeBefore.name=="ol")){const s=r.toModelElement(i);let a=1;let c=o.nodeBefore;while(c&&PI(c)){a+=r.getModelLength(c);c=c.previousSibling}n.modelPosition=t.createPositionBefore(s).getShiftedBy(a);e.stop()}}}function TI(t,e){const n=t.document.differ.getChanges();const o=new Map;let i=false;for(const o of n){if(o.type=="insert"&&o.name=="listItem"){r(o.position)}else if(o.type=="insert"&&o.name!="listItem"){if(o.name!="$text"){const n=o.position.nodeAfter;if(n.hasAttribute("listIndent")){e.removeAttribute("listIndent",n);i=true}if(n.hasAttribute("listType")){e.removeAttribute("listType",n);i=true}if(n.hasAttribute("listStyle")){e.removeAttribute("listStyle",n);i=true}for(const e of Array.from(t.createRangeIn(n)).filter((t=>t.item.is("element","listItem")))){r(e.previousPosition)}}const n=o.position.getShiftedBy(o.length);r(n)}else if(o.type=="remove"&&o.name=="listItem"){r(o.position)}else if(o.type=="attribute"&&o.attributeKey=="listIndent"){r(o.range.start)}else if(o.type=="attribute"&&o.attributeKey=="listType"){r(o.range.start)}}for(const t of o.values()){s(t);a(t)}return i;function r(t){const e=t.nodeBefore;if(!e||!e.is("element","listItem")){const e=t.nodeAfter;if(e&&e.is("element","listItem")){o.set(e,e)}}else{let t=e;if(o.has(t)){return}for(let e=t.previousSibling;e&&e.is("element","listItem");e=t.previousSibling){t=e;if(o.has(t)){return}}o.set(e,t)}}function s(t){let n=0;let o=null;while(t&&t.is("element","listItem")){const r=t.getAttribute("listIndent");if(r>n){let s;if(o===null){o=r-n;s=n}else{if(o>r){o=r}s=r-o}e.setAttribute("listIndent",s,t);i=true}else{o=null;n=t.getAttribute("listIndent")+1}t=t.nextSibling}}function a(t){let n=[];let o=null;while(t&&t.is("element","listItem")){const r=t.getAttribute("listIndent");if(o&&o.getAttribute("listIndent")>r){n=n.slice(0,r+1)}if(r!=0){if(n[r]){const o=n[r];if(t.getAttribute("listType")!=o){e.setAttribute("listType",o,t);i=true}}else{n[r]=t.getAttribute("listType")}}o=t;t=t.nextSibling}}}function SI(t,[e,n]){let o=e.is("documentFragment")?e.getChild(0):e;let i;if(!n){i=this.document.selection}else{i=this.createSelection(n)}if(o&&o.is("element","listItem")){const t=i.getFirstPosition();let e=null;if(t.parent.is("element","listItem")){e=t.parent}else if(t.nodeBefore&&t.nodeBefore.is("element","listItem")){e=t.nodeBefore}if(e){const t=e.getAttribute("listIndent");if(t>0){while(o&&o.is("element","listItem")){o._setAttribute("listIndent",o.getAttribute("listIndent")+t);o=o.nextSibling}}}}}function II(t,e,n){const{writer:o,schema:i}=n;let r=o.createPositionAfter(t);for(const s of e){if(s.name=="ul"||s.name=="ol"){r=n.convertItem(s,r).modelCursor}else{const e=n.convertItem(s,o.createPositionAt(t,"end"));const a=e.modelRange.start.nodeAfter;const c=a&&a.is("element")&&!i.checkChild(t,a.name);if(c){if(e.modelCursor.parent.is("element","listItem")){t=e.modelCursor.parent}else{t=NI(e.modelCursor)}r=o.createPositionAfter(t)}}}return r}function NI(t){const e=new Qh({startPosition:t});let n;do{n=e.next()}while(!n.value.item.is("element","listItem"));return n.value.item}function BI(t,e,n,o,i,r){const s=hI(e.nodeBefore,{sameIndent:true,smallerIndent:true,listIndent:t,foo:"b"});const a=i.mapper;const c=i.writer;const l=s?s.getAttribute("listIndent"):null;let d;if(!s){d=n}else if(l==t){const t=a.toViewElement(s).parent;d=c.createPositionAfter(t)}else{const t=r.createPositionAt(s,"end");d=a.toViewPosition(t)}d=uI(d);for(const t of[...o.getChildren()]){if(PI(t)){d=c.move(c.createRangeOn(t),d).end;dI(c,t,t.nextSibling);dI(c,t.previousSibling,t)}}}function PI(t){return t.is("element","ol")||t.is("element","ul")}function zI(t){let e=0;let n=t.parent;while(n){if(n.is("element","li")){e++}else{const t=n.previousSibling;if(t&&t.is("element","li")){e++}}n=n.parent}return e}class LI extends nC{static get pluginName(){return"ListEditing"}static get requires(){return[wD]}init(){const t=this.editor;t.model.schema.register("listItem",{inheritAllFrom:"$block",allowAttributes:["listType","listIndent"]});const e=t.data;const n=t.editing;t.model.document.registerPostFixer((e=>TI(t.model,e)));n.mapper.registerViewToModelLength("li",OI);e.mapper.registerViewToModelLength("li",OI);n.mapper.on("modelToViewPosition",EI(n.view));n.mapper.on("viewToModelPosition",MI(t.model));e.mapper.on("modelToViewPosition",EI(n.view));t.conversion.for("editingDowncast").add((e=>{e.on("insert",_I,{priority:"high"});e.on("insert:listItem",kI(t.model));e.on("attribute:listType:listItem",wI,{priority:"high"});e.on("attribute:listType:listItem",CI,{priority:"low"});e.on("attribute:listIndent:listItem",AI(t.model));e.on("remove:listItem",bI(t.model));e.on("remove",vI,{priority:"low"})}));t.conversion.for("dataDowncast").add((e=>{e.on("insert",_I,{priority:"high"});e.on("insert:listItem",kI(t.model))}));t.conversion.for("upcast").add((t=>{t.on("element:ul",xI,{priority:"high"});t.on("element:ol",xI,{priority:"high"});t.on("element:li",DI,{priority:"high"});t.on("element:li",yI)}));t.model.on("insertContent",SI,{priority:"high"});t.commands.add("numberedList",new oI(t,"numbered"));t.commands.add("bulletedList",new oI(t,"bulleted"));t.commands.add("indentList",new sI(t,"forward"));t.commands.add("outdentList",new sI(t,"backward"));const o=n.view.document;this.listenTo(o,"enter",((t,e)=>{const n=this.editor.model.document;const o=n.selection.getLastPosition().parent;if(n.selection.isCollapsed&&o.name=="listItem"&&o.isEmpty){this.editor.execute("outdentList");e.preventDefault();t.stop()}}));this.listenTo(o,"delete",((t,e)=>{if(e.direction!=="backward"){return}const n=this.editor.model.document.selection;if(!n.isCollapsed){return}const o=n.getFirstPosition();if(!o.isAtStart){return}const i=o.parent;if(i.name!=="listItem"){return}const r=i.previousSibling&&i.previousSibling.name==="listItem";if(r){return}this.editor.execute("outdentList");e.preventDefault();t.stop()}),{priority:"high"});const i=t=>(e,n)=>{const o=this.editor.commands.get(t);if(o.isEnabled){this.editor.execute(t);n()}};t.keystrokes.set("Tab",i("indentList"));t.keystrokes.set("Shift+Tab",i("outdentList"))}afterInit(){const t=this.editor.commands;const e=t.get("indent");const n=t.get("outdent");if(e){e.registerChildCommand(t.get("indentList"))}if(n){n.registerChildCommand(t.get("outdentList"))}}}function OI(t){let e=1;for(const n of t.getChildren()){if(n.name=="ul"||n.name=="ol"){for(const t of n.getChildren()){e+=OI(t)}}}return e}var RI='';var jI='';class FI extends nC{init(){const t=this.editor.t;fI(this.editor,"numberedList",t("Numbered List"),RI);fI(this.editor,"bulletedList",t("Bulleted List"),jI)}}class VI extends nC{static get requires(){return[LI,FI]}static get pluginName(){return"List"}}function UI(t,e){return t=>{t.on("attribute:url:media",n)};function n(n,o,i){if(!i.consumable.consume(o.item,n.name)){return}const r=o.attributeNewValue;const s=i.writer;const a=i.mapper.toViewElement(o.item);const c=[...a.getChildren()].find((t=>t.getCustomProperty("media-content")));s.remove(c);const l=t.getMediaViewElement(s,r,e);s.insert(s.createPositionAt(a,0),l)}}function HI(t,e,n){e.setCustomProperty("media",true,t);return MA(t,e,{label:n})}function GI(t){const e=t.getSelectedElement();if(e&&KI(e)){return e}return null}function KI(t){return!!t.getCustomProperty("media")&&EA(t)}function WI(t,e,n,o){const i=t.createContainerElement("figure",{class:"media"});t.insert(t.createPositionAt(i,0),e.getMediaViewElement(t,n,o));return i}function qI(t){const e=t.getSelectedElement();if(e&&e.is("element","media")){return e}return null}function YI(t,e,n){t.change((o=>{const i=o.createElement("media",{url:e});t.insertContent(i,n);o.setSelection(i,"on")}))}class QI extends iC{refresh(){const t=this.editor.model;const e=t.document.selection;const n=t.schema;const o=BA(e,t);const i=qI(e);let r=o.parent;if(r.isEmpty&&!t.schema.isLimit(r)){r=r.parent}this.value=i?i.getAttribute("url"):null;this.isEnabled=n.checkChild(r,"media")}execute(t){const e=this.editor.model;const n=e.document.selection;const o=qI(n);if(o){e.change((e=>{e.setAttribute("url",t,o)}))}else{const o=BA(n,e);YI(e,t,o)}}}var $I='';const JI="0 0 64 42";class ZI{constructor(t,e){const n=e.providers;const o=e.extraProviders||[];const i=new Set(e.removeProviders);const r=n.concat(o).filter((t=>{const e=t.name;if(!e){Object(ss["c"])("media-embed-no-provider-name",{provider:t});return false}return!i.has(e)}));this.locale=t;this.providerDefinitions=r}hasMedia(t){return!!this._getMedia(t)}getMediaViewElement(t,e,n){return this._getMedia(e).getViewElement(t,n)}_getMedia(t){if(!t){return new XI(this.locale)}t=t.trim();for(const e of this.providerDefinitions){const n=e.html;const o=xs(e.url);for(const e of o){const o=this._getUrlMatches(t,e);if(o){return new XI(this.locale,t,o,n)}}}return null}_getUrlMatches(t,e){let n=t.match(e);if(n){return n}let o=t.replace(/^https?:\/\//,"");n=o.match(e);if(n){return n}o=o.replace(/^www\./,"");n=o.match(e);if(n){return n}return null}}class XI{constructor(t,e,n,o){this.url=this._getValidUrl(e);this._t=t.t;this._match=n;this._previewRenderer=o}getViewElement(t,e){const n={};let o;if(e.renderForEditingView||e.renderMediaPreview&&this.url&&this._previewRenderer){if(this.url){n["data-oembed-url"]=this.url}if(e.renderForEditingView){n.class="ck-media__wrapper"}const i=this._getPreviewHtml(e);o=t.createRawElement("div",n,(function(t){t.innerHTML=i}))}else{if(this.url){n.url=this.url}o=t.createEmptyElement("oembed",n)}t.setCustomProperty("media-content",true,o);return o}_getPreviewHtml(t){if(this._previewRenderer){return this._previewRenderer(this._match)}else{if(this.url&&t.renderForEditingView){return this._getPlaceholderHtml()}return""}}_getPlaceholderHtml(){const t=new ow;const e=new Zb;t.text=this._t("Open media in new tab");e.content=$I;e.viewBox=JI;const n=new yk({tag:"div",attributes:{class:"ck ck-reset_all ck-media__placeholder"},children:[{tag:"div",attributes:{class:"ck-media__placeholder__icon"},children:[e]},{tag:"a",attributes:{class:"ck-media__placeholder__url",target:"_blank",rel:"noopener noreferrer",href:this.url},children:[{tag:"span",attributes:{class:"ck-media__placeholder__url__text"},children:[this.url]},t]}]}).render();return n.outerHTML}_getValidUrl(t){if(!t){return null}if(t.match(/^https?/)){return t}return"https://"+t}}var tN=n(53);var eN={injectType:"singletonStyleTag",attributes:{"data-cke":true}};eN.insert="head";eN.singleton=true;var nN=rk()(tN["a"],eN);var oN=tN["a"].locals||{};class iN extends nC{static get pluginName(){return"MediaEmbedEditing"}constructor(t){super(t);t.config.define("mediaEmbed",{providers:[{name:"dailymotion",url:/^dailymotion\.com\/video\/(\w+)/,html:t=>{const e=t[1];return'
'+`"+"
"}},{name:"spotify",url:[/^open\.spotify\.com\/(artist\/\w+)/,/^open\.spotify\.com\/(album\/\w+)/,/^open\.spotify\.com\/(track\/\w+)/],html:t=>{const e=t[1];return'
'+`"+"
"}},{name:"youtube",url:[/^(?:m\.)?youtube\.com\/watch\?v=([\w-]+)/,/^(?:m\.)?youtube\.com\/v\/([\w-]+)/,/^youtube\.com\/embed\/([\w-]+)/,/^youtu\.be\/([\w-]+)/],html:t=>{const e=t[1];return'
'+`"+"
"}},{name:"vimeo",url:[/^vimeo\.com\/(\d+)/,/^vimeo\.com\/[^/]+\/[^/]+\/video\/(\d+)/,/^vimeo\.com\/album\/[^/]+\/video\/(\d+)/,/^vimeo\.com\/channels\/[^/]+\/(\d+)/,/^vimeo\.com\/groups\/[^/]+\/videos\/(\d+)/,/^vimeo\.com\/ondemand\/[^/]+\/(\d+)/,/^player\.vimeo\.com\/video\/(\d+)/],html:t=>{const e=t[1];return'
'+`"+"
"}},{name:"instagram",url:/^instagram\.com\/p\/(\w+)/},{name:"twitter",url:/^twitter\.com/},{name:"googleMaps",url:/^google\.com\/maps/},{name:"flickr",url:/^flickr\.com/},{name:"facebook",url:/^facebook\.com/}]});this.registry=new ZI(t.locale,t.config.get("mediaEmbed"))}init(){const t=this.editor;const e=t.model.schema;const n=t.t;const o=t.conversion;const i=t.config.get("mediaEmbed.previewsInData");const r=this.registry;t.commands.add("mediaEmbed",new QI(t));e.register("media",{isObject:true,isBlock:true,allowWhere:"$block",allowAttributes:["url"]});o.for("dataDowncast").elementToElement({model:"media",view:(t,{writer:e})=>{const n=t.getAttribute("url");return WI(e,r,n,{renderMediaPreview:n&&i})}});o.for("dataDowncast").add(UI(r,{renderMediaPreview:i}));o.for("editingDowncast").elementToElement({model:"media",view:(t,{writer:e})=>{const o=t.getAttribute("url");const i=WI(e,r,o,{renderForEditingView:true});return HI(i,e,n("media widget"))}});o.for("editingDowncast").add(UI(r,{renderForEditingView:true}));o.for("upcast").elementToElement({view:{name:"oembed",attributes:{url:true}},model:(t,{writer:e})=>{const n=t.getAttribute("url");if(r.hasMedia(n)){return e.createElement("media",{url:n})}}}).elementToElement({view:{name:"div",attributes:{"data-oembed-url":true}},model:(t,{writer:e})=>{const n=t.getAttribute("data-oembed-url");if(r.hasMedia(n)){return e.createElement("media",{url:n})}}})}}const rN=/^(?:http(s)?:\/\/)?[\w.-]+(?:\.[\w.-]+)+[\w\-._~:/?#[\]@!$&'()*+,;=%]+$/;class sN extends nC{static get requires(){return[z_,sx]}static get pluginName(){return"AutoMediaEmbed"}constructor(t){super(t);this._timeoutId=null;this._positionToInsert=null}init(){const t=this.editor;const e=t.model.document;this.listenTo(t.plugins.get(z_),"inputTransformation",(()=>{const t=e.selection.getFirstRange();const n=ep.fromPosition(t.start);n.stickiness="toPrevious";const o=ep.fromPosition(t.end);o.stickiness="toNext";e.once("change:data",(()=>{this._embedMediaBetweenPositions(n,o);n.detach();o.detach()}),{priority:"high"})}));t.commands.get("undo").on("execute",(()=>{if(this._timeoutId){jd.window.clearTimeout(this._timeoutId);this._positionToInsert.detach();this._timeoutId=null;this._positionToInsert=null}}),{priority:"high"})}_embedMediaBetweenPositions(t,e){const n=this.editor;const o=n.plugins.get(iN).registry;const i=new kf(t,e);const r=i.getWalker({ignoreElementEnd:true});let s="";for(const t of r){if(t.item.is("$textProxy")){s+=t.item.data}}s=s.trim();if(!s.match(rN)){i.detach();return}if(!o.hasMedia(s)){i.detach();return}const a=n.commands.get("mediaEmbed");if(!a.isEnabled){i.detach();return}this._positionToInsert=ep.fromPosition(t);this._timeoutId=jd.window.setTimeout((()=>{n.model.change((t=>{this._timeoutId=null;t.remove(i);i.detach();let e;if(this._positionToInsert.root.rootName!=="$graveyard"){e=this._positionToInsert}YI(n.model,s,e);this._positionToInsert.detach();this._positionToInsert=null}))}),100)}}var aN=n(54);var cN={injectType:"singletonStyleTag",attributes:{"data-cke":true}};cN.insert="head";cN.singleton=true;var lN=rk()(aN["a"],cN);var dN=aN["a"].locals||{};class uN extends tb{constructor(t,e){super(e);const n=e.t;this.focusTracker=new tk;this.keystrokes=new Vp;this.set("mediaURLInputValue","");this.urlInputView=this._createUrlInput();this.saveButtonView=this._createButton(n("Save"),PE,"ck-button-save");this.saveButtonView.type="submit";this.saveButtonView.bind("isEnabled").to(this,"mediaURLInputValue",(t=>!!t));this.cancelButtonView=this._createButton(n("Cancel"),zE,"ck-button-cancel","cancel");this._focusables=new Ak;this._focusCycler=new Db({focusables:this._focusables,focusTracker:this.focusTracker,keystrokeHandler:this.keystrokes,actions:{focusPrevious:"shift + tab",focusNext:"tab"}});this._validators=t;this.setTemplate({tag:"form",attributes:{class:["ck","ck-media-form","ck-responsive-form"],tabindex:"-1"},children:[this.urlInputView,this.saveButtonView,this.cancelButtonView]});NE(this)}render(){super.render();BE({view:this});const t=[this.urlInputView,this.saveButtonView,this.cancelButtonView];t.forEach((t=>{this._focusables.add(t);this.focusTracker.add(t.element)}));this.keystrokes.listenTo(this.element);const e=t=>t.stopPropagation();this.keystrokes.set("arrowright",e);this.keystrokes.set("arrowleft",e);this.keystrokes.set("arrowup",e);this.keystrokes.set("arrowdown",e);this.listenTo(this.urlInputView.element,"selectstart",((t,e)=>{e.stopPropagation()}),{priority:"high"})}focus(){this._focusCycler.focusFirst()}get url(){return this.urlInputView.fieldView.element.value.trim()}set url(t){this.urlInputView.fieldView.element.value=t.trim()}isValid(){this.resetFormStatus();for(const t of this._validators){const e=t(this);if(e){this.urlInputView.errorText=e;return false}}return true}resetFormStatus(){this.urlInputView.errorText=null;this.urlInputView.infoText=this._urlInputViewInfoDefault}_createUrlInput(){const t=this.locale.t;const e=new vE(this.locale,SE);const n=e.fieldView;this._urlInputViewInfoDefault=t("Paste the media URL in the input.");this._urlInputViewInfoTip=t("Tip: Paste the URL into the content to embed faster.");e.label=t("Media URL");e.infoText=this._urlInputViewInfoDefault;n.on("input",(()=>{e.infoText=n.element.value?this._urlInputViewInfoTip:this._urlInputViewInfoDefault;this.mediaURLInputValue=n.element.value.trim()}));return e}_createButton(t,e,n,o){const i=new cw(this.locale);i.set({label:t,icon:e,tooltip:true});i.extendTemplate({attributes:{class:n}});if(o){i.delegate("execute").to(this,o)}return i}}var hN='';class fN extends nC{static get requires(){return[iN]}static get pluginName(){return"MediaEmbedUI"}init(){const t=this.editor;const e=t.commands.get("mediaEmbed");const n=t.plugins.get(iN).registry;t.ui.componentFactory.add("mediaEmbed",(o=>{const i=Nw(o);const r=new uN(mN(t.t,n),t.locale);this._setUpDropdown(i,r,e,t);this._setUpForm(i,r,e);return i}))}_setUpDropdown(t,e,n){const o=this.editor;const i=o.t;const r=t.buttonView;t.bind("isEnabled").to(n);t.panelView.children.add(e);r.set({label:i("Insert media"),icon:hN,tooltip:true});r.on("open",(()=>{e.disableCssTransitions();e.url=n.value||"";e.urlInputView.fieldView.select();e.focus();e.enableCssTransitions()}),{priority:"low"});t.on("submit",(()=>{if(e.isValid()){o.execute("mediaEmbed",e.url);s()}}));t.on("change:isOpen",(()=>e.resetFormStatus()));t.on("cancel",(()=>s()));function s(){o.editing.view.focus();t.isOpen=false}}_setUpForm(t,e,n){e.delegate("submit","cancel").to(t);e.urlInputView.bind("value").to(n,"value");e.urlInputView.bind("isReadOnly").to(n,"isEnabled",(t=>!t))}}function mN(t,e){return[e=>{if(!e.url.length){return t("The URL must not be empty.")}},n=>{if(!e.hasMedia(n.url)){return t("This media URL is not supported.")}}]}var gN=n(55);var pN={injectType:"singletonStyleTag",attributes:{"data-cke":true}};pN.insert="head";pN.singleton=true;var kN=rk()(gN["a"],pN);var bN=gN["a"].locals||{};class wN extends nC{static get requires(){return[iN,fN,sN,mE]}static get pluginName(){return"MediaEmbed"}}function CN(t,e){for(const n of t.getChildren()){if(n.is("element","b")&&n.getStyle("font-weight")==="normal"){const o=t.getChildIndex(n);e.remove(n);e.insertChild(o,n.getChildren(),t)}}}function AN(t,e){if(!t.childCount){return}const n=new dS(t.document);const o=vN(t,n);if(!o.length){return}let i=null;let r=1;o.forEach(((t,s)=>{const a=NN(o[s-1],t);const c=a?null:o[s-1];const l=PN(c,t);if(a){i=null;r=1}if(!i||l!==0){const o=yN(t,e);if(!i){i=MN(o,t.element,n)}else if(t.indent>r){const t=i.getChild(i.childCount-1);const e=t.getChild(t.childCount-1);i=MN(o,e,n);r+=1}else if(t.indent[\s]*?)[\r\n]+(\s*<\/span>)/g,"$1$2").replace(/<\/span>/g,"").replace(/ <\//g," <\/o:p>/g," ").replace(/( |\u00A0)<\/o:p>/g,"").replace(/>(\s*[\r\n]\s*)<")}function jN(t){t.querySelectorAll("span[style*=spacerun]").forEach((t=>{const e=t.innerText.length||0;t.innerHTML=Array(e+1).join("  ").substr(0,e)}))}function FN(t){return t.replace(/(\s+)<\/span>/g,((t,e)=>e.length===1?" ":Array(e.length+1).join("  ").substr(0,e.length)))}function VN(t,e){const n=new DOMParser;t=t.replace(//gi,Kt=/<\/?(?:\w+:)\w+[^>]*>/gi,Yt=/[\s\S]*?<\/xml>/gi,Xt=/]*>[\s\S]*?<\/style>/gi,Zt=/\s*mso-[^:]+:[^;"]+;?/gi,Jt=/l(\d+)\s+level(\d+)\s+lfo(\d+)/i,Qt=/mso-list:\s*Ignore/i,te=/\bMso\w+/g,ee=/\bxl\d+/g,se=/\s*tab-stops:[^;"]+;?/gi,ie=/^[\s\u00a0]*[\u2022\u00b7\u00a7\u25cf\u25cb\u25aa\u25a0·o§]\s*/,ne=[/^\s*[0-9]+[.)]\s/,/^\s*[a-z][.)]\s/i,/^\s*[ivxlmcd]+[.)]\s/i],oe=/([\s\u00a0]*)<\/span>/gi,re=/[^<]*<\/span>/gi,le=/mso-outline-level:\s*(\d+)/i,ae=/mso-highlight:\s*([^;"]+)/i,he=/mso-level-number-format:\s*([^;\s]+)/i,ce=/mso-level-start-at:\s*(\d+)/i,de=/mso-level-text:\s*([^;\s]+)/i,ue={decimal:"decimal","alpha-upper":"upper-alpha","alpha-lower":"lower-alpha","roman-upper":"upper-roman","roman-lower":"lower-roman","arabic-leading-zero":"decimal-leading-zero"},pe=/\s*margin:\s*0[a-z]*\s+0[a-z]*\s+0[a-z]*\s*;?/gi,ge=/\s*text-indent:\s*-?[\d.]+[a-z]*\s*;?/gi,me=/\s*line-height:\s*normal\s*;?/gi,fe=/MsoHeading(\d)/i,ve=/^file:\/\/\//i,be=/^_(Toc|Ref|Hlt|Hlk)\d+$/i,ye=/^#_(Toc|Ref|Hlt|Hlk)\d+$/i,we=/page-break-before\s*:\s*always/i,Ce=/mso-break-type\s*:\s*section-break/i,_e=/mso-column-break-before\s*:\s*always/i,ke=/^(?:Word)?Section\d+$/i;function xe(t){const e=t.replace(/[\s\u00a0]+/g," ").trim();if(ie.test(e))return"ul";for(const t of ne)if(t.test(e))return"ol";return"ul"}function $e(t){const e=document.createTreeWalker(t,NodeFilter.SHOW_COMMENT,null),s=[];for(;e.nextNode();)s.push(e.currentNode);for(const t of s)t?.remove();const i=t.querySelectorAll("span");for(const t of i){const e=t.getAttribute("style")||"";Qt.test(e)&&t.remove()}t.firstChild&&3===t.firstChild.nodeType&&(t.firstChild.nodeValue=t.firstChild.nodeValue.replace(/^[\s\u00a0]+/,""))}function Se(t){const e=t.getAttribute("style");if(!e)return;let s=e;const i=ae.exec(s);!i||/background-color/i.test(s)||/background\s*:/i.test(s)||(s+=";background-color:"+i[1].trim()),s=s.replace(Zt,"").replace(se,"").replace(pe,"").replace(ge,"").replace(me,"").trim(),s=s.replace(/^;+|;+$/g,"").replace(/;{2,}/g,";").trim(),s?t.setAttribute("style",s):t.removeAttribute("style")}function Ee(t){const e=t.getAttribute("class");if(!e)return;const s=e.replace(te,"").replace(ee,"").trim();s?t.setAttribute("class",s):t.removeAttribute("class")}function Te(t){let e=t.previousSibling;for(;e;){if(1===e.nodeType)return e;if(3===e.nodeType&&e.nodeValue.trim())return null;e=e.previousSibling}return null}function Me(t,e){for(const s of t){const t=`l${s.listId}:level${s.level}`,i=e.get(t);if(i)s.type=i.type,s.listStyleType=i.listStyleType,s.startAt=i.startAt;else{const t=Be(s.el);s.type=xe(t),s.listStyleType="",s.startAt=1}}const s=t[0].el.parentNode,i=t[t.length-1].el.nextSibling,n=[];let o=null;for(const e of t){const{el:t,level:s,type:i,listStyleType:r,startAt:l}=e;$e(t),Se(t),Ee(t);const a=t.ownerDocument.createElement("li");for(;t.firstChild;)a.appendChild(t.firstChild);if(t.getAttribute("style")&&a.setAttribute("style",t.getAttribute("style")),0===n.length)o=Ne(t.ownerDocument,i,r,l),o.appendChild(a),n.push({listEl:o,level:s});else{const e=n[n.length-1].level;if(s>e){const e=n[n.length-1].listEl.lastElementChild,o=Ne(t.ownerDocument,i,r,l);o.appendChild(a),e?e.appendChild(o):n[n.length-1].listEl.appendChild(o),n.push({listEl:o,level:s})}else if(s1&&n[n.length-1].level>s;)n.pop();n[n.length-1].listEl.appendChild(a)}else n[n.length-1].listEl.appendChild(a)}t.remove()}o&&s.insertBefore(o,i)}function Ne(t,e,s,i){const n=t.createElement(e);return s&&(n.style.listStyleType=s),"ol"===e&&i>1&&n.setAttribute("start",String(i)),n}function Be(t){const e=t.querySelectorAll("span");for(const t of e){const e=t.getAttribute("style")||"";if(Qt.test(e))return t.textContent||""}return t.textContent?.substring(0,10)||""}const Ie={cleanHTML:function(t){if(!t)return"";const e=function(t){const e=new Map,s=t.match(/]*>([\s\S]*?)<\/style>/i);if(!s)return e;const i=s[1],n=/@list\s+l(\d+):level(\d+)\s*\{([^}]*)\}/gi;let o;for(;null!==(o=n.exec(i));){const t=o[1],s=o[2],i=o[3],n=`l${t}:level${s}`,r=he.exec(i),l=ce.exec(i),a=de.exec(i);let h="ol",c="";if(r){const t=r[1].toLowerCase();if("bullet"===t||"image"===t){if(h="ul",a){const t=a[1].replace(/["%\\]/g,"");"·"===t||"·"===t?c="disc":"o"===t?c="circle":"§"!==t&&"§"!==t||(c="square")}}else c=ue[t]||""}e.set(n,{type:h,listStyleType:c,startAt:l?parseInt(l[1],10):1})}return e}(t);let s=t;s=s.replace(Xt,""),s=s.replace(Yt,""),s=s.replace(Gt,""),s=s.replace(Kt,""),s=s.replace(//gi,""),s=s.replace(/<(?:meta|link)[^>]*>/gi,""),s=s.replace(oe," "),s=s.replace(re," "),s=s.replace(/( ){2,}/g," "),s=s.replace(/\u00AD/g,"");const i=(new DOMParser).parseFromString(s,"text/html");!function(t){const e=t.body.querySelectorAll("del, .msoDel");for(const t of e)t.remove();const s=t.body.querySelectorAll("ins, .msoIns");for(let t=s.length-1;t>=0;t--){const e=s[t],i=e.parentNode;if(i){for(;e.firstChild;)i.insertBefore(e.firstChild,e);e.remove()}}const i=t.body.querySelectorAll('.MsoCommentReference, [style*="mso-comment-reference"]');for(const t of i)t.remove();const n=t.body.querySelectorAll(".MsoCommentText");for(const t of n)t.remove();const o=t.body.querySelectorAll('div[style*="mso-element:comment"]');for(const t of o)t.remove();const r=t.body.querySelectorAll('a[name^="_msocom"], a[name^="_msoanchor"]');for(const t of r)t.remove()}(i),function(t,e){const s=[],i=t.body.querySelectorAll("p, h1, h2, h3, h4, h5, h6");for(const t of i){const e=t.getAttribute("style")||"",i=t.getAttribute("class")||"",n=Jt.exec(e);(n||/MsoListParagraph/i.test(i))&&s.push({el:t,listId:n?n[1]:"0",level:n?parseInt(n[2],10):1,lfo:n?n[3]:"1"})}if(0===s.length)return;const n=[];let o=null;for(const t of s){const e=Te(t.el);o&&o.length>0&&e===o[o.length-1].el?o.push(t):(o=[t],n.push(o))}for(const t of n)Me(t,e)}(i,e),function(t){const e=t.body.querySelectorAll("p");for(const s of e){const e=s.getAttribute("style")||"",i=s.getAttribute("class")||"";let n=0;const o=le.exec(e);if(o&&(n=parseInt(o[1],10)),!n){const t=fe.exec(i);t&&(n=parseInt(t[1],10))}if(n>=1&&n<=6){const i=t.createElement("h"+n);for(;s.firstChild;)i.appendChild(s.firstChild);e&&i.setAttribute("style",e),s.replaceWith(i)}}}(i),function(t){const e=t.body.querySelectorAll("table");for(const t of e){Ee(t),t.removeAttribute("cellspacing"),t.removeAttribute("cellpadding");const e=t.querySelectorAll("col");for(const t of e)t.remove();const s=t.querySelectorAll("colgroup");for(const t of s)t.children.length||t.remove()}const s=t.body.querySelectorAll("tr");for(const t of s)t.removeAttribute("height");const i=t.body.querySelectorAll("td, th");for(const t of i){const e=t.getAttribute("valign");if(e){t.removeAttribute("valign");const s=t.getAttribute("style")||"";/vertical-align/i.test(s)||t.setAttribute("style",(s?s+";":"")+"vertical-align:"+e)}const s=t.children;if(1===s.length&&"P"===s[0].tagName){const e=s[0],i=e.getAttribute("class")||"";if(/MsoNormal/i.test(i)||!i){for(;e.firstChild;)t.insertBefore(e.firstChild,e);e.remove()}}}}(i),function(t){const e=t.body.querySelectorAll("a");for(let t=e.length-1;t>=0;t--){const s=e[t],i=s.getAttribute("href")||"",n=s.getAttribute("name")||"";if(ve.test(i)){const t=s.parentNode;if(t){for(;s.firstChild;)t.insertBefore(s.firstChild,s);s.remove()}}else if(be.test(n)){const t=s.parentNode;if(t){if(s.childNodes.length)for(;s.firstChild;)t.insertBefore(s.firstChild,s);s.remove()}}else if(ye.test(i)){const t=s.parentNode;if(t){for(;s.firstChild;)t.insertBefore(s.firstChild,s);s.remove()}}else s.removeAttribute("v:shapes")}}(i),function(t){const e=t.body.querySelectorAll("img");for(let t=e.length-1;t>=0;t--){const s=e[t],i=s.getAttribute("src")||"";ve.test(i)?s.remove():s.removeAttribute("v:shapes")}}(i),function(t){const e=t.body.querySelectorAll("br");for(let t=e.length-1;t>=0;t--){const s=e[t],i=s.getAttribute("style")||"";we.test(i)||Ce.test(i)||_e.test(i)?s.remove():(s.removeAttribute("style"),s.removeAttribute("clear"))}const s=t.body.querySelectorAll('div[class*="Section"]');for(let t=s.length-1;t>=0;t--){const e=s[t],i=e.getAttribute("class")||"";if(ke.test(i.trim())){const t=e.parentNode;if(t){for(;e.firstChild;)t.insertBefore(e.firstChild,e);e.remove()}}}}(i);const n=i.body.querySelectorAll("*");for(const t of n){Se(t),Ee(t),t.getAttribute("lang")&&t.removeAttribute("lang"),t.removeAttribute("v:shapes");const e=t.tagName.toLowerCase();"img"!==e&&"video"!==e&&"iframe"!==e&&"table"!==e&&"td"!==e&&"th"!==e&&(t.removeAttribute("width"),t.removeAttribute("height"))}!function(t){const e=t.querySelectorAll("span");for(let t=e.length-1;t>=0;t--){const s=e[t];if(!s.attributes.length||!s.getAttribute("style")&&!s.getAttribute("class")){const t=s.parentNode;if(t){for(;s.firstChild;)t.insertBefore(s.firstChild,s);t.removeChild(s)}}}}(i.body);const o=i.body.querySelectorAll("p");for(const t of o)t.textContent.trim()||t.querySelector("img, video, iframe, br, table")||t.remove();return i.body.innerHTML}},Le=/id=["']?docs-internal-guid-/i;const Ae={isGoogleDocs:function(t){return Le.test(t)},cleanHTML:function(t){const e=(new DOMParser).parseFromString(t,"text/html"),s=e.body.querySelectorAll('b[id^="docs-internal-guid-"], span[id^="docs-internal-guid-"]');if(0===s.length)return t;for(let t,e=0,i=s.length;e',undo:'',bold:'',underline:'',italic:'',strike:'',subscript:'',superscript:'',remove_color:'',remove_format:'',indent:'',outdent:'',expansion:'',reduction:'',code_block:'',code_view:'',markdown_view:'',preview:'',print:'',template:'',layout:'',ai:'',new_document:'',select_all:'',line_height:'',paragraph_style:'',text_style:'',save:'',blockquote:'',arrow_down:'',align_justify:'',align_left:'',align_right:'',align_center:'',align_top:'',align_middle:'',align_bottom:'',format_float_none:'',format_float_left:'',format_float_right:'',format_float_center:'',font_color:'',background_color:'',list_bulleted:'',list_numbered:'',list_checked:'',table:'',table_header:'',table_properties:'',cell_properties:'',table_column:'',table_row:'',color_checked:'',color_palette:'',border_all:'',border_inside:'',border_horizontal:'',border_vertical:'',border_outside:'',border_left:'',border_top:'',border_right:'',border_bottom:'',border_none:'',horizontal_line:'',show_blocks:'',cancel:'',selection_remove:'',image:'',image_thumbnail:'',video:'',video_thumbnail:'',link:'',link_rel:'',math:'',unlink:'',merge_cell:'',split_cell:'',unmerge_cell:'',caption:'',edit:'',delete:'',revert:'',auto_size:'',resize:'',insert_row_below:'',insert_row_above:'',insert_column_left:'',insert_column_right:'',delete_row:'',delete_column:'',fixed_column_width:'',rotate_left:'',rotate_right:'',mirror_horizontal:'',mirror_vertical:'',checked:'',line_break:'',audio:'',audio_thumbnail:'',image_gallery:'',audio_gallery:'',video_gallery:'',file_gallery:'',file_browser:'',bookmark:'',bookmark_anchor:'',download:'',dir_ltr:'',dir_rtl:'',dragHandle:'',file_upload:'',file_thumbnail:'',file_plus:'',upload_tray:'',folder:'',plus:'',minus:'',selection:'',copy:'',cut:'',PDF:'',format_paint:'',drawing:'',eraser:'',search:'',selection_search:'',embed:'',finder:'',regex:'',match_case:'',whole_word:'',swap_vert:'',arrow_down_small:'',arrow_up_small:'',replaceText:'',relaceTextAll:'',menu_arrow_down:'',menu_arrow_up:'',menu_arrow_right:'',menu_arrow_left:'',side_menu_hamburger:'',side_menu_folder:'',side_menu_folder_item:'',side_menu_item:'',side_menu_folder_plus:'',alert_outline:'',more_media:'',more_gallery:'',more_folder:'',more_list:'',more_file:'',more_view:'',more_page:'',more_text:'',more_paragraph:'',more_plus:'',more_horizontal:'',more_vertical:'',more_flag:'',as_inline:'',as_block:'',page_break:'',page_down:'',page_up:'',collapse_left:'',collapse_right:'',map:'',magic_stick:'',open_in_new:''};var Ge=s("cfbI"),Ke=s.n(Ge);function Ye(t,e,s,i,n){const o=new Map([["menuTray",s],["toolbar_main",t],["toolbar_buttonTray",t.querySelector(".se-btn-tray")],["toolbar_arrow",t.querySelector(".se-arrow")]]);return i&&(o.set("toolbar_sub_main",i),o.set("toolbar_sub_buttonTray",i.querySelector(".se-btn-tray")),o.set("toolbar_sub_arrow",i.querySelector(".se-arrow")),o.set("toolbar_sub_wrapper",i.parentElement.parentElement)),e&&(o.set("toolbar_wrapper",e.querySelector(".sun-editor")),o.set("_stickyDummy",e.querySelector(".se-toolbar-sticky-dummy"))),n&&o.set("statusbar_wrapper",n.querySelector(".sun-editor")),o}function Xe(t,e,s,i,n,o,r,l,a,h,c){const d=new Map([["key",c],["options",t.options],["originElement",t.target],["topArea",e],["container",e.querySelector(".se-container")],["wrapper",e.querySelector(".se-wrapper")],["wysiwygFrame",s],["wysiwyg",s],["codeWrapper",i],["code",n],["codeNumbers",i?.querySelector(".se-code-view-line")],["markdownWrapper",o],["markdown",r],["markdownNumbers",o?.querySelector(".se-markdown-view-line")],["lineBreaker_t",e.querySelector(".se-line-breaker-component-t")],["lineBreaker_b",e.querySelector(".se-line-breaker-component-b")],["blockHandleArea",h],["blockHandle",h?.querySelector(".se-block-handle")||null],["blockHandlePlus",h?.querySelector(".se-block-handle-plus")||null],["blockHandleDrag",h?.querySelector(".se-block-handle-drag")||null],["_stickyDummy",e.querySelector(".se-toolbar-sticky-dummy")],["_toolbarShadow",e.querySelector(".se-toolbar-shadow")],["_minHeight",B(s.style.minHeight||"65",0)],["isCodeView",!1],["isMarkdownView",!1],["isFullScreen",!1],["isReadOnly",!1],["isDisabled",!1],["isChanged",!1],["historyIndex",-1],["savedIndex",-1],["documentTypeInner",a.inner],["documentTypePage",a.page],["documentTypePageMirror",a.pageMirror]]);l&&Ze(l,d);const u=e.querySelector(".se-placeholder");u&&d.set("placeholder",u);const p=t.options.get("placeholder_line");return p&&d.set("placeholder_line",p),d}function Ze(t,e){t?e.set("statusbar",t):e.delete("statusbar");const s=t?t.querySelector(".se-navigation"):null,i=t?t.querySelector(".se-char-counter-wrapper"):null,n=t?t.querySelector(".se-char-counter-wrapper .se-char-counter"):null;s?e.set("navigation",s):e.delete("navigation"),i?e.set("charWrapper",i):e.delete("charWrapper"),n?e.set("charCounter",n):e.delete("charCounter");const o=t?t.querySelector(".se-word-counter-wrapper"):null,r=t?t.querySelector(".se-word-counter-wrapper .se-word-counter"):null;o?e.set("wordWrapper",o):e.delete("wordWrapper"),r?e.set("wordCounter",r):e.delete("wordCounter")}const Je={BUTTON_LIST:[["undo","redo"],"|",["bold","underline","italic","strike","|","subscript","superscript"],"|",["removeFormat"],"|",["outdent","indent"],"|",["fullScreen","showBlocks","codeView"],"|",["preview","print"]],REQUIRED_FORMAT_LINE:"div",REQUIRED_ELEMENT_WHITELIST:"br|div",ELEMENT_WHITELIST:"p|pre|blockquote|h1|h2|h3|h4|h5|h6|ol|ul|li|hr|figure|figcaption|img|iframe|audio|video|source|table|colgroup|col|thead|tbody|tr|th|td|caption|a|b|strong|var|i|em|u|ins|s|span|strike|del|sub|sup|code|svg|path|details|summary",TEXT_STYLE_TAGS:"strong|span|font|b|var|i|em|u|ins|s|strike|del|sub|sup|mark|a|label|code|summary",SCOPE_SELECTION_TAGS:["td","table","li","ol","ul","pre","figcaption","blockquote","dl","dt","dd"],ATTRIBUTE_WHITELIST:"contenteditable|target|href|title|download|rel|src|alt|class|type|colspan|rowspan|width|height|controls|autoplay|loop|muted|poster|preload|playsinline|volume|crossorigin|disableRemotePlayback|controlsList|allowfullscreen|sandbox|loading|allow|referrerpolicy|frameborder|scrolling",FORMAT_LINE:"P|H[1-6]|LI|TH|TD|DETAILS",FORMAT_BR_LINE:"PRE",FORMAT_CLOSURE_BR_LINE:"",FORMAT_BLOCK:"BLOCKQUOTE|OL|UL|FIGCAPTION|TABLE|THEAD|TBODY|TR|CAPTION|DETAILS",FORMAT_CLOSURE_BLOCK:"TH|TD",ALLOWED_EMPTY_NODE_LIST:".se-component, pre, blockquote, hr, li, table, img, iframe, video, audio, canvas, details",SIZE_UNITS:["px","pt","em","rem"],CLASS_NAME:"^__se__|^se-|^katex|^MathJax|^language-",CLASS_MJX:"mjx-container|mjx-math|mjx-mrow|mjx-mi|mjx-mo|mjx-mn|mjx-msup|mjx-mfrac|mjx-munderover",EXTRA_TAG_MAP:{script:!1,style:!1,meta:!1,link:!1,"[a-z]+:[a-z]+":!1},CONTENT_STYLES:"background|background-clip|background-color|border|border-bottom|border-collapse|border-color|border-image|border-left-width|border-radius|border-right-width|border-spacing|border-style|border-top|border-width|box-shadow|box-sizing|caption-side|color|content|direction|display|position|float|font|font-family|font-size|font-style|font-weight|height|min-height|max-height|width|min-width|max-width|left|letter-spacing|line-height|list-style-position|list-style-type|margin|margin-block-end|margin-block-start|margin-bottom|margin-inline-end|margin-inline-start|margin-left|margin-right|margin-top|padding|padding-bottom|padding-inline-start|padding-left|padding-right|padding-top|outline|overflow|page-break-before|page-break-after|page-break-inside|rotate|rotateX|rotateY|table-layout|text-align|text-decoration|text-shadow|text-transform|top|text-indent|text-rendering|vertical-align|visibility|white-space|word-break|word-wrap",TAG_STYLES:{"@text":"font-family|font-size|color|background-color|width|height","@line":"text-align|margin|margin-left|margin-right|line-height","@component":"width|height|min-width",li:"font-family|font-size|color|background-color|font-weight|font-style","table|th|td":"border|border-[a-z]+|color|background-color|text-align|float|font-weight|text-decoration|font-style|vertical-align","table|td":"width",tr:"height",col:"width",caption:"text-align|caption-side","ol|ul":"list-style-type",figure:"display|width|height|padding|padding-bottom",figcaption:"margin|margin-top|margin-bottom|text-align","img|video|iframe":"transform|transform-origin|width|min-width|max-width|height|min-height|max-height|float|margin|margin-top",hr:""},RETAIN_STYLE_MODE:["repeat","always","none"]},Qe={value:"fixed",placeholder:!0,placeholder_line:!0,editableFrameAttributes:!0,width:!0,minWidth:!0,maxWidth:!0,innerWidth:"fixed",height:!0,minHeight:!0,maxHeight:!0,editorStyle:!0,iframe:"fixed",iframe_fullPage:"fixed",iframe_attributes:!0,iframe_cssFileName:!0,statusbar:!0,statusbar_showPathLabel:!0,statusbar_resizeEnable:"fixed",charCounter:!0,charCounter_max:!0,charCounter_label:!0,charCounter_type:!0,wordCounter:!0,wordCounter_label:!0},ts={plugins:"fixed",excludedPlugins:"fixed",buttonList:"fixed",v2Migration:"fixed",strictMode:"fixed",mode:"fixed",blockHandle:"fixed",type:"fixed",theme:!0,lang:"fixed",fontSizeUnits:"fixed",allowedClassName:"fixed",closeModalOutsideClick:"fixed",copyFormatKeepOn:!0,syncTabIndent:!0,tabDisable:!0,autoLinkify:!0,autoStyleify:!0,retainStyleMode:!0,allowedExtraTags:"fixed",events:!0,__textStyleTags:"fixed",textStyleTags:"fixed",convertTextTags:"fixed",__tagStyles:"fixed",tagStyles:"fixed",textDirection:!0,reverseButtons:"fixed",historyStackDelayTime:!0,historyStackSize:"fixed",lineAttrReset:!0,printClass:!0,defaultLine:"fixed",defaultLineBreakFormat:!0,lineBreakClearStyle:!0,scopeSelectionTags:!0,__defaultElementWhitelist:"fixed",elementWhitelist:"fixed",elementBlacklist:"fixed",__defaultAttributeWhitelist:"fixed",attributeWhitelist:"fixed",attributeBlacklist:"fixed",__defaultFormatLine:"fixed",formatLine:"fixed",__defaultFormatBrLine:"fixed",formatBrLine:"fixed",__defaultFormatClosureBrLine:"fixed",formatClosureBrLine:"fixed",__defaultFormatBlock:"fixed",formatBlock:"fixed",__defaultFormatClosureBlock:"fixed",formatClosureBlock:"fixed",allowedEmptyTags:!0,toolbar_width:!0,toolbar_innerWidth:"fixed",toolbar_container:"fixed",toolbar_sticky:!0,toolbar_hide:!0,subToolbar:"fixed",statusbar_container:"fixed",shortcutsHint:!0,shortcutsDisable:"fixed",shortcuts:"fixed",fullScreenOffset:!0,previewTemplate:!0,printTemplate:!0,componentInsertBehavior:!0,defaultUrlProtocol:!0,allUsedStyles:"fixed",toastMessageTime:!0,icons:"fixed",freeCodeViewMode:!0,finder_panel:"fixed",finder_liveSearch:!0,__lineFormatFilter:!0,__pluginRetainFilter:!0,__listCommonStyle:"fixed",externalLibs:"fixed"},es=Oe._d;let ss=0;function is(t,e,s,i,n,o){if(!s||s.length<2)return;const r=e?.querySelector(".se-tooltip-text");for(let l,a,h,c,d,u,p,g,m,f,v,b,y,w,C=0;C'+s+""),n=t.querySelector(".se-shortcut");n?t.replaceChild(i,n):t.appendChild(i)}function os(t,e){return[t,e].reduce(((t,e)=>{for(const s in e)t[s]=(e[s]||"").toLowerCase();return t}),{})}function rs(t,e,s){const i=t.buttonList||Je.BUTTON_LIST,n=new Map;if(e.length>1&&!t.toolbar_container&&!/inline|balloon/i.test(t.mode))throw Error('[SUNEDITOR.create.fail] In multi root, The "mode" option cannot be "classic" without using the "toolbar_container" option.');n.set("v2Migration",!!t.v2Migration),n.set("buttons",new Set(i.toString().split(","))),n.set("strictMode",{tagFilter:!0,formatFilter:!0,classFilter:!0,textStyleTagFilter:!0,attrFilter:!0,styleFilter:!0,..."boolean"==typeof t.strictMode?{}:t.strictMode}),n.set("freeCodeViewMode",!!t.freeCodeViewMode),n.set("finder_panel",!1!==t.finder_panel),n.set("finder_liveSearch",!1!==t.finder_liveSearch),n.set("__lineFormatFilter",t.__lineFormatFilter??!0),n.set("__pluginRetainFilter",t.__pluginRetainFilter??!0);const[o,r]=(t.mode||"classic").split(":");n.set("mode",o),n.set("_toolbar_bottom","bottom"===r&&/^(classic|inline)$/i.test(o)),n.set("blockHandle",t.blockHandle?"object"==typeof t.blockHandle?t.blockHandle:{}:null),n.set("type",t.type?.split(":")[0]||""),n.set("theme",t.theme||""),n.set("_themeClass",t.theme?` se-theme-${t.theme}`:""),n.set("_type_options",t.type?.split(":")[1]||""),n.set("externalLibs",t.externalLibs||{}),n.set("fontSizeUnits",Array.isArray(t.fontSizeUnits)&&t.fontSizeUnits.length>0?t.fontSizeUnits.map((t=>t.toLowerCase())):Je.SIZE_UNITS),n.set("allowedClassName",new RegExp(`${t.allowedClassName&&"string"==typeof t.allowedClassName?t.allowedClassName+"|":""}${Je.CLASS_NAME}`)),n.set("closeModalOutsideClick",!!t.closeModalOutsideClick),n.set("copyFormatKeepOn",!!t.copyFormatKeepOn),n.set("syncTabIndent",t.syncTabIndent??!0),n.set("autoLinkify",t.autoLinkify??!!s.link),n.set("autoStyleify",Array.isArray(t.autoStyleify)?t.autoStyleify:["bold","underline","italic","strike"]);let l=t.retainStyleMode||"repeat";"string"!=typeof l||Je.RETAIN_STYLE_MODE.includes(l)||(console.error(`Invalid retainStyleMode: ${l}. Valid options are ${Je.RETAIN_STYLE_MODE.join(", ")}. Using default 'repeat'.`),l="repeat"),n.set("retainStyleMode",l);const a={...Je.EXTRA_TAG_MAP,...t.allowedExtraTags,"-":!0},h=Object.keys(a),c=h.filter((t=>a[t])).join("|"),d=h.filter((t=>!a[t])).join("|");n.set("_allowedExtraTag",c),n.set("_disallowedExtraTag",d),n.set("events",t.events||{}),n.set("textStyleTags",("string"==typeof t.__textStyleTags?t.__textStyleTags:Je.TEXT_STYLE_TAGS)+(t.textStyleTags?"|"+t.textStyleTags:""));const u=os({bold:"strong",underline:"u",italic:"em",strike:"del",subscript:"sub",superscript:"sup"},t.convertTextTags||{});n.set("convertTextTags",u),n.set("_textStyleTags",Object.values(u).concat(["span","li"])),n.set("tagStyles",[{...Je.TAG_STYLES,...t.__tagStyles||{}},t.tagStyles||{}].reduce(((t,e)=>{for(const s in e)t[s]=e[s];return t}),{})),n.set("_defaultStyleTagMap",{strong:u.bold,b:u.bold,u:u.underline,ins:u.underline,em:u.italic,i:u.italic,del:u.strike,strike:u.strike,s:u.strike,sub:u.subscript,sup:u.superscript}),n.set("_styleCommandMap",os(ze.swapKeyValue(u),{strong:"bold",b:"bold",u:"underline",ins:"underline",em:"italic",i:"italic",del:"strike",strike:"strike",s:"strike",sub:"subscript",sup:"superscript"})),n.set("_defaultTagCommand",{bold:u.bold,underline:u.underline,italic:u.italic,strike:u.strike,subscript:u.sub,superscript:u.sup}),n.set("textDirection",t.textDirection??"ltr"),n.set("_rtl","rtl"===n.get("textDirection")),n.set("reverseCommands",["indent-outdent"].concat(t.reverseButtons||[])),n.set("_reverseCommandArray",("-"+n.get("reverseCommands").join("-")).split("-")),De.isEven(n.get("_reverseCommandArray").length)&&console.warn('[SUNEDITOR.create.warning] The "reverseCommands" option is invalid, Shortcuts key may not work properly.'),n.set("historyStackDelayTime","number"==typeof t.historyStackDelayTime?t.historyStackDelayTime:400),n.set("historyStackSize","number"==typeof t.historyStackSize&&t.historyStackSize>0?t.historyStackSize:100),n.set("_editableClass","sun-editor-editable"+n.get("_themeClass")+(n.get("_rtl")?" se-rtl":"")+("document"===n.get("type")?" se-type-document-editable-a4":"")),n.set("lineAttrReset",["id"].concat(t.lineAttrReset&&"string"==typeof t.lineAttrReset?t.lineAttrReset.toLowerCase().split("|"):[])),n.set("printClass","string"==typeof t.printClass?t.printClass+" "+n.get("_editableClass"):null),n.set("defaultLine","string"==typeof t.defaultLine&&t.defaultLine.length>0?t.defaultLine:"p"),n.set("defaultLineBreakFormat",t.defaultLineBreakFormat||"line"),n.set("lineBreakClearStyle",!!t.lineBreakClearStyle),n.set("scopeSelectionTags",t.scopeSelectionTags||Je.SCOPE_SELECTION_TAGS);const p=("string"==typeof t.elementWhitelist?t.elementWhitelist:"").toLowerCase(),g=n.get("externalLibs").mathjax?Je.CLASS_MJX+"|":"";n.set("elementWhitelist",p+(p?"|":"")+g+n.get("_allowedExtraTag"));const m=(f=("string"==typeof t.elementBlacklist?t.elementBlacklist:"").toLowerCase(),v=(v=n.get("defaultLine")).toLowerCase(),f.split("|").filter((function(t){return t!==v||(console.warn(`[SUNEDITOR.constructor.createBlacklist.warn] defaultLine("<${v}>") cannot be included in the blacklist and will be removed.`),!1)})).join("|"));var f,v;if(n.set("elementBlacklist",m+(m?"|":"")+n.get("_disallowedExtraTag")),n.set("attributeWhitelist",t.attributeWhitelist&&"object"==typeof t.attributeWhitelist?t.attributeWhitelist:null),n.set("attributeBlacklist",t.attributeBlacklist&&"object"==typeof t.attributeBlacklist?t.attributeBlacklist:null),n.set("formatClosureBrLine",ds(t.formatClosureBrLine,(t.__defaultFormatClosureBrLine="string"==typeof t.__defaultFormatClosureBrLine?t.__defaultFormatClosureBrLine:Je.FORMAT_CLOSURE_BR_LINE).toLowerCase(),n.get("elementBlacklist"))),n.set("formatBrLine",ds((t.formatBrLine||"")+"|"+n.get("formatClosureBrLine").str,(t.__defaultFormatBrLine="string"==typeof t.__defaultFormatBrLine?t.__defaultFormatBrLine:Je.FORMAT_BR_LINE).toLowerCase(),n.get("elementBlacklist"))),n.set("formatLine",ds(Je.REQUIRED_FORMAT_LINE+"|"+(t.formatLine||"")+"|"+n.get("formatBrLine").str,(t.__defaultFormatLine="string"==typeof t.__defaultFormatLine?t.__defaultFormatLine:Je.FORMAT_LINE).toLowerCase(),n.get("elementBlacklist"))),!n.get("formatLine").reg.test(n.get("defaultLine")))throw Error(`[SUNEDITOR.create.fail] The "defaultLine(${n.get("defaultLine")})" option must be included in the "formatLine(${n.get("formatLine").str})" option.`);n.set("formatClosureBlock",ds(t.formatClosureBlock,(t.__defaultFormatClosureBlock="string"==typeof t.__defaultFormatClosureBlock?t.__defaultFormatClosureBlock:Je.FORMAT_CLOSURE_BLOCK).toLowerCase(),n.get("elementBlacklist"))),n.set("formatBlock",ds((t.formatBlock||"")+"|"+n.get("formatClosureBlock").str,(t.__defaultFormatBlock="string"==typeof t.__defaultFormatBlock?t.__defaultFormatBlock:Je.FORMAT_BLOCK).toLowerCase(),n.get("elementBlacklist"))),n.set("allowedEmptyTags",Je.ALLOWED_EMPTY_NODE_LIST+(t.allowedEmptyTags?", "+t.allowedEmptyTags:"")),n.set("__defaultElementWhitelist",Je.REQUIRED_ELEMENT_WHITELIST+"|"+("string"==typeof t.__defaultElementWhitelist?t.__defaultElementWhitelist:Je.ELEMENT_WHITELIST).toLowerCase()),n.set("__defaultAttributeWhitelist",("string"==typeof t.__defaultAttributeWhitelist?t.__defaultAttributeWhitelist:Je.ATTRIBUTE_WHITELIST).toLowerCase()),n.set("_editorElementWhitelist","*"===n.get("elementWhitelist")?"*":function(t){const e=t.get("elementBlacklist").split("|"),s=(t.get("__defaultElementWhitelist")+"|"+t.get("elementWhitelist")+"|"+t.get("formatLine").str+"|"+t.get("formatBrLine").str+"|"+t.get("formatClosureBlock").str+"|"+t.get("formatClosureBrLine").str).replace(/(^\||\|$)/g,"").split("|").filter(((t,s,i)=>t&&i.indexOf(t)===s&&!e.includes(t)));return s.join("|")}(n)),n.set("toolbar_width",t.toolbar_width?De.is(t.toolbar_width)?t.toolbar_width+"px":t.toolbar_width:"auto"),n.set("toolbar_innerWidth",t.toolbar_innerWidth?De.is(t.toolbar_innerWidth)?t.toolbar_innerWidth+"px":t.toolbar_innerWidth:""),n.set("toolbar_container",t.toolbar_container&&!/inline/i.test(n.get("mode"))?"string"==typeof t.toolbar_container?es.querySelector(t.toolbar_container):t.toolbar_container:null);const b=t.toolbar_sticky;/balloon/i.test(n.get("mode"))?(n.set("_toolbar_sticky",-1),n.set("_toolbar_sticky_offset",0),n.set("_toolbar_sticky_fixed",!1)):null!==b&&"object"==typeof b?(n.set("_toolbar_sticky",De.get(b.top,0)),n.set("_toolbar_sticky_offset",De.get(b.offset,0)),n.set("_toolbar_sticky_fixed","fixed"===b.position)):(n.set("_toolbar_sticky",void 0===b?0:De.is(b)?b:-1),n.set("_toolbar_sticky_offset",0),n.set("_toolbar_sticky_fixed",!1)),n.set("toolbar_hide",!!t.toolbar_hide);let y=null;const w=t.subToolbar;w?.buttonList?.length>0&&(/balloon/.test(n.get("mode"))?console.warn('[SUNEDITOR.create.subToolbar.fail] When the "mode" option is "balloon-*", the "subToolbar" option is omitted.'):(n.set("_subMode",w.mode||"balloon"),n.set("toolbar_sub_width",w.width?De.is(w.width)?w.width+"px":w.width:"auto"),y=w.buttonList,n.set("buttons_sub",new Set(y.toString().split(",")))));const C=new Map;for(let s=0,i=e.length;s{for(const s in e)t[s]=e[s];return t}),{});n.set("shortcuts",_),n.set("fullScreenOffset",void 0===t.fullScreenOffset?0:De.is(t.fullScreenOffset)?De.get(t.fullScreenOffset,0):0),n.set("previewTemplate","string"==typeof t.previewTemplate?t.previewTemplate:null),n.set("printTemplate","string"==typeof t.printTemplate?t.printTemplate:null),n.set("componentInsertBehavior",["auto","select","line","none"].includes(t.componentInsertBehavior)?t.componentInsertBehavior:"auto"),n.set("defaultUrlProtocol","string"==typeof t.defaultUrlProtocol?t.defaultUrlProtocol:null);const k=n.get("externalLibs").codeMirror;k&&(n.set("codeMirror",k),k.src?n.set("codeMirrorEditor",!0):(console.warn("[SUNEDITOR.options.externalLibs.codeMirror.fail] The codeMirror option is set incorrectly. See: https://github.com/ARA-developer/suneditor/blob/develop/guide/external-libraries.md"),n.set("codeMirror",null))),n.set("__listCommonStyle",t.__listCommonStyle||["fontSize","color","fontFamily","fontWeight","fontStyle"]);const x=t.icons&&"object"==typeof t.icons?[je,t.icons].reduce(((t,e)=>{for(const s in e)t[s]=e[s];return t}),{}):je;n.set("icons",x);const $=new Set(Je.CONTENT_STYLES.split("|")),S=n.get("__listCommonStyle");for(const t of Object.values(n.get("tagStyles"))){const e=t.split("|");for(let t=0,s=e.length;t0){const e=i.querySelector(".se-char-max")||Pe.utils.createElement("SPAN",{class:"se-char-max"});e.textContent=" / "+t.get("charCounter_max"),i.appendChild(e)}e.appendChild(i)}}return{statusbar:e,navigation:s,charWrapper:i,charCounter:n,wordWrapper:o,wordCounter:r}}function as(t,e){const s=new Map;s.set("_origin",t);const i=e.statusbar_container,n=void 0===t.value?e.value:t.value,o=void 0===t.placeholder?e.placeholder:t.placeholder,r=void 0===t.placeholder_line?e.placeholder_line:t.placeholder_line,l=void 0===t.editableFrameAttributes?e.editableFrameAttributes:t.editableFrameAttributes,a=void 0===t.width?e.width:t.width,h=void 0===t.minWidth?e.minWidth:t.minWidth,c=void 0===t.maxWidth?e.maxWidth:t.maxWidth,d=void 0===t.innerWidth?e.innerWidth:t.innerWidth,u=void 0===t.height?e.height:t.height,p=void 0===t.minHeight?e.minHeight:t.minHeight,g=void 0===t.maxHeight?e.maxHeight:t.maxHeight,m=void 0===t.editorStyle?e.editorStyle:t.editorStyle,f=void 0===t.iframe?e.iframe:t.iframe,v=void 0===t.iframe_fullPage?e.iframe_fullPage:t.iframe_fullPage,b=void 0===t.iframe_attributes?e.iframe_attributes:t.iframe_attributes,y=void 0===t.iframe_cssFileName?e.iframe_cssFileName:t.iframe_cssFileName,w=i||void 0===t.statusbar?e.statusbar:t.statusbar,C=i||void 0===t.statusbar_showPathLabel?e.statusbar_showPathLabel:t.statusbar_showPathLabel,_=!i&&(void 0===t.statusbar_resizeEnable?e.statusbar_resizeEnable:t.statusbar_resizeEnable),k=i||void 0===t.charCounter?e.charCounter:t.charCounter,x=i||void 0===t.charCounter_max?e.charCounter_max:t.charCounter_max,$=i||void 0===t.charCounter_label?e.charCounter_label:t.charCounter_label,S=i||void 0===t.charCounter_type?e.charCounter_type:t.charCounter_type,E=i||void 0===t.wordCounter?e.wordCounter:t.wordCounter,T=i||void 0===t.wordCounter_label?e.wordCounter_label:t.wordCounter_label;s.set("value",n),s.set("placeholder",o),s.set("placeholder_line",r),s.set("editableFrameAttributes",{spellcheck:"false",...l}),s.set("width",a?String(De.is(a)?a+"px":a):"100%"),s.set("minWidth",h?String(De.is(h)?h+"px":h):""),s.set("maxWidth",c?String(De.is(c)?c+"px":c):""),s.set("innerWidth",d?String(De.is(d)?d+"px":d):""),s.set("height",u?String(De.is(u)?u+"px":u):"auto"),s.set("minHeight",p?String(De.is(p)?p+"px":p):""),s.set("maxHeight",g?String(De.is(g)?g+"px":g):""),s.set("editorStyle",m),s.set("_defaultStyles",ze._setDefaultOptionStyle(s,"string"==typeof m?m:"")),s.set("iframe",!(!v&&!f)),s.set("iframe_fullPage",!!v),s.set("iframe_attributes",b||{}),s.set("iframe_cssFileName",f?("string"==typeof y?[y]:y)||["suneditor"]:null);const M=void 0===w||!!w;return s.set("statusbar",M),s.set("statusbar_showPathLabel",!!M&&("boolean"!=typeof C||C)),s.set("statusbar_resizeEnable",!!M&&(void 0===_||!!_)),s.set("charCounter",x>0||"boolean"==typeof k&&k),s.set("charCounter_max",De.is(x)&&x>-1?1*x:null),s.set("charCounter_label","string"==typeof $?$.trim():null),s.set("charCounter_type","string"==typeof S?S:"char"),s.set("wordCounter","boolean"==typeof E&&E),s.set("wordCounter_label","string"==typeof T?T.trim():null),s}function hs(t,e,s,i,n){const o=i.get("_defaultStyles");s.style.cssText=o.top;const r=Pe.utils.createElement(i.get("iframe")?"IFRAME":"DIV",{class:"se-wrapper-inner se-wrapper-wysiwyg"+("document"===e.get("type")?" se-type-document-iframe-a4":""),"data-root-key":t});if(i.get("iframe")){const t=r,e=i.get("iframe_attributes");let s=e.sandbox;if(s){const t=["allow-same-origin","allow-scripts"],e=s.split(/\s+/),i=t.filter((t=>!e.includes(t)));i.length>0&&(s=e.concat(i).join(" "))}else s="allow-same-origin allow-scripts";t.setAttribute("sandbox",s),t.setAttribute("frameBorder","0");for(const s in e)"sandbox"!==s&&t.setAttribute(s,e[s]);t.allowFullscreen=!0,t.setAttribute("scrolling","auto"===i.get("height")?"no":"auto"),t.style.cssText=o.frame}else r.setAttribute("contenteditable","true"),e.get("_rtl")&&(r.dir="rtl"),r.className+=" "+e.get("_editableClass"),r.style.cssText=o.frame+o.editor;const l=Pe.utils.createElement("TEXTAREA",{id:n+"-code-viewer-"+(t||"default"),class:"se-wrapper-inner se-code-viewer",style:o.frame,autocomplete:"off"}),a=Pe.utils.createElement("TEXTAREA",{id:n+"-markdown-viewer-"+(t||"default"),class:"se-wrapper-inner se-markdown-viewer",style:o.frame,autocomplete:"off"}),h=Pe.utils.createElement("SPAN",{class:"se-placeholder"});return i.get("placeholder")&&(h.textContent=i.get("placeholder")),{bottomBar:ls(i,null),wysiwygFrame:r,codeView:l,markdownView:a,placeholder:h}}function cs(t,e,s){let i=null,n=!1;if(t.get("codeMirrorEditor")){const o=t.get("codeMirror"),r=[{mode:"htmlmixed",htmlMode:!0,lineNumbers:!0,lineWrapping:!1},o.options||{}].reduce(((t,e)=>{for(const s in e)t[s]=e[s];return t}),{});"auto"===e.get("height")&&(r.viewportMargin=1/0,r.height="auto");const l=s.style.cssText,a=o.src.fromTextArea(s,r);e.set("codeMirrorEditor",a),i=a.display.wrapper,i.style.cssText=l,n=!0}return t.set("hasCodeMirror",n),i?(Pe.utils.removeItem(s),i.className+=" se-code-viewer-mirror",i):s}function ds(t,e,s){const i=s.split("|"),n=(e+"|"+("string"==typeof t?t.toLowerCase():"")).replace(/^\||\|$/g,"").split("|").filter((t=>t&&!i.includes(t))).join("|");return{reg:new RegExp(`^(${n})$`,"i"),str:n}}function us(t,e,s,i,n){const o=e?.[t];if(o){const e="function"==typeof o?o:o.constructor;return{className:o.className||e.className||"",title:n[o.title]||o.title||n[e.title]||e.title||t,command:t,type:o.type||e.type||"",icon:i[o.icon]||o.icon||i[e.icon]||e.icon||""}}const r=ps(s.get("_rtl"),i,n)[t];return r?{className:r[0],title:r[1],command:r[2],type:r[3],icon:r[4]}:null}function ps(t,e,s){return{bold:["",s.bold,"bold","",e.bold],underline:["",s.underline,"underline","",e.underline],italic:["",s.italic,"italic","",e.italic],strike:["",s.strike,"strike","",e.strike],subscript:["",s.subscript,"subscript","",e.subscript],superscript:["",s.superscript,"superscript","",e.superscript],removeFormat:["",s.removeFormat,"removeFormat","",e.remove_format],copyFormat:["",s.copyFormat,"copyFormat","",e.format_paint],indent:["se-icon-flip-rtl",s.indent,"indent","",t?e.outdent:e.indent],outdent:["se-icon-flip-rtl",s.outdent,"outdent","",t?e.indent:e.outdent],fullScreen:["se-code-view-enabled se-component-enabled",s.fullScreen,"fullScreen","",e.expansion],showBlocks:["",s.showBlocks,"showBlocks","",e.show_blocks],codeView:["se-code-view-enabled se-component-enabled",s.codeView,"codeView","",e.code_view],markdownView:["se-code-view-enabled se-component-enabled",s.markdownView,"markdownView","",e.markdown_view],undo:["se-component-enabled",s.undo,"undo","",e.undo],redo:["se-component-enabled",s.redo,"redo","",e.redo],preview:["se-component-enabled",s.preview,"preview","",e.preview],print:["se-component-enabled",s.print,"print","",e.print],copy:["",s.copy,"copy","",e.copy],dir:["",s[t?"dir_ltr":"dir_rtl"],"dir","",e[t?"dir_ltr":"dir_rtl"]],dir_ltr:["",s.dir_ltr,"dir_ltr","",e.dir_ltr],dir_rtl:["",s.dir_rtl,"dir_rtl","",e.dir_rtl],finder:["se-component-enabled",s.find,"finder","",e.finder],save:["se-component-enabled",s.save,"save","",e.save],newDocument:["se-component-enabled",s.newDocument,"newDocument","",e.new_document],selectAll:["se-component-enabled",s.selectAll,"selectAll_full","",e.select_all],pageBreak:["se-component-enabled",s.pageBreak,"pageBreak","",e.page_break],pageUp:["se-component-enabled",s.pageUp,"pageUp","",e.page_up],pageDown:["se-component-enabled",s.pageDown,"pageDown","",e.page_down],pageNavigator:["se-component-enabled","","pageNavigator","input",""]}}function gs(){const t=Pe.utils.createElement("UL",{class:"se-menu-list"});return{div:Pe.utils.createElement("DIV",{class:"se-btn-module se-btn-module-border"},t),ul:t}}function ms(t,e,s,i,n,o,r){n||="";const l=Pe.utils.createElement("LI"),a=e||"",h=/^INPUT|FIELD$/i.test(i),c="se-toolbar-separator-vertical"===t?Pe.utils.createElement("DIV",{class:t,tabindex:"-1"},null):Pe.utils.createElement(h?"DIV":"BUTTON",{class:"se-toolbar-btn se-btn se-tooltip"+(t?" "+t:""),"data-command":s,"data-type":i,"aria-label":a.replace(//,""),tabindex:"-1"});return h||c.setAttribute("type","button"),/^default\./i.test(n)&&(n=r[n.replace(/^default\./i,"")]),/^text\./i.test(n)&&(n=n.replace(/^text\./i,""),c.className+=" se-btn-more-text"),o&&(c.disabled=!0),/^FIELD$/i.test(i)&&Pe.utils.addClass(l,"se-toolbar-hidden-btn"),a&&(n+=Pe.utils.createTooltipInner(a)),n&&(c.innerHTML=n),l.appendChild(c),{li:l,button:c}}function fs(t,e,s,i){if(!t)return;const n=!1===e.inner;if(1===e.inner?.nodeType?t.appendChild(e.inner):t.innerHTML=n?"":(e.inner||s[e.icon]||e.icon||'!')+''+(i[e.title]||e.title)+"",t.setAttribute("aria-label",e.title),e.type&&t.setAttribute("data-type",e.type),e.className&&(t.className+=" "+e.className),e.afterItem&&(Pe.utils.addClass(e.afterItem,"se-toolbar-btn"),t.parentElement.appendChild(e.afterItem),Pe.utils.addClass(t,"se-side-btn-a"),Pe.utils.addClass(e.afterItem,"se-side-btn-after")),e.beforeItem&&(Pe.utils.addClass(e.beforeItem,"se-toolbar-btn"),t.parentElement.insertBefore(e.beforeItem,t),e.afterItem?(Pe.utils.addClass(t,"se-side-btn"),Pe.utils.removeClass(t,"se-side-btn-a")):Pe.utils.addClass(t,"se-side-btn-b"),Pe.utils.addClass(e.beforeItem,"se-side-btn-before")),e.replaceButton&&(t.parentElement.appendChild(e.replaceButton),t.style.display="none"),!e.replaceButton&&/^INPUT$/i.test(t.getAttribute("data-type"))){const e=t.querySelector("input");e&&(Pe.utils.addClass(e,"se-toolbar-btn"),e.setAttribute("data-command",t.getAttribute("data-command")),e.setAttribute("data-type",t.getAttribute("data-type")),t.hasAttribute("disabled")&&(e.disabled=!0))}}function vs(t,e,s,i,n,o){t=JSON.parse(JSON.stringify(t));const r=ps(s.get("_rtl"),i,n),l={},a=[],h=[];let c=null,d=null,u=null,p=null,g=null;const m=Pe.utils.createElement("DIV",{class:"se-toolbar-more-layer"}),f=Pe.utils.createElement("DIV",{class:"se-btn-tray"}),v=Pe.utils.createElement("DIV",{class:"se-toolbar-separator-vertical"});t:for(let s,b,y,w,C,_=0;_",m.appendChild(b),b=b.firstElementChild.firstElementChild)}f.appendChild(p.div)}else{if("|"===w){const t=v.cloneNode(!1);f.appendChild(t);continue}if(/^\/$/.test(w)){const t=Pe.utils.createElement("DIV",{class:"se-btn-module-enter"});f.appendChild(t)}}switch(f.children.length){case 0:f.style.display="none";break;case 1:Pe.utils.removeClass(f.firstElementChild,"se-btn-module-border")}var b,y;m.children.length>0&&f.appendChild(m),a.length>0&&a.unshift(t),b=f,y=s.get("toolbar_innerWidth"),b&&y&&("auto"!==y&&(b.style.maxWidth=y),b.style.width="max-content",b.style.marginLeft="auto",b.style.marginRight="auto");const w=Pe.utils.createElement("DIV",{class:"se-toolbar sun-editor-common"+(s.get("shortcutsHint")?"":" se-shortcut-hide")},f);return s.get("toolbar_hide")&&(w.style.display="none"),{element:w,pluginCallButtons:l,responsiveButtons:a,buttonTray:f,updateButtons:h}}const bs=function(t,e){"object"!=typeof e&&(e={});const s={};if(e.plugins){const t=e.excludedPlugins||[],i=e.plugins,n=Array.isArray(i)?i.map((t=>[null,t])):Object.keys(i).map((t=>[t,i[t]]));for(let e,i,o=0,r=n.length;o'),a="suneditor-"+ ++ss,h=Pe.utils.createElement("DIV",{class:"sun-editor sun-editor-carrier-wrapper sun-editor-common"+n.get("_themeClass")+(n.get("_rtl")?" se-rtl":"")}),c=Pe.utils.createElement("DIV",{class:"se-menu-tray",popover:"manual"});h.appendChild(c);const d=Pe.utils.createElement("INPUT",{type:"text",id:a+"-focus-temp",class:"__se__focus__temp__",autocomplete:"off","aria-hidden":"true",style:"position: fixed !important; top: -10000px !important; left: -10000px !important; display: block !important; width: 0 !important; height: 0 !important; margin: 0 !important; padding: 0 !important;"});d.tabIndex=-1,h.appendChild(d);const u=Pe.utils.createElement("DIV",{class:"se-modal se-modal-area sun-editor-common",popover:"manual"}),p=Pe.utils.createElement("DIV",{class:"se-modal-back"}),g=Pe.utils.createElement("DIV",{class:"se-modal-inner"});u.appendChild(p),u.appendChild(g),h.appendChild(u);const m=Pe.utils.createElement("DIV",{class:"se-alert se-modal-area sun-editor-common",style:"display: none;",popover:"manual"}),f=Pe.utils.createElement("DIV",{class:"se-modal-back"}),v=Pe.utils.createElement("DIV",{class:"se-modal-inner"});m.appendChild(f),m.appendChild(v),h.appendChild(m),h.appendChild(Pe.utils.createElement("DIV",{class:"se-back-wrapper",popover:"manual"}));const b=l.cloneNode(!0);b.setAttribute("popover","manual"),h.appendChild(b);const y=Pe.utils.createElement("DIV",{class:"se-drag-cursor",popover:"manual"});h.appendChild(y),es.body.appendChild(h);let w=null,C=null;const _=vs(i.buttons,s,n,o,r,!1),k=_.element;k.style.visibility="hidden",/inline/i.test(n.get("mode"))?(k.className+=" se-toolbar-inline",k.style.width=n.get("toolbar_width")):/balloon/i.test(n.get("mode"))&&(k.className+=" se-toolbar-balloon",k.style.width=n.get("toolbar_width"),k.appendChild(Pe.utils.createElement("DIV",{class:"se-arrow"}))),n.get("_toolbar_bottom")&&(k.className+=" se-toolbar-bottom"),i.subButtons&&(C=vs(i.subButtons,s,n,o,r,!1),w=C.element,w.style.visibility="hidden",w.className+=" se-toolbar-balloon se-toolbar-sub",w.style.width=n.get("toolbar_sub_width"),w.appendChild(Pe.utils.createElement("DIV",{class:"se-arrow"})));const x=t[0].key||null,$=[],S=new Map,E=i.statusbarContainer;let T=null;for(let e=0,s=t.length;e')),n.get("_type_options").includes("page")&&(N.page=Pe.utils.createElement("DIV",{class:"se-document-page"},null),N.pageMirror=Pe.utils.createElement("DIV",{class:"sun-editor-editable se-document-page-mirror-a4",style:"position: absolute; width: 21cm; columns: 21cm; border: 0; overflow: hidden; height: auto; top: -10000px; left: -10000px;"},null));let B=null;if(u){B=Pe.utils.createElement("DIV",{class:"se-block-handle-area"});const t=Pe.utils.createElement("DIV",{class:"se-block-handle",popover:"manual"}),e=Pe.utils.createElement("DIV",{class:"se-block-handle-btn se-block-handle-plus"},o.plus),s=Pe.utils.createElement("DIV",{class:"se-block-handle-btn se-block-handle-drag"},o.dragHandle);t.appendChild(e),t.appendChild(s),B.appendChild(t)}c.appendChild(d),$.push(_),S.set(_,Xe({target:s.target,key:s.key,options:h},c,v,k,y,x,M,T||f,N,B,_))}const M=n.get("toolbar_container");if(M){const t=Pe.utils.createElement("DIV",{class:"sun-editor"+n.get("_themeClass")+(n.get("_rtl")?" se-rtl":"")}),e=Pe.utils.createElement("DIV",{class:"se-container"});e.appendChild(k),w&&e.appendChild(w),t.appendChild(e),M.appendChild(t),M.appendChild(Pe.utils.createElement("DIV",{class:"se-toolbar-sticky-dummy"}))}else{const t=S.get(x).get("container");if(n.get("_toolbar_bottom")){const e=t.querySelector(".se-statusbar");t.insertBefore(k,e),w&&t.insertBefore(w,k)}else t.insertBefore(k,t.firstElementChild),w&&t.insertBefore(w,t.firstElementChild)}return{context:Ye(k,M,c,w,E),carrierWrapper:h,options:n,plugins:s,icons:o,lang:r,value:i.v,rootId:x,rootKeys:$,frameRoots:S,pluginCallButtons:_.pluginCallButtons,responsiveButtons:_.responsiveButtons,pluginCallButtons_sub:C?C.pluginCallButtons:[],responsiveButtons_sub:C?C.responsiveButtons:[]}},{_w:ys}=Oe,ws=Math.floor(96/72*841.89105);const Cs=class{#t;#e;#s;#i;#n;#o;#r;#l;#a;#h;#c;#d;#u;#p;#g;#m;#f=-1;#v=-1;#b=null;#y=null;#w=0;#C=0;#_=-1;#k=0;#x=[];#$=null;#S=0;#E=0;#T=new Map;#M=null;constructor(t,e){const s=t.$;if(this.#t=s.store,this.#e=s.context,this.#s=this.#t.get("isScrollable"),this.#i=s.offset,this.#n=s.selection,this.#o=s.toolbar,this.useHeader=s.options.get("_type_options").includes("header"),this.usePage=s.options.get("_type_options").includes("page"),this.#r=e,this.#l=e.get("wysiwyg"),this.#a=e.get("wysiwygFrame"),this.#h=e.get("documentTypeInner"),this.#p=e.get("documentTypePageMirror"),this.#p){const t=ys.getComputedStyle(this.#p);this.#g=De.get(t.paddingTop),this.#m=De.get(t.paddingBottom)}if(this.useHeader){const t=this._getHeaders(),e=this.#c=this.#h.querySelector(".se-document-lines-inner");let i="";for(let e,s=0,n=t.length;s${e.textContent}`;e.innerHTML=i,this.#b=e.querySelectorAll("div"),s.eventManager.addEvent(e,"click",this.#N.bind(this,this.#l))}this.usePage&&(this.#d=e.get("documentTypePage"),this.#u=s.plugins.pageNavigator)}reHeader(){if(!this.useHeader)return;const t=this._getHeaders(),e=this.#c,s=this.#b;for(let i,n,o,r=0,l=t.length;rt.length)for(let i=t.length;i{await Pe.utils.waitForMediaLoad(this.#p,1500);const e=this.#l.scrollHeight>this.#p.scrollHeight?this.#l.scrollHeight-this.#p.scrollHeight:0,s=this.#p.scrollHeight+e,i=this.#l.querySelectorAll(".se-page-break");if(!t&&this.#_===s&&this.#k===i.length)return;this.#_=s,this.#k=i.length;let n=0;const o=[];if(i.length>0){n=i[0].offsetHeight;for(let t=0;tt.end))],d=[...o.map((t=>t.top)),s];for(let t=0;t=e);)if(!l.some((t=>Math.abs(t.top-s)<3))){const t=this._calcPageBreakTop(s,a,h,l);if(null===t)break;l.push({number:0,top:t})}}if(0===l.length)return this.#$=null,this.#w=1,void this._displayCurrentPage();l.sort(((t,e)=>t.top-e.top)),this.#d.innerHTML="",this.#x=[];const u=this.#a.offsetWidth+1;for(let t,e=0;e${e+1}`);this.#d.appendChild(s),this.#x.push(s)}this.#$=this.#d.querySelectorAll(".se-document-page-line"),this.#w=this.#x.length,this.#B(),this._displayCurrentPage()}),400))}_getDisplayPage(){return this.#s(this.#r)?this.#r.get("wysiwyg"):ys}_calcPageBreakTop(t,e,s,i){const{ci:n}=this._getElementAtPosition(t,s,i),o=s[n],r=e[n];if(!o||!r)return null;const l=t+(r.offsetTop-o.offsetTop)+(r.offsetHeight-o.offsetHeight)/2;return Math.round(l)}_initializeCache(t){this.#T.clear();for(let e=0,s=t.length;e0){const e=this.#T.get(i);e&&t=r&&t<=a){let i=o;if(s&&Pe.utils.hasClass(e[i],"se-page-break")){i=i+1800?Pe.utils.removeClass(this.#h,"se-document-responsible"):Pe.utils.addClass(this.#h,"se-document-responsible"),this.#f=t,this.#v=e;const i=this.#$;for(let e=0,s=i?.length;ee?"none":""}}scrollWindow(){this.#s(this.#r)||this._displayCurrentPage()}getCurrentPageNumber(){if(this.#w<=1)return 1;let t=0;if(this.#s(this.#r))t=this.#v/2;else{const e=this._getGlobalTop();if(t=ys.scrollY-e+ws/2,t<=0)return 1}const e=this.#x;for(let s=0,i=e.length;s=t)return this.#C=s;return this.#C=this.#w}pageUp(){const t=this.#C-1<=1?1:this.#C-1;this._movePage(t,!1)}pageDown(){const t=this.#C+1>this.#x.length?this.#x.length:this.#C+1;this._movePage(t,!1)}pageGo(t){t<1?t=1:t>this.#x.length&&(t=this.#x.length),this._movePage(t,!0)}on(t){if(!this.useHeader)return;if(this._is(t)||(t=this._findLinesHeader(t)),!t)return;const e=this._findItem(t);e&&(Pe.utils.removeClass(this.#b,"active"),Pe.utils.addClass(e,"active"))}onChangeText(t){if(!this.useHeader)return;if(!this._is(t))return;const e=this._findItem(t);e&&(e.textContent=t.textContent)}_displayCurrentPage(){const t=this.getCurrentPageNumber();this.#u?.display(t,this.#w)}_getWWScrollTop(){const t=this._getDisplayPage();return t.scrollTop||t.scrollY||0}_movePage(t,e){const s=this._getGlobalTop(),i=this.#s(this.#r),n=ze.nodeListToArray(this.#l.children),o=this.#d.offsetTop+De.get(this.#x[t-1].style.top)+(i?this._getWWScrollTop():0);for(let r,l=0,a=n.length;l=o){e||this.#n.setRange(r,0,r,0);const n=0===l&&i?0:r.offsetTop-this.#d.offsetTop-r.offsetHeight+s;this._applyPageScroll(n,(()=>{this.#o.isSticky&&!this.#t.mode.isBottom&&this._getDisplayPage().scrollTo({top:n-this.#e.get("toolbar_main").offsetHeight,behavior:"smooth"})})),this.#C=t;break}}_applyPageScroll(t,e){const s=this._getDisplayPage();s.scrollTo({top:t,behavior:"smooth"});const i=()=>{Math.abs((s.scrollY??s.scrollTop)-t)<1?e():ys.requestAnimationFrame(i)};ys.requestAnimationFrame(i)}_getGlobalTop(){return this.#s(this.#r)?0:this.#i.getGlobal(this.#a).top}_findItem(t){const e=this.#y,s=Array.prototype.indexOf.call(e,t);return-1!==s&&this.#b[s]?this.#b[s]:null}_findLinesHeader(t){for(;t&&t!==this.#l;){if(this._is(t))return t;t=t.previousElementSibling||t.parentElement}return null}_is(t){return/^h[1-6]$/i.test(t?.nodeName)}_getHeaders(){return this.#y=this.#l.querySelectorAll("h1, h2, h3, h4, h5, h6")}#N(t,e){e.preventDefault();try{this.#t.set("_preventBlur",!0);const t=Pe.query.getEventTarget(e);if(Pe.utils.hasClass(t,"se-doc-item")){const e=Array.prototype.indexOf.call(this.#b,t);if(-1===e)return;const s=this.#y[e];s&&this.#n.scrollTo(s)}}finally{this.#t.set("_preventBlur",!1)}}_destroy(){this.#M&&(ys.clearTimeout(this.#M),this.#M=null),this.#T&&(this.#T.clear(),this.#T=null),this.#r=null,this.#l=null,this.#a=null,this.#h=null,this.#c=null,this.#d=null,this.#x=null,this.#$=null,this.#b=null,this.#y=null,this.#u=null,this.#p=null}};const _s=class{#I;#L=new Map;constructor(t){const e=t.options,s=e.get("mode"),i=e.get("_subMode");this._editorInitFinished=!1,this.mode={isClassic:/classic/i.test(s),isInline:/inline/i.test(s),isBalloon:/balloon/i.test(s),isBalloonAlways:/balloon-always/i.test(s),isSubBalloon:/balloon/i.test(i),isSubBalloonAlways:/balloon-always/i.test(i),isBottom:!!e.get("_toolbar_bottom")},this.#I={rootKey:t.rootId,hasFocus:!1,tabSize:4,indentSize:25,codeIndentSize:2,currentNodes:[],currentNodesMap:[],initViewportHeight:0,currentViewportHeight:0,controlActive:!1,_lastSelectionNode:null,isScrollable:t=>{const e=t.get("options"),s=e.get("height"),i=e.get("maxHeight");return"auto"!==s||!!i&&t.get("wysiwyg").offsetHeight>=De.get(i)},_range:null,_mousedown:!1,_preventBlur:!1,_preventFocus:!1,_canUseBeforeInput:!0}}get(t){return this.#I[t]}set(t,e){const s=this.#I[t];this.#I[t]=e,this.#A(t,e,s)}subscribe(t,e){return this.#L.has(t)||this.#L.set(t,new Set),this.#L.get(t).add(e),()=>this.#L.get(t).delete(e)}#A(t,e,s){const i=this.#L.get(t);if(i)for(const n of i)try{n(e,s)}catch(e){console.error(`[Store] Subscriber error for "${t}":`,e)}}_reset(){}_destroy(){this.#L.clear(),this.#I=null}},{_w:ks,_d:xs}=Oe;class $s{#O;#R;#z;constructor(t){this.#O=t.frameRoots,this.#R=this.#P(t.context),this.#z=this.#D({value:new Map}),this.rootKeys=t.rootKeys,this.carrierWrapper=t.carrierWrapper,this.icons=t.icons,this.lang=t.lang,this.shadowRoot=null}get frameRoots(){return this.#O}get context(){return this.#R}get frameContext(){return this.#z}init(){this.applyToRoots((t=>{this.#F(t)}))}reset(t){this.#z.reset(t)}applyToRoots(t){this.#O.forEach(t)}#F(t){const e=t.get("options");if(t.set("wwComputedStyle",ks.getComputedStyle(t.get("wysiwyg"))),!e.get("iframe")&&"function"==typeof ShadowRoot){let e=t.get("wysiwygFrame");for(;e;){if(e.shadowRoot){this.shadowRoot=e.shadowRoot;break}if(e instanceof ShadowRoot){this.shadowRoot=e;break}e=e.parentNode}}e.get("iframe")?(t.set("_ww",t.get("wysiwygFrame").contentWindow),t.set("_wd",t.get("wysiwygFrame").contentDocument),t.set("wysiwyg",t.get("_wd").body),e.get("_defaultStyles").editor&&(t.get("wysiwyg").style.cssText=e.get("_defaultStyles").editor),"auto"===e.get("height")&&t.set("_iframeAuto",t.get("_wd").body)):(t.set("_ww",ks),t.set("_wd",xs));const s=e.get("editableFrameAttributes");for(const e in s)t.get("wysiwyg").setAttribute(e,s[e])}#P(t){const e=t;return{get:t=>e.get(t),set:(t,s)=>e.set(t,s),has:t=>e.has(t),delete:t=>e.delete(t),getAll:()=>Object.fromEntries(e.entries()),get size(){return e.size},clear(){e.clear()}}}#D(t){let e=t.value;return{get:t=>e.get(t),set:(t,s)=>e.set(t,s),has:t=>e.has(t),delete:t=>e.delete(t),getAll:()=>Object.fromEntries(e.entries()),reset(s){e=t.value=s},get size(){return e.size},clear(){e.clear()}}}_destroy(){this.applyToRoots((t=>{const e=t.get("documentType");e&&e._destroy(),Pe.utils.removeItem(t.get("topArea")),t.get("options").clear(),t.clear()})),this.#R.clear(),this.#z.clear(),this.#O.clear(),Pe.utils.removeItem(this.carrierWrapper),this.rootKeys=null,this.carrierWrapper=null,this.icons=null,this.lang=null,this.shadowRoot=null}}class Ss{#H;#q;#W;#U;constructor(t,e,s){this.#H=t,this.#q=s,this.#W=this.#V({value:e.options}),this.#U=this.#j({value:new Map})}get options(){return this.#W}get frameOptions(){return this.#U}reset(t){const{$:e}=this.#H,s=e.frameRoots,i=e.context,n=e.eventManager,o=e.format,r=e.html,l=e.char,a=e.viewer,h=e.plugins,c=e.history,d=e.ui,u=this.#H._eventOrchestrator;a.codeView(!1),a.showBlocks(!1);const p=new Map,g=[],m=new Map,f={};for(const e in t)void 0!==Qe[e]&&(f[e]=t[e],delete t[e]);for(const e of s.keys())t[e||""]={...f,...t[e||""]};const v=Object.keys(t);if(this.#G(v,h,""),0===v.length)return;1===s.size&&v.unshift(null);const b=[this.#q,t].reduce(((t,e)=>{for(const i in e)s.has(i||null)?this.#K(i,e,s,p,m,g):t[i]=e[i];return t}),{}),y=this.#W,w=rs(b,g,h),C=w.o,_=w.frameMap;for(let t,e=0,i=v.length;ee.get(t),set:(t,s)=>e.set(t,s),has:t=>e.has(t),getAll:()=>Object.fromEntries(e.entries()),setMany(t){t.forEach(((t,s)=>e.set(s,t)))},reset(s){e=t.value=s},size:()=>e.size,clear(){e.clear()},entries:()=>e.entries(),keys:()=>e.keys(),values:()=>e.values(),forEach(t){e.forEach(t)}}}#j(t){let e=t.value;return{get:t=>e.get(t),set:(t,s)=>e.set(t,s),has:t=>e.has(t),getAll:()=>Object.fromEntries(e.entries()),setMany(t){t.forEach(((t,s)=>e.set(s,t)))},reset(s){e=t.value=s},size:()=>e.size,clear(){e.clear()},entries:()=>e.entries(),keys:()=>e.keys(),values:()=>e.values(),forEach(t){e.forEach(t)}}}_destroy(){this.#q=null,this.#W.clear(),this.#U.clear()}}const Es=class{#X;constructor(t){this.#X=t}isNode(t){return t&&"number"==typeof t.nodeType||t instanceof this.#Z().Node}isElement(t){return t&&1===t.nodeType||t instanceof this.#Z().Element}isRange(t){return t&&"Range"===t.constructor?.name||t instanceof this.#Z().Range}isSelection(t){return t&&"Selection"===t.constructor?.name||t instanceof this.#Z().Selection}#Z(){return this.#X.get("_ww")}},{_w:Ts,_d:Ms,NO_EVENT:Ns}=Oe;const Bs=class{#J;#X;#Q;#tt=null;#et=null;#st=[];#it=[];constructor(t,e,s){this.#J=s,this.#X=t.frameContext,this.#Q=e.frameOptions,this.events=e.options.get("events")||{},this.triggerEvent=async(t,e)=>{if(Pe.check.isNonEditable(e?.frameContext?.get("wysiwyg")))return!1;const s=this.events[t];if("function"==typeof s)try{return await s({$:this.#J,...e})}catch(e){return console.error(`[SUNEDITOR.triggerEvent.${t}]`,e),!1}return Ns}}_bindOrchestrator(t){this.#tt=t}applyTagEffect(t){return this.#tt?.applyTagEffect(t)}addEvent(t,e,s,i){if(!t)return null;if((t===Ts||t===Ms||"number"!=typeof t.length||t.nodeType||!Array.isArray(t)&&t.length<1)&&(t=[t]),0===t.length)return null;const n=t.length;for(let o=0;oi.type===t&&i.listener===e&&i.useCapture===s))??-1;return i>-1&&this.#it.splice(i,1),null}_injectActiveEvent(t){Pe.utils.addClass(t,"__se__active"),this.#et=this.addGlobalEvent("mouseup",(()=>{Pe.utils.removeClass(t,"__se__active"),this.#et=this.removeGlobalEvent(this.#et)}))}_init(){for(let t,e=0,s=this.#st.length;e0&&(c+=v.offsetTop),v.scrollHeight>=v.clientHeight&&(d=/^html$/i.test(v.nodeName)?d||v.clientHeight:v.clientHeight+(m?-m.clientTop:0),p=m||p||v,m=v),v.scrollLeft>0&&(h+=v.offsetLeft),v.scrollWidth>=v.clientWidth&&(u=/^html$/i.test(v.nodeName)?u||v.clientWidth:v.clientWidth+(f?-f.clientLeft:0),g=f||g||v,f=v),v=v.parentElement;if(!i&&!s&&/^iframe$/i.test(this.#X.get("wysiwygFrame").nodeName))for(v=this.#X.get("wrapper"),p=g=e;v;)n+=v.scrollTop,r+=v.scrollLeft,l+=v.scrollHeight,a+=v.scrollWidth,v.scrollTop>0&&(c+=v.offsetTop),v.scrollHeight>=v.clientHeight&&(d=/^html$/i.test(v.nodeName)?d||v.clientHeight:v.clientHeight+(m?-m.clientTop:0),m=v),v.scrollLeft>0&&(h+=v.offsetLeft),v.scrollWidth>=v.clientWidth&&(u=/^html$/i.test(v.nodeName)?u||v.clientWidth:v.clientWidth+(f?-f.clientLeft:0),f=v),v=v.parentElement;for(v=this.#nt?.host,v&&(p=g=e);v;)n+=v.scrollTop,r+=v.scrollLeft,l+=v.scrollHeight,a+=v.scrollWidth,v.scrollTop>0&&(c+=v.offsetTop),v.scrollHeight>=v.clientHeight&&(d=/^html$/i.test(v.nodeName)?d||v.clientHeight:v.clientHeight+(m?-m.clientTop:0),m=v),v.scrollLeft>0&&(h+=v.offsetLeft),v.scrollWidth>=v.clientWidth&&(u=/^html$/i.test(v.nodeName)?u||v.clientWidth:v.clientWidth+(f?-f.clientLeft:0),f=v),v=v.parentElement;const b=e.contains(p),y=e.contains(g);p=b?e:p,g=y?e:g;const w=p?p.getBoundingClientRect().top+(!p.parentElement||/^html$/i.test(p.parentElement.nodeName)?o.scrollY:0):0,C=g?g.getBoundingClientRect().left+(!g.parentElement||/^html$/i.test(g.parentElement.nodeName)?o.scrollX:0):0;d=b?e.clientHeight:d,u=y?e.clientWidth:u;const _=pt(this.#X.get("_wd"));return{top:n,left:r,ts:w,ls:C,width:a,height:l,x:h,y:c,ohOffsetEl:i?window:p,owOffsetEl:i?window:g,oh:i?_.h:d,ow:i?_.w:u,heightEditorRefer:b,widthEditorRefer:y}}getWWScroll(){const t=this.#X.get("eventWysiwyg"),e=t.scrollTop||t.scrollY||0,s=t.scrollHeight||t.document?.documentElement.scrollHeight||0;return{top:e,left:t.scrollLeft||t.scrollX||0,width:t.scrollWidth||t.document?.documentElement.scrollWidth||0,height:s,bottom:e+s}}setRelPosition(t,e,s,i,{preferUp:n}={}){const l=/^fixed$/i.test(o.getComputedStyle(i).position),a=this.getGlobal(s);if(l)t.style.position="fixed",t.style.top=n?a.fixedTop-t.offsetHeight+"px":`${a.fixedTop+a.height}px`;else{t.style.position="";const l=i.contains(t)?this.getGlobal(e).top:0,h=t.offsetHeight,c=o.scrollY,d=a.top;if(n){const e=l-c+d;if(e=h?t.style.top=`${d+s.offsetHeight}px`:i>e?(t.style.height=`${i}px`,t.style.top=`${d+s.offsetHeight}px`):(t.style.height=`${e}px`,t.style.top=-1*(e-d+3)+"px")}else t.style.top=d-h+"px"}else{const e=pt(r).h-(l-c+d+s.offsetHeight);if(ee?(t.style.height=`${o}px`,i=-1*(o-d+3)):(t.style.height=`${e}px`,i=d+s.offsetHeight),t.style.top=`${i}px`}else t.style.top=`${d+s.offsetHeight}px`}}const h=t.offsetWidth,c=a.left,d=this.getGlobal(i).left;if(this.#rt.get("_rtl")){const e=s.getBoundingClientRect(),n=o.innerWidth;let r=n-e.right;if(h>0){const t=i.getBoundingClientRect();n-r-h0||!this.#J.toolbar.isSticky&&N?0:T+(this.#J.toolbar.isSticky?this.#rt.get("_toolbar_sticky"):0),I=this.#X.get("statusbar")?.offsetHeight||0,{rmt:L,rmb:A,bMargin:O,rt:R}=this.#at(x,$,B,m,v,p,d);if(c&&(A-I+k<=0||L+R+k-(this.#J.toolbar.isSticky&&g?B:0)<=0)||L+k<0)return;const z=this.#X.get("topArea").getBoundingClientRect(),P=this.#t.mode.isBottom?z.bottom>=o.innerHeight-T:z.top<=T,D=this.#J.toolbar.isSticky&&"none"!==this.#e.get("toolbar_main").style.display&&(!N||P);let F=i.top,H=0,q="";"bottom"===n?(q="up",F+=v.bottom+C+E,H=A-(_+C),H-w<0&&(q="down",F-=k+_+2*C,H=L-(_+C),H-w<0&&(q="",F-=H-w-Math.max(1,H+_+C)))):(q="down",F+=v.top-_-C+E,H=(D&&!this.#t.mode.isBottom?v.top-B:L)-_-C,H-w<0&&(q="up",F+=k+_+2*C,H=(A>0?O:A)-(_+C)-I,H-w<0&&(q="",F+=H-2))),this.#ht(y,q),t.style.top=`${F}px`;const W=(1===t.nodeType?De.get(o.getComputedStyle(t).borderRadius):0)||0,U=b.width,V=t.offsetWidth,j=y?y.offsetWidth:0,G=v.left,K=m.w-v.right;if(c&&(G+U<=0||K+U<=0))return;y&&(y.style.left="",y.style.right="");let Y=i.left||(i.right?a?i.right-t.offsetWidth:t.offsetWidth-i.right:0),X=0,Z=0,J=0;return a?(Y+=v.left+o.scrollX-(G<0?G:0),X=U+G,XJ?J:Z),y&&Z>0&&(y.style.left=Z+"px")):(Y+=v.right-V+o.scrollX+(K<0?K:0),X=U+K,XV-J?V-J:Z),y&&Z>0&&(y.style.right=Z+"px")),t.style.left=`${Y}px`,l.__offset={left:t.offsetLeft+f.left,top:t.offsetTop+f.top,addOffset:i},{position:"up"===q?"bottom":"top"}}setRangePosition(t,e,{position:s,addTop:i}={}){t.style.top="-10000px",t.style.visibility="hidden",t.style.display="block";let n="top"===s;e||=this.#J.selection.getRange();const l=this.#J.selection.getRects(e,n?"start":"end");if(n="start"===l.position,l.rects.noText){let t=e.startContainer;1===t.nodeType&&(t=t.childNodes[e.startOffset]||t);const s=t.parentNode;if(s){const e=rt(E);s.insertBefore(e,t);const i=r.createRange();i.setStart(e,1),i.setEnd(e,1);const n=i.getClientRects()[0];n&&(l.rects=n,l.scrollLeft=o.scrollX,l.scrollTop=o.scrollY),s.removeChild(e)}}const a=this.#X.get("isFullScreen"),h=this.#X.get("topArea"),c=this.#ot.contains(t),d=l.rects,u=a?0:l.scrollLeft,p=a?0:l.scrollTop,g=c?pt(r).w:h.offsetWidth,m=this.getGlobal(h),f=c?0:m.left,v=t.offsetWidth,b=t.offsetHeight;this.#ct(n,d,t,f,g,u,p,i),this.getGlobal(t).top-m.top<0&&(n=!n,this.#ct(n,d,t,f,g,u,p,i)),v===t.offsetWidth&&b===t.offsetHeight||this.#ct(n,d,t,f,g,u,p,i);const y=!this.#ot.contains(t),w=pt(r),C=d.height,_=d.top,k=w.h-d.bottom,x=this.#J.toolbar.isSticky||!this.#t.mode.isBalloon&&!this.#t.mode.isInline?this.#e.get("toolbar_main").offsetHeight:0,{rmt:$,rmb:S,rt:T}=this.#at(_,k,x,w,d,y,!1);if(!(S+C<=0||$+T+C<=0))return t.style.visibility="",!0}#ct(t,e,s,i,n,o,l,a=0){const h=s.querySelector(".se-arrow "),c=Math.round(h.offsetWidth/2),d=s.offsetWidth,u=e.noText&&!t?0:s.offsetHeight,p=(t?e.left:e.right)-i-d/2+o,g=p+d-n;let m=(t?e.top-u-c:e.bottom+c)-(e.noText?0:a)+l;const f=p<0?1:g<0?p:p-g-1-1;let v=!1;const b=m+(t?this.getGlobal(this.#X.get("topArea")).top:s.offsetHeight-this.#X.get("wysiwyg").offsetHeight);!t&&b>0&&this.#dt()b&&(t=!1,v=!0),v&&(m=(t?e.top-u-c:e.bottom+c)-(e.noText?0:a)+l),s.style.left=Math.floor(f)+"px",s.style.top=Math.floor(m)+"px",t?(ut(h,"se-arrow-up"),dt(h,"se-arrow-down")):(ut(h,"se-arrow-down"),dt(h,"se-arrow-up"));const y=Math.floor(d/2+(p-f));h.style.left=(y+c>s.offsetWidth?s.offsetWidth-c:ye?r=this.#J.toolbar.isSticky?s:e+s:this.#rt.get("toolbar_container")&&!this.#J.toolbar.isSticky?s=0:r=e+s,h=n.top-(a.top-t),c=a.bottom-(n.bottom-r)+s,c=c>0?c:c-s):(s>t?i=this.#J.toolbar.isSticky?s:t+s:this.#rt.get("toolbar_container")&&!this.#J.toolbar.isSticky?s=0:i=t+s,h=n.top-(a.top-i)+s,c=a.bottom-(n.bottom-e),h=h>0?h:h-s)}else{const t=m.fixedTop>0?m.fixedTop:0,e=o.innerHeight-(m.fixedTop+m.height);d=l||!this.#J.toolbar.isSticky&&this.#J.toolbar.isBalloonMode?0:s,f?(h=u-(l?0:t),c=p-(e>0?e:0)-d):(h=u-(l?0:t)-d,c=p-(e>0?e:0))}return{rmt:h,rmb:c,rt:d,tMargin:u,bMargin:p}}#ht(t,e){"up"===e?(t&&(t.style.visibility=""),dt(t,"se-arrow-up"),ut(t,"se-arrow-down")):"down"===e?(t&&(t.style.visibility=""),dt(t,"se-arrow-down"),ut(t,"se-arrow-up")):t&&(t.style.visibility="hidden")}#lt(){const t=pt(r);return{top:o.scrollY,left:o.scrollX,width:t.w,height:t.h,bottom:o.scrollY+t.h,rects:{left:0,top:0,right:o.innerWidth,bottom:this.#t.get("currentViewportHeight")||o.innerHeight,noText:!0}}}},{_w:Ls}=Oe;const As=class{#H;#J;#t;#nt;#ut;#e;#X;#rt;#Q;#pt=0;#gt=!1;constructor(t){this.#H=t,this.#J=t.$,this.#t=t.store,this.#nt=this.#J.contextProvider.shadowRoot,this.#ut=this.#J.instanceCheck,this.#e=this.#J.context,this.#X=this.#J.frameContext,this.#rt=this.#J.options,this.#Q=this.#J.frameOptions,this.range=null,this.selectionNode=null,this.__iframeFocus=!1}get(){let t=null;return t="function"==typeof this.#nt?.getSelection?this.#nt.getSelection():this.#X.get("_ww").getSelection(),t?(this.#t.get("_range")||this.#X.get("wysiwyg").contains(t.focusNode)||(t.removeAllRanges(),t.addRange(this.#mt())),t):null}isRange(t){return this.#ut.isRange(t)}getRange(){const t=this.#t.get("_range")||this.#mt(),e=this.get();if(t.collapsed===e.isCollapsed||!this.#X.get("wysiwyg").contains(e.focusNode)){if(this.#J.component.is(t.startContainer)){const e=this.#J.component.get(t.startContainer),s=e?.container;return s?this.setRange(s,0,s,1):t}return t}if(e.rangeCount>0){const t=e.getRangeAt(0);return this.#t.set("_range",t),t}{const t=e.anchorNode,s=e.focusNode,i=e.anchorOffset,n=e.focusOffset,o=Pe.query.compareElements(t,s),r=o.ancestor&&(0===o.result?i<=n:o.result>1);return this.setRange(r?t:s,r?i:n,r?s:t,r?n:i)}}setRange(t,e,s,i){let n,o,r,l;if(this.isRange(t)){const e=t;n=e.startContainer,o=e.startOffset,r=e.endContainer,l=e.endOffset}else n=t,o=e,r=s,l=i;if(!n||!r)return;(Pe.check.isBreak(n)||3===n.nodeType)&&o>n.textContent.length&&(o=n.textContent.length),(Pe.check.isBreak(r)||3===r.nodeType)&&l>r.textContent.length&&(l=r.textContent.length),this.#J.format.isLine(n)&&(n=n.childNodes[o>0?n.childNodes.length-1:0]||n,o=o>0?1!==n.nodeType||Pe.check.isBreak(n)?n.textContent?n.textContent.length:0:1:0),this.#J.format.isLine(r)&&(r=r.childNodes[l>0?r.childNodes.length-1:0]||r,l=l>0?1!==r.nodeType||Pe.check.isBreak(r)?r.textContent?r.textContent.length:0:1:0);const a=this.#X.get("_wd").createRange();try{o=Math.min(o,n.textContent?.length||0),l=l>0&&0===(r.textContent?.length||0)&&1===r.nodeType?1:Math.min(Math.max(l,0),r.textContent?.length||0),a.setStart(n,o),a.setEnd(r,l),this.#t.set("hasFocus",!0)}catch(t){return console.warn("[SUNEDITOR.selection.focus.warn]",t.message),void this.#J.focusManager.nativeFocus()}const h=this.get();return h.removeAllRanges&&h.removeAllRanges(),h.addRange(a),this.#t.set("_range",a),this.#ft(a,this.get()),this.#Q.get("iframe")&&this.__focus(),a}removeRange(){this.#t.set("_range",null),this.#t.set("_lastSelectionNode",null),this.selectionNode=null,this.#t.get("hasFocus")&&this.get().removeAllRanges(),this.#H._eventOrchestrator.selectionState.reset()}getNearRange(t){const e=t.nextSibling,s=t.previousSibling;return e?{container:e,offset:0}:s?{container:s,offset:1}:null}getRangeAndAddLine(t,e){if(this.#vt(t)){const s=e?.parentElement||this.#X.get("wysiwyg"),i=Pe.utils.createElement(this.#rt.get("defaultLine"),null,"
");s.insertBefore(i,e&&e!==s?e.previousElementSibling?e.nextElementSibling:e:s.firstElementChild),this.setRange(i.firstElementChild,0,i.firstElementChild,1),t=this.#t.get("_range")}return t}getNode(){if(this.#X.get("wysiwyg").contains(this.selectionNode)||this.init(),!this.selectionNode){const t=Pe.query.getEdgeChild(this.#X.get("wysiwyg").firstChild,(t=>0===t.childNodes.length||3===t.nodeType),!1);if(t)return this.selectionNode=t,t;this.init()}return this.selectionNode}getRects(t,e){const s=!!Pe.check.isElement(t)&&"absolute"===Ls.getComputedStyle(t).position;t=!t||Pe.check.isText(t)?this.getRange():t;let i="start"===e,n=Ls.scrollX,o=Ls.scrollY,r=t.getClientRects();if(r=r[i?0:r.length-1],!r){const t=this.getNode();if(this.#J.format.isLine(t)){const t=Pe.utils.createTextNode(Re.zeroWidthSpace);this.#J.html.insertNode(t,{afterNode:null,skipCharCount:!0}),this.setRange(t,1,t,1),this.init(),r=this.getRange().getClientRects(),r=r[i?0:r.length-1]}if(!r){const e=this.#J.offset.get(t);r={left:e.left,top:e.top,right:e.left+t.offsetWidth,bottom:e.top+t.offsetHeight,noText:!0},n=0,o=0}i=!0}const l=/^iframe$/i.test(this.#X.get("wysiwygFrame").nodeName)?this.#X.get("wysiwygFrame").getClientRects()[0]:null;return!s&&l&&(r={left:r.left+l.left,top:r.top+l.top,right:r.right+l.right-l.width,bottom:r.bottom+l.bottom-l.height}),{rects:r,position:i?"start":"end",scrollLeft:n,scrollTop:o}}getDragEventLocationRange(t){const e=this.#X.get("_wd");let s,i,n,o,r;return e.caretPositionFromPoint?(s=e.caretPositionFromPoint(t.clientX,t.clientY),i=s.offsetNode,n=s.offset,o=s.offsetNode,r=s.offset):e.caretRangeFromPoint&&(s=e.caretRangeFromPoint(t.clientX,t.clientY),i=s.startContainer,n=s.startOffset,o=s.endContainer,r=s.endOffset),{sc:i,so:n,ec:o,eo:r}}scrollTo(t,e){const s=e?.noFocus;if(this.#ut.isSelection(t))t=t.getRangeAt(0);else if(this.#ut.isNode(t))if(s){const e=this.#X.get("_wd").createRange();e.selectNodeContents(t),t=e}else t=this.setRange(t,1,t,1);else void 0===t?.startContainer&&console.warn('[SUNEDITOR.html.scrollTo.warn] "selectionRange" must be Selection or Range or Node object.',t);const i=Pe.query.getParentElement(t?.startContainer,(t=>1===t.nodeType));if(!i)return;delete(e={behavior:"smooth",block:"nearest",inline:"nearest",...e}).noFocus;const n=this.#X.get("_ww"),o=this.#X.get("wysiwygFrame"),r=this.#Q.get("iframe"),l=!this.#t.get("isScrollable")(this.#X),a=this.#t.get("currentViewportHeight"),h=l?Ls.scrollY:r?n.scrollY:o.scrollTop,c=this.#t.mode.isBottom,d=this.#e.get("toolbar_main").offsetHeight,u=this.#J.toolbar.isSticky?d:0,p=this.#J.toolbar.isSticky?u+this.#rt.get("_toolbar_sticky"):u,g=this.#X.get("statusbar")?.offsetHeight||0;if(this.#gt){const s=this.#J.format.isBrLine(i)?t?.getBoundingClientRect?.():null;if(s?.height>0?this.#bt(s,e.behavior):i?.scrollIntoView(e),"auto"===e?.behavior)if(p&&!c){const e=t?.getBoundingClientRect?.();e?.height>0&&e.top>=0&&e.top0?v.height:i.offsetHeight)||0,y=e?.behavior,w=c?0:p;if(l)if(r){const e=this.getRects(t,"end").rects,s=e.top+b-w,i=f-m-(e.top+b);if(s>=0&&i>=0)return;const n=h-(s<0?-(s-m):i),o=w>0&&s<0;Ls.scrollTo({top:o?n-w:n,behavior:y})}else{const t=v?.height>0?v.top+h:this.#J.offset.getGlobal(i).top,e=f+h-t-b,s=w>0?t-h>=w:f>e+m;if(e-m>0&&s)return;const n=e<=m?h-e+m+g:h-e+(f-b-m),o=w>0&&!s;Ls.scrollTo({top:o?n-w:n,behavior:y})}else{const t=v?.height>0?v.top:i.getBoundingClientRect().top,e=r?t:t-o.getBoundingClientRect().top,s=e>=(c?0:u)&&e+m<=f;let l=h+(c?e-m>0?e+m-f+u:e-b:e-m>0?e+m-f:e-(u+b));const p=Ls.scrollY,w=this.#J.offset.getGlobal(),C=c?0:d,_=c?d:0,k=p-w.top+C,x=w.top+w.height-(p+a)+_;if(k>0){const t=(s?e:e+h-l)-b-m-k;t<0&&(l+=C,Ls.scrollTo({top:p+t,behavior:"smooth"}))}if(x>0){const t=(s?e:e+h-l)+b+m-(w.height-x);t>0&&(l+=c?_:g,Ls.scrollTo({top:p+t,behavior:"smooth"}))}s||(r?n:o).scrollTo({top:l,behavior:y})}}#bt(t,e){let{top:s,bottom:i}=t;const n=[...this.#H._eventOrchestrator.scrollparents||[],Ls];for(const t of n){const n=t===Ls,o=n?0:t.getBoundingClientRect().top,r=n?this.#t.get("currentViewportHeight"):t.getBoundingClientRect().bottom;let l=0;sr&&(l=i-r),0!==l&&(t.scrollBy({top:l,behavior:e}),s-=l,i-=l)}}resetRangeToTextNode(){let t=this.getRange();if(this.#vt(t)){if(!Pe.check.isWysiwygFrame(t.startContainer)||!Pe.check.isWysiwygFrame(t.endContainer))return!1;const e=t.commonAncestorContainer,s=e.children[t.startOffset],i=e.children[t.endOffset];if(!(t=this.setRange(s,0,i,s===i?0:1)))return!1}const e=t,s=e.collapsed;let i,n,o,r=e.startContainer,l=e.startOffset,a=e.endContainer,h=e.endOffset;if(this.#J.format.isLine(r))for(r.childNodes[l]?(r=r.childNodes[l]||r,l=0):(r=r.lastChild||r,l=r.textContent.length);1===r?.nodeType&&r.firstChild;)r=r.firstChild||r,l=0;if(this.#J.format.isLine(a)){for(a=a.childNodes[h]||a.lastChild||a;1===a?.nodeType&&a.lastChild;)a=a.lastChild;s?h=0:h>0&&(h=a.textContent.length)}if(i=Pe.check.isWysiwygFrame(r)?this.#X.get("wysiwyg").firstChild:r,n=l,Pe.check.isBreak(i)||1===i.nodeType&&i.childNodes.length>0){const t=Pe.check.isBreak(i);if(!t){const t=i;for(;i&&!Pe.check.isBreak(i)&&1===i.nodeType&&(o=i.childNodes,0!==o.length);)i=o[n>0?n-1:n]||!/FIGURE/i.test(o[0].nodeName)?o[0]:i.previousElementSibling||i.previousSibling||r,n=n>0?i.textContent.length:n;let e=this.#J.format.getLine(i,null);e===this.#J.format.getBlock(e,null)&&(i||=t,e=Pe.utils.createElement(Pe.query.getParentElement(i,Pe.check.isTableCell)?"DIV":this.#rt.get("defaultLine")),i.parentNode.insertBefore(e,i),i!==t&&e.appendChild(i))}if(Pe.check.isBreak(i)||this.#J.component.is(i)){const e=Pe.utils.createTextNode(Re.zeroWidthSpace);i.parentNode.insertBefore(e,i),i=e,t&&r===a&&(a=i,h=1)}}if(r=i,l=n,i=Pe.check.isWysiwygFrame(a)?this.#X.get("wysiwyg").lastChild:a,n=h,Pe.check.isBreak(i)||1===i.nodeType&&i.childNodes.length>0){const t=Pe.check.isBreak(i);if(!t){for(;i&&!Pe.check.isBreak(i)&&1===i.nodeType&&(o=i.childNodes,0!==o.length);)i=o[n>0?n-1:n]||!/FIGURE/i.test(o[0].nodeName)?o[0]:i.previousElementSibling||i.previousSibling||r,n=n>0?i.textContent.length:n;let t=this.#J.format.getLine(i,null);t===this.#J.format.getBlock(t,null)&&(t=Pe.utils.createElement(Pe.check.isTableCell(t)?"DIV":this.#rt.get("defaultLine")),i.parentNode.insertBefore(t,i),t.appendChild(i))}if(Pe.check.isBreak(i)){const e=Pe.utils.createTextNode(Re.zeroWidthSpace);i.parentNode.insertBefore(e,i),i=e,n=1,t&&!i.previousSibling&&Pe.utils.removeItem(a)}}return a=i,h=n,this.setRange(r,l,a,h),!0}init(){const t=this.#X.get("_wd").activeElement;if(Pe.check.isInputElement(t))return this.selectionNode=t,t;const e=this.get();if(!e)return null;let s=null;s=e.rangeCount>0?e.getRangeAt(0):this.#mt(),this.#ft(s,e)}#ft(t,e){let s=null;this.#t.set("_range",t),s=t.collapsed?Pe.check.isWysiwygFrame(t.commonAncestorContainer)&&t.commonAncestorContainer.children[t.startOffset]||t.commonAncestorContainer:e.anchorNode,this.selectionNode=s}#vt(t){const e=t.commonAncestorContainer;return Pe.check.isWysiwygFrame(t.startContainer)&&Pe.check.isWysiwygFrame(t.endContainer)||/FIGURE/i.test(e.nodeName)||this.#J.pluginManager.fileInfo.regExp.test(e.nodeName)&&(!this.#J.pluginManager.fileInfo.tagAttrs[e.nodeName]||this.#J.pluginManager.fileInfo.tagAttrs[e.nodeName]?.every((t=>e.hasAttribute(t))))||this.#J.component.is(e)}#mt(){const t=this.#X.get("wysiwyg"),e=this.#X.get("_wd").createRange();let s=t.firstElementChild,i=null;return s?(i=s.firstChild,i||(i=Pe.utils.createElement("BR"),s.appendChild(i))):(i=Pe.utils.createElement("BR"),s=Pe.utils.createElement(this.#rt.get("defaultLine"),null,i),t.appendChild(s)),e.setStart(i,0),e.setEnd(i,0),e}__focus(){try{this.__iframeFocus=!0;const t=Pe.query.getParentElement(this.getNode(),"figcaption");t?t.focus():this.#X.get("wysiwyg").focus()}finally{Ls.setTimeout((()=>this.__iframeFocus=!1),0)}}__init(){this.#gt=this.#H._eventOrchestrator.scrollparents?.length>0,this.#pt=this.#X?.get("wysiwyg")?(De.get(Ls.getComputedStyle(this.#X.get("wysiwyg")).scrollMargin,0)||40)+De.get(Ls.getComputedStyle(this.#X.get("wrapper")).paddingBottom,0):40}};function Os(t,e,s){const i=[];for(let n,o,r=0,l=t.length;r!0;t;){if(Pe.check.isWysiwygFrame(t))return null;if(this.isBlock(t)){if(this.isLine(t.firstElementChild))return t.firstElementChild;if(this.isLine(t))return t}if(this.isLine(t)&&e(t))return t;t=t.parentNode}return null}setBrLine(t){if(!this.isBrLine(t))throw new Error('[SUNEDITOR.format.setBrLine.fail] The "element" must satisfy "format.isBrLine()".');const e=this.#St().lines,s=e.length-1;let i=e[s].parentNode,n=t.cloneNode(!1);const o=n;for(let o,r,l,a,h,c,d=s,u=!0;d>=0;d--)if(o=e[d],o!==(e[d+1]?e[d+1].parentNode:null)){if(c=this.#J.component.is(o),r=c?"":o.innerHTML.replace(/(?!>)\s+(?=<)|\n/g," "),l=Pe.query.getParentElement(o,(t=>t.parentNode===i)),(i!==o.parentNode||c)&&(this.isLine(i)?(i.parentNode.insertBefore(n,i.nextSibling),i=i.parentNode):(i.insertBefore(n,l?l.nextSibling:null),i=o.parentNode),a=n.nextSibling,a&&n.nodeName===a.nodeName&&Pe.check.isSameAttributes(n,a)&&(n.innerHTML+="
"+a.innerHTML,Pe.utils.removeItem(a)),n=t.cloneNode(!1),u=!0),h=n.innerHTML,n.innerHTML=(u||!r||!h||/
$/i.test(r)?r:r+"
")+h,0===d){i.insertBefore(n,o),a=o.nextSibling,a&&n.nodeName===a.nodeName&&Pe.check.isSameAttributes(n,a)&&(n.innerHTML+="
"+a.innerHTML,Pe.utils.removeItem(a));const t=n.previousSibling;t&&n.nodeName===t.nodeName&&Pe.check.isSameAttributes(n,t)&&(t.innerHTML+="
"+n.innerHTML,Pe.utils.removeItem(n))}c||Pe.utils.removeItem(o),r&&(u=!1)}this.#J.selection.setRange(o,0,o,0),this.#J.history.push(!1)}getBrLine(t,e){if(!t)return null;for(e||=()=>!0;t;){if(Pe.check.isWysiwygFrame(t))return null;if(this.isBrLine(t)&&e(t))return t;t=t.parentNode}return null}addLine(t,e){if(!t||!t.parentNode)return null;const s=this.getLine(this.#J.selection.getNode(),null);let i=null;if(this.isBrLine(t)||!this.isBrLine(s||t.parentNode)||this.#J.component.is(t)){const t=e?"string"==typeof e?e:e.nodeName:this.isNormalLine(s)?s.nodeName:this.#rt.get("defaultLine");i=Pe.utils.createElement(t,null,"
"),(e&&"string"!=typeof e||!e&&this.isLine(s))&&Pe.utils.copyTagAttributes(i,e||s,["id"])}else i=Pe.utils.createElement("BR");return Pe.check.isTableCell(t)?t.insertBefore(i,t.nextElementSibling):t.parentNode.insertBefore(i,t.nextElementSibling),i}addLineAfter(t){if(!t||!t.parentNode)return null;const e=t.nodeName,s=this.#rt.get("lineAttrReset");let i;return/^H[1-6]$/i.test(e)||this.#J.component.is(t)||this.isBrLine(t)?i=Pe.utils.createElement(this.#rt.get("defaultLine"),null,"
"):(i=Pe.utils.createElement(e,null,"
"),Pe.utils.copyTagAttributes(i,t,s)),Pe.check.isTableCell(t)?t.insertBefore(i,t.nextElementSibling):t.parentNode.insertBefore(i,t.nextElementSibling),i}getBlock(t,e){if(!t)return null;for(e||=()=>!0;t;){if(Pe.check.isWysiwygFrame(t))return null;if(this.isBlock(t)&&!/^(THEAD|TBODY|TR)$/i.test(t.nodeName)&&e(t))return t;t=t.parentNode}return null}applyBlock(t){this.#J.selection.getRangeAndAddLine(this.#J.selection.getRange(),null);const e=this.getLinesAndComponents(!1);if(!e||0===e.length)return;t:for(let t,s,i,n,o,r,l=0,a=e.length;l{let i=null;if(t!==e&&!Pe.check.isTableElements(e)){if(e&&Pe.query.getNodeDepth(t)===Pe.query.getNodeDepth(e))return s;i=this.#J.nodeTransform.removeAllParents(e,null,t)}return i?i.ec:s};for(let t,s,i,d,u,p,g,m=0,f=e.length;m=i?(l=i,o=f.cc,n=c(o,s,f.ec),n&&(o=n.parentNode)):o===f.cc&&(n=f.ec),o!==f.cc&&(d=c(o,f.cc,d),n=void 0!==d?d:f.cc);for(let t=0,e=f.removeArray.length;t=i&&(l=i,o=s,n=t.nextSibling),r.appendChild(t),o!==s&&(d=c(o,s),void 0!==d&&(n=d));if(this.#t.set("_lastSelectionNode",null),this.#J.nodeTransform.mergeSameTags(r,null,!1),this.#J.nodeTransform.mergeNestedTags(r,(t=>Pe.check.isList(t))),n&&Pe.query.getNodeDepth(n)>0&&(Pe.check.isList(n.parentNode)||Pe.check.isList(n.parentNode.parentNode))){const t=Pe.query.getParentElement(n,(t=>this.isBlock(t)&&!Pe.check.isList(t))),e=this.#J.nodeTransform.split(n,null,t?Pe.query.getNodeDepth(t)+1:0);e.parentNode.insertBefore(r,e)}else o.insertBefore(r,n),c(r,n);const d=Pe.query.getEdgeChildNodes(r.firstElementChild,r.lastElementChild);e.length>1?this.#J.selection.setRange(d.sc,0,d.ec,d.ec.textContent.length):this.#J.selection.setRange(d.ec,d.ec.textContent.length,d.ec,d.ec.textContent.length),this.#J.history.push(!1)}removeBlock(t,{selectedFormats:e,newBlockElement:s,shouldDelete:i,skipHistory:n}={}){const o=this.#J.selection.getRange();let r=o.startOffset,l=o.endOffset,a=Pe.query.getListChildNodes(t,null,1),h=t.parentNode,c=null,d=null,u=t.cloneNode(!1);const p=[],g=Pe.check.isList(s);let m=!1,f=!1,v=!1;const b=(e,s,i,n)=>{if(1===s.childNodes.length&&Pe.check.isZeroWidth(s)&&(s.innerHTML=Re.zeroWidthSpace,r=l=1),3===s.nodeType)return e.insertBefore(s,i),s;const o=(v?s:n).childNodes;let a=s.cloneNode(!1),h=null,c=null;for(;o[0];)c=o[0],!this._isNotTextNode(c)||Pe.check.isBreak(c)||Pe.check.isListCell(a)?a.appendChild(c):(a.childNodes.length>0&&(h||=a,e.insertBefore(a,i),a=s.cloneNode(!1)),e.insertBefore(c,i),h||=c);if(a.childNodes.length>0){if(Pe.check.isListCell(e)&&Pe.check.isListCell(a)&&Pe.check.isList(i))if(g){for(h=i;i;)a.appendChild(i),i=i.nextSibling;e.parentNode.insertBefore(a,e.nextElementSibling)}else{const e=n.nextElementSibling,s=this.#J.listFormat.removeNested(n,!1);if(t!==s||e!==n.nextElementSibling){const e=a.childNodes;for(;e[0];)n.appendChild(e[0]);t=s,f=!0}}else e.insertBefore(a,i);h||=a}return h};for(let n,o,r,l=0,y=a.length;l0&&(h.insertBefore(u,t),u=null),!g&&Pe.check.isListCell(n))if(r&&Pe.query.getNodeDepth(n)!==Pe.query.getNodeDepth(r)&&(Pe.check.isListCell(h)||Pe.utils.arrayFind(n.children,Pe.check.isList))){const e=n.nextElementSibling,s=this.#J.listFormat.removeNested(n,!1);t===s&&e===n.nextElementSibling||(t=s,f=!0)}else{const e=n;n=Pe.utils.createElement(i?e.nodeName:Pe.check.isList(t.parentNode)||Pe.check.isListCell(t.parentNode)?"LI":Pe.check.isTableCell(t.parentNode)?"DIV":this.#rt.get("defaultLine"));const s=Pe.check.isListCell(n),o=e.childNodes;for(;o[0]&&(!Pe.check.isList(o[0])||s);)n.appendChild(o[0]);Pe.utils.copyFormatAttributes(n,e),v=!0}else n=n.cloneNode(!1);if(!f&&(i?(p.push(n),Pe.utils.removeItem(a[l])):(s?(m||(h.insertBefore(s,t),m=!0),n=b(s,n,null,a[l])):n=b(h,n,t,a[l]),f||(e?(d=n,c||=n):c||(c=d=n))),f)){f=v=!1,a=Pe.query.getListChildNodes(t,null,1),u=t.cloneNode(!1),h=t.parentNode,l=-1,y=a.length;continue}}const y=t.parentNode;let w=t.nextSibling;u?.children.length>0&&y.insertBefore(u,w),s?c=s.previousSibling:c||=t.previousSibling,w=t.nextSibling!==u?t.nextSibling:u?u.nextSibling:null,0===t.children.length||0===t.textContent.length?Pe.utils.removeItem(t):this.#J.nodeTransform.removeEmptyNode(t,null,!1);let C=null;if(this.#t.set("_lastSelectionNode",null),i)C={cc:y,sc:c,so:r,ec:w,eo:l,removeArray:p};else{c||=d,d||=c;const t=Pe.query.getEdgeChildNodes(c,d?.parentNode?c:d);t?C={cc:(t.sc||t.ec).parentNode,sc:t.sc,so:r,ec:t.ec,eo:l,removeArray:null}:this.#J.focusManager.focus()}if(n)return C;!i&&C&&(e?this.#J.selection.setRange(C.sc,r,C.ec,l):this.#J.selection.setRange(C.sc,0,C.sc,0)),this.#J.history.push(!1)}indent(){const t=this.#J.selection.getRange(),e=t.startContainer,s=t.endContainer,i=t.startOffset,n=t.endOffset,o=Os(this.getLines(null),this.#t.get("indentSize"),this.#rt.get("_rtl")?"marginRight":"marginLeft");o.length>0&&this.#J.listFormat.applyNested(o,!1),this.#t.set("_lastSelectionNode",null),this.#J.selection.setRange(e,i,s,n),this.#J.history.push(!1)}outdent(){const t=this.#J.selection.getRange(),e=t.startContainer,s=t.endContainer,i=t.startOffset,n=t.endOffset,o=Os(this.getLines(null),-1*this.#t.get("indentSize"),this.#rt.get("_rtl")?"marginRight":"marginLeft");o.length>0&&this.#J.listFormat.applyNested(o,!0),this.#t.set("_lastSelectionNode",null),this.#J.selection.setRange(e,i,s,n),this.#J.history.push(!1)}isEdgeLine(t,e,s){if("front"===s){if(e>0)return!1}else if(t?.textContent?.length>e)return!1;let i=!1;const n="front"===s?"previousSibling":"nextSibling";for(;t&&!this.isLine(t)&&!Pe.check.isWysiwygFrame(t);){if(t[n]&&(!Pe.check.isBreak(t[n])||t[n][n]))return!1;i=!0,t=t.parentNode}return i}isTextStyleNode(t){return"string"==typeof t?this.#xt.test(t):1===t?.nodeType&&this.#xt.test(t.nodeName)}isLine(t){return"string"==typeof t?this.#yt.test(t):1===t?.nodeType&&(this.#yt.test(t.nodeName)||Pe.utils.hasClass(t,"__se__format__line_.+|__se__format__br_line_.+"))&&!this.#Et(t)}isNormalLine(t){return this.isLine(t)&&(this.#$t||!this.isBrLine(t))&&!this.isBlock(t)}isBrLine(t){return this.#$t&&this.isLine(t)||("string"==typeof t?this.#wt.test(t):1===t?.nodeType&&(this.#wt.test(t.nodeName)||Pe.utils.hasClass(t,"__se__format__br_line_.+"))&&!this.#Et(t))}isBlock(t){return"string"==typeof t?this.#Ct.test(t):1===t?.nodeType&&(this.#Ct.test(t.nodeName)||Pe.utils.hasClass(t,"__se__format__block_.+"))&&!this.#Et(t)}isClosureBlock(t){return"string"==typeof t?this.#_t.test(t):1===t?.nodeType&&(this.#_t.test(t.nodeName)||Pe.utils.hasClass(t,"__se__format__block_closure_.+"))&&!this.#Et(t)}isClosureBrLine(t){return"string"==typeof t?this.#kt.test(t):1===t?.nodeType&&(this.#kt.test(t.nodeName)||Pe.utils.hasClass(t,"__se__format__br_line__closure_.+"))&&!this.#Et(t)}getLines(t){if(!this.#J.selection.resetRangeToTextNode())return[];let e=this.#J.selection.getRange();if(Pe.check.isWysiwygFrame(e.startContainer)){const t=this.#X.get("wysiwyg").children,s=t.length;if(0===s)return[];this.#J.selection.setRange(t[0],0,t[s-1],t[s-1].textContent.trim().length),e=this.#J.selection.getRange()}const s=e.startContainer,i=e.endContainer,n=e.commonAncestorContainer;t||=this.isLine.bind(this);const o=Pe.query.getListChildren(n,(e=>t(e)),null);if(3!==n.nodeType&&(Pe.check.isWysiwygFrame(n)||this.isBlock(n))||o.unshift(this.getLine(n,null)),s===i||1===o.length)return o;const r=this.getLine(s,null),l=this.getLine(i,null);let a=null,h=null;const c=function(t){return!Pe.check.isTableElements(t)||/^TABLE$/i.test(t.nodeName)};let d=this.getBlock(r,c),u=this.getBlock(l,c);Pe.check.isTableElements(d)&&Pe.check.isListCell(d.parentNode)&&(d=d.parentNode),Pe.check.isTableElements(u)&&Pe.check.isListCell(u.parentNode)&&(u=u.parentNode);const p=d===u;for(let t,e=0,s=o.length;e{const e=Pe.query.getParentElement(t,this.#J.component.is.bind(this.#J.component));return this.isLine(t)&&(!e||e===s)||Pe.check.isComponentContainer(t)&&!this.getLine(t)}));if(t)for(let t=0,e=i.length;t=0;s--)if(i[s].contains(i[t])){i.splice(t,1),t--,e--;break}return i}_isNotTextNode(t){if(!t)return!1;const e=/^(br|input|select|canvas|img|iframe|audio|video)$/i;return"string"==typeof t?e.test(t):1===t.nodeType&&(this.#J.component.is(t)||e.test(t.nodeName))}_isExcludeSelectionElement(t){return!/FIGCAPTION/i.test(t.nodeName)&&(this.#J.component.is(t)||/FIGURE/i.test(t.nodeName))}#Et(t){return Pe.check.isExcludeFormat(t)||this.#J.component.is(t)||Pe.check.isWysiwygFrame(t)}#St(){let t=this.#J.selection.getRange(),e=this.getLinesAndComponents(!1);if(0===e.length&&(t=this.#J.selection.getRangeAndAddLine(t,null),e=this.getLinesAndComponents(!1),0===e.length))return;const s=t.startOffset,i=t.endOffset;let n=e[0],o=e.at(-1);const r=Pe.query.getNodePath(t.startContainer,n,null),l=Pe.query.getNodePath(t.endContainer,o,null),a=this.#J.listFormat.remove(e,!1);return a.sc&&(n=a.sc),a.ec&&(o=a.ec),this.#J.selection.setRange(Pe.query.getNodeFromPath(r,n),s,Pe.query.getNodeFromPath(l,o),i),{lines:this.getLinesAndComponents(!1),firstNode:n,lastNode:o,firstPath:r,lastPath:l,startOffset:s,endOffset:i}}__resetBrLineBreak(t){return this.#$t="br"===t}};function zs(t){const e=t.parentNode;if(!t||3===t.nodeType||!e)return;const s=t.childNodes;for(;s[0];)e.insertBefore(s[0],t);e.removeChild(t)}const Ps=class{#J;#rt;#Tt;#Mt;constructor(t){this.#J=t.$,this.#rt=this.#J.options,this.#Tt=this.#rt.get("__listCommonStyle"),this.#Mt=ze.camelToKebabCase(this.#rt.get("__listCommonStyle"))}apply(t,{stylesToModify:e,nodesToRemove:s,strictRemove:i}={}){if(Pe.query.getParentElement(this.#J.selection.getNode(),Pe.check.isNonEditable))return;this.#J.selection.resetRangeToTextNode();let n=this.#J.selection.getRangeAndAddLine(this.#J.selection.getRange(),null);e=e?.length>0?e:null,s=s?.length>0?s:null;const o=!t,r=o&&!s&&!e;let l=n.startContainer,a=n.startOffset,h=n.endContainer,c=n.endOffset;if(r&&n.collapsed&&this.#J.format.isLine(l.parentNode)&&this.#J.format.isLine(h.parentNode)||l===h&&1===l.nodeType&&Pe.check.isNonEditable(l)){const t=l.parentNode;if(!Pe.check.isListCell(t)||!ze.getValues(t.style).some((t=>this.#Mt.includes(t))))return}if(n.collapsed&&!r&&1===l.nodeType&&!Pe.check.isBreak(l)&&!this.#J.component.is(l)){let t=null;const e=l.childNodes[a];e&&(t=e.nextSibling?Pe.check.isBreak(e)?e:e.nextSibling:null);const s=Pe.utils.createTextNode(Re.zeroWidthSpace);l.insertBefore(s,t),this.#J.selection.setRange(s,1,s,1),n=this.#J.selection.getRange(),l=n.startContainer,a=n.startOffset,h=n.endContainer,c=n.endOffset}this.#J.format.isLine(l)&&(l=l.childNodes[a]||l.firstChild,a=0),this.#J.format.isLine(h)&&(h=h.childNodes[c]||h.lastChild,c=h.textContent.length),o&&(t=Pe.utils.createElement("DIV"));const d=RegExp,u=t.nodeName;if(!r&&l===h&&!s&&t){let e=l,s=0;const i=[],n=t.style;for(let t=0,e=n.length;t0){for(;!this.#J.format.isLine(e)&&!Pe.check.isWysiwygFrame(e);){for(let t=0;t=i.length)return}}let p,g,m={},f={},v="",b="";if(e){for(let t,s=0,i=e.length;s0&&(l=n.replace(v,"").trim(),l!==n&&(y.v=!0));const a=e.className;let h="";return b&&a.length>0&&(h=a.replace(b,"").trim(),h!==a&&(y.v=!0)),(!o||!b&&a||!v&&n||l||h||!s)&&(l||h||e.nodeName!==u||Boolean(v)!==Boolean(n)||Boolean(b)!==Boolean(a))?(v&&n.length>0&&(e.style.cssText=l),e.style.cssText||e.removeAttribute("style"),b&&a.length>0&&(e.className=h.trim()),e.className.trim()||e.removeAttribute("class"),e.style.cssText||e.className||e.nodeName!==u&&!s?e:(y.v=!0,null)):(y.v=!0,null)},C=this.#J.format.getLines(null);if(0===C.length)return void console.warn("[SUNEDITOR.inline.apply.warn] There is no line to apply.");n=this.#J.selection.getRange(),l=n.startContainer,a=n.startOffset,h=n.endContainer,c=n.endOffset,this.#J.format.getLine(l,null)||(l=Pe.query.getEdgeChild(C[0],(function(t){return 3===t.nodeType}),!1),a=0),this.#J.format.getLine(h,null)||(h=Pe.query.getEdgeChild(C.at(-1),(function(t){return 3===t.nodeType}),!1),c=h.textContent.length);const _=this.#J.format.getLine(l,null)===this.#J.format.getLine(h,null),k=C.length-(_?0:1);p=t.cloneNode(!1);const x=r||o&&(t=>{for(let e=0,s=t?.length;e0&&this.#Lt(C[k],e)&&(s=!0),this.#Lt(C[0],e)&&(s=!0),s&&this.#J.selection.setRange(l,a,h,c),k>0&&(p=t.cloneNode(!1),f=this.#Rt(C[k],p,w,h,c,r,o,y,S,E));for(let s,i=k-1;i>0;i--)this.#Lt(C[i],e),p=t.cloneNode(!1),s=this.#zt(C[i],p,w,r,o,y,f.container),s.endContainer&&s.ancestor.contains(s.endContainer)&&(f.ancestor=null,f.container=s.endContainer),this.#Ot(s.ancestor,null);p=t.cloneNode(!1),m=this.#Pt(C[0],p,w,l,a,r,o,y,S,E,f.container),m.endContainer&&(f.ancestor=null,f.container=m.endContainer),k<=0?f=m:f.container||(f.ancestor=null,f.container=m.container,f.offset=m.container.textContent.length),this.#Ot(m.ancestor,null),this.#Ot(f.ancestor||this.#J.format.getLine(f.container),null)}return this.#J.ui.offCurrentController(),this.#J.selection.setRange(m.container,m.offset,f.container,f.offset),this.#J.history.push(!1),p}remove(){this.apply(null,{stylesToModify:null,nodesToRemove:null,strictRemove:null})}_isNonSplitNode(t){if(!t)return!1;const e=/^(a|label|code|summary)$/i;return"string"==typeof t?e.test(t):1===t.nodeType&&e.test(t.nodeName)}_isIgnoreNodeChange(t){return t&&1===t.nodeType&&(Pe.check.isNonEditable(t)||!this.#J.format.isTextStyleNode(t)||this.#J.component.is(t))}#At(t,e,s,i,n,o,r,l,a,h,c,d,u){let p=i.parentNode;for(;!(p.nextSibling||p.previousSibling||this.#J.format.isLine(p.parentNode)||Pe.check.isWysiwygFrame(p.parentNode))&&p.nodeName!==e.nodeName;)p=p.parentNode;if(!a&&!l&&p===o.parentNode&&p.nodeName===e.nodeName&&Pe.check.isZeroWidth(i.textContent.slice(0,n))&&Pe.check.isZeroWidth(o.textContent.slice(r))){const s=p.childNodes;let l=!0;for(let t,e,n,r,a=0,h=s.length;a0&&(s=e.test(t.style.cssText)),!s}if(function t(i,n){const o=i.childNodes;for(let i,r=0,a=o.length;r=$?E-$:t.data.length-$)}const l=Pe.utils.createTextNode(o),h=Pe.utils.createTextNode(r);if(k){const e=d(n);if(e.parentNode!==t){let s=e,i=null;for(;s.parentNode!==t;){for(n=i=s.parentNode.cloneNode(!1);s.childNodes[0];)i.appendChild(s.childNodes[0]);s.appendChild(i),s=s.parentNode}s.parentNode.appendChild(e)}k=k.cloneNode(!1)}Pe.check.isZeroWidth(l)||n.appendChild(l);const c=d(n);for(c&&(k=c),k&&(t=k),w=a,y=[],_="";w!==t&&w!==m&&null!==w;)i=u(w)?null:s(w),i&&1===w.nodeType&&B(w)&&(y.push(i),_+=w.style.cssText.substring(0,w.style.cssText.indexOf(":"))+"|"),w=w.parentElement;const p=y.pop()||h;for(C=w=p;y.length>0;)w=y.pop(),C.appendChild(w),C=w;if(e.appendChild(p),t.appendChild(e),k&&!d(S)&&(e=e.cloneNode(!1),v.appendChild(e),f.push(e)),x=h,$=0,T=!0,w!==h&&w.appendChild(x),!b)continue}if(M||a!==S){if(T){if(1===a.nodeType&&!Pe.check.isBreak(a)){g._isIgnoreNodeChange(a)?(v.appendChild(a.cloneNode(!0)),h||(e=e.cloneNode(!1),v.appendChild(e),f.push(e))):t(a,a);continue}w=a,y=[],_="";const o=[];for(;null!==w.parentNode&&w!==m&&w!==e;)i=M?w.cloneNode(!1):s(w),1===w.nodeType&&!Pe.check.isBreak(a)&&i&&B(w)&&(u(w)?k||o.push(i):y.push(i),_+=w.style.cssText.substring(0,w.style.cssText.indexOf(":"))+"|"),w=w.parentElement;y=y.concat(o);const r=y.pop()||a;for(C=w=r;y.length>0;)w=y.pop(),C.appendChild(w),C=w;if(!u(e.parentNode)||u(r)||Pe.check.isZeroWidth(e)||(e=e.cloneNode(!1),v.appendChild(e),f.push(e)),M||k||!u(r))r===a?n=M?v:e:M?(v.appendChild(r),n=w):(e.appendChild(r),n=w);else{e=e.cloneNode(!1);const t=r.childNodes;for(let s=0,i=t.length;s0?w:e}if(k&&3===a.nodeType)if(d(a)){const t=Pe.query.getParentElement(n,(t=>g._isNonSplitNode(t.parentNode)||t.parentNode===v));k.appendChild(t),e=t.cloneNode(!1),f.push(e),v.appendChild(e)}else k=null}c=a.cloneNode(!1),n.appendChild(c),1!==a.nodeType||Pe.check.isBreak(a)||(p=c),t(a,p)}else{k=d(a);let t="",n="";if(3===S.nodeType){const e=S;t=e.substringData(E,e.length-E),n=b?"":e.substringData(0,E)}const o=Pe.utils.createTextNode(t),r=Pe.utils.createTextNode(n);if(k?k=k.cloneNode(!1):u(e.parentNode)&&!k&&(e=e.cloneNode(!1),v.appendChild(e),f.push(e)),!Pe.check.isZeroWidth(o)){w=a,_="",y=[];const t=[];for(;w!==v&&w!==m&&null!==w;)1===w.nodeType&&B(w)&&(u(w)?t.push(w.cloneNode(!1)):y.push(w.cloneNode(!1)),_+=w.style.cssText.substring(0,w.style.cssText.indexOf(":"))+"|"),w=w.parentElement;for(y=y.concat(t),c=C=w=y.pop()||o;y.length>0;)w=y.pop(),C.appendChild(w),C=w;v.appendChild(c),w.textContent=o.data}if(k&&c){const t=d(c);t&&(k=t)}for(w=a,y=[],_="";w!==v&&w!==m&&null!==w;)i=u(w)?null:s(w),i&&1===w.nodeType&&B(w)&&(y.push(i),_+=w.style.cssText.substring(0,w.style.cssText.indexOf(":"))+"|"),w=w.parentElement;const p=y.pop()||r;for(C=w=p;y.length>0;)w=y.pop(),C.appendChild(w),C=w;k?((e=e.cloneNode(!1)).appendChild(p),k.insertBefore(e,k.firstChild),v.appendChild(k),f.push(e),k=null):e.appendChild(p),S=r,E=r.data.length,M=!0,!l&&h&&(e=r,r.textContent=Re.zeroWidthSpace),w!==r&&w.appendChild(S)}}}(t,v),a&&!l&&!c.v)return{ancestor:t,startContainer:i,startOffset:n,endContainer:o,endOffset:r};if(l&&=a,l)for(let t=0;t0,w=f.pop()||d;for(b=v=w;f.length>0;)v=f.pop(),b.appendChild(v),b=v;if(h(e.parentNode)&&!h(w)&&(e=e.cloneNode(!1),m.appendChild(e),g.push(e)),!y&&h(w)){e=e.cloneNode(!1);const t=w.childNodes;for(let s=0,i=t.length;su._isNonSplitNode(t.parentNode)||t.parentNode===m));y.appendChild(t),e=t.cloneNode(!1),g.push(e),m.appendChild(e)}else y=null}if(_||d!==w)i=_?s(d):d.cloneNode(!1),i&&(n.appendChild(i),1!==d.nodeType||Pe.check.isBreak(d)||(k=i)),t(d,k);else{let t=m;y=a(d);let o="",r="";if(3===w.nodeType){const t=w;o=t.substringData(0,C),r=t.substringData(C,t.length-C)}const l=Pe.utils.createTextNode(o),h=Pe.utils.createTextNode(r);if(y){const e=a(n);if(e&&e.parentNode!==t){let s=e,i=null;for(;s.parentNode!==t;){for(n=i=s.parentNode.cloneNode(!1);s.childNodes[0];)i.appendChild(s.childNodes[0]);s.appendChild(i),s=s.parentNode}s.parentNode.appendChild(e)}y=y.cloneNode(!1)}Pe.check.isZeroWidth(l)||n.appendChild(l);const c=a(n);for(c&&(y=c),y&&(t=y),v=n,f=[];v!==t&&null!==v;)i=s(v),1===v.nodeType&&i&&f.push(i),v=v.parentNode;const u=f.pop()||n;for(b=v=u;f.length>0;)v=f.pop(),b.appendChild(v),b=v;u!==n?(e.appendChild(u),n=v):n=e,Pe.check.isBreak(d)&&e.appendChild(d.cloneNode(!1)),t.appendChild(e),w=h,C=0,_=!0,n.appendChild(w)}}}(t,m),r&&!o&&!l.v)return{ancestor:t,container:i,offset:n,endContainer:c};if(o&&=r,o)for(let t=0;t0&&h===c)return t.innerHTML=i.innerHTML,{ancestor:t,endContainer:s?Pe.query.getNodeFromPath(s,t):null}}o.v=!1;const l=this,a=t.cloneNode(!1),h=[e];let c=!0;if(function t(i,n){const o=i.childNodes;for(let i,d,u=0,p=o.length;u0&&(a.appendChild(e),e=e.cloneNode(!1)),d=p.cloneNode(!0),a.appendChild(d),a.appendChild(e),h.push(e),n=e,r&&p.contains(r)){const t=Pe.query.getNodePath(r,p);r=Pe.query.getNodeFromPath(t,d)}}}(t,e),c||n&&!i&&!o.v)return{ancestor:t,endContainer:r};if(a.appendChild(e),i&&n)for(let t=0;t0,c=m.pop()||l;for(v=f=c;m.length>0;)f=m.pop(),v.appendChild(f),v=f;if(h(e.parentNode)&&!h(c)&&(e=e.cloneNode(!1),g.insertBefore(e,g.firstChild),p.push(e)),!b&&h(c)){e=e.cloneNode(!1);const t=c.childNodes;for(let s=0,i=t.length;s0?f:e}else r?(e.insertBefore(c,e.firstChild),n=f):n=e;if(b&&3===l.nodeType)if(a(l)){const t=Pe.query.getParentElement(n,(t=>d._isNonSplitNode(t.parentNode)||t.parentNode===g));b.appendChild(t),e=t.cloneNode(!1),p.push(e),g.insertBefore(e,g.firstChild)}else b=null}if(C||l!==y)i=C?s(l):l.cloneNode(!1),i&&(n.insertBefore(i,n.firstChild),1!==l.nodeType||Pe.check.isBreak(l)||(c=i)),t(l,c);else{b=a(l);let t="",o="";if(3===y.nodeType){const e=y;t=e.substringData(w,e.length-w),o=e.substringData(0,w)}const r=Pe.utils.createTextNode(t),c=Pe.utils.createTextNode(o);if(b){b=b.cloneNode(!1);const t=a(n);if(t.parentNode!==g){let e=t,s=null;for(;e.parentNode!==g;){for(n=s=e.parentNode.cloneNode(!1);e.childNodes[0];)s.appendChild(e.childNodes[0]);e.appendChild(s),e=e.parentNode}e.parentNode.insertBefore(t,e.parentNode.firstChild)}b=b.cloneNode(!1)}else h(e.parentNode)&&!b&&(e=e.cloneNode(!1),g.appendChild(e),p.push(e));for(Pe.check.isZeroWidth(r)||n.insertBefore(r,n.firstChild),f=n,m=[];f!==g&&null!==f;)i=h(f)?null:s(f),i&&1===f.nodeType&&m.push(i),f=f.parentNode;const d=m.pop()||n;for(v=f=d;m.length>0;)f=m.pop(),v.appendChild(f),v=f;d!==n?(e.insertBefore(d,e.firstChild),n=f):n=e,Pe.check.isBreak(l)&&e.appendChild(l.cloneNode(!1)),b?(b.insertBefore(e,b.firstChild),g.insertBefore(b,g.firstChild),b=null):g.insertBefore(e,g.firstChild),y=c,w=c.data.length,C=!0,n.insertBefore(y,n.firstChild)}}}(t,g),r&&!o&&!l.v)return{ancestor:t,container:i,offset:n};if(o&&=r,o)for(let t=0;t!Pe.check.isBreak(t)));if(e=s[0],!Pe.check.isElement(e)||s.length>1)return;const i=e.style,n=t.style,o=e.nodeName.toLowerCase();let r=!1;this.#rt.get("_defaultStyleTagMap")[o]===this.#rt.get("_defaultTagCommand").bold.toLowerCase()&&(n.fontWeight="bold"),this.#rt.get("_defaultStyleTagMap")[o]===this.#rt.get("_defaultTagCommand").italic.toLowerCase()&&(n.fontStyle="italic");const l=ze.getValues(i);if(l.length>0)for(let t=0,e=this.#Tt.length;t0;)s.insertBefore(t[0],i);Pe.utils.removeItem(e)}}#Lt(t,e){if(!Pe.check.isListCell(t))return;e||=this.#Mt;const s=Pe.utils.arrayFilter(t.childNodes,(t=>!Pe.check.isBreak(t))),i=t.style,n=[],o=[],r=ze.getValues(i);for(let t=0,s=this.#Mt.length;t0&&(t.insertBefore(a,h),a=l.cloneNode(!1),h=null,c=!0));return a.childNodes.length>0&&(t.insertBefore(a,h),c=!0),0===i.length&&t.removeAttribute("style"),c}};function Ds(t){const e=t.parentNode;let s,i,n,o,r,l=e.parentNode,a=e;for(;Pe.check.isListCell(l);){for(o=Pe.query.getPositionIndex(t),s=l.nextElementSibling,i=l.parentNode,n=a;n;){if(a=a.nextSibling,Pe.check.isList(n)){for(r=n.childNodes;r[o];)i.insertBefore(r[o],s);0===r.length&&Pe.utils.removeItem(n)}else i.appendChild(n);n=a}l=i.parentNode}return 0===e.children.length&&Pe.utils.removeItem(e),i}const Fs=class{#J;#t;constructor(t){this.#J=t.$,this.#t=t.store}apply(t,e,s){const i=(t.split(":")[0]||"ol").toUpperCase(),n=t.split(":")[1]||"";let o=this.#J.selection.getRange(),r=e||this.#J.format.getLinesAndComponents(!1);if(0===r.length){if(e)return;if(o=this.#J.selection.getRangeAndAddLine(o,null),r=this.#J.format.getLinesAndComponents(!1),0===r.length)return}Pe.query.sortNodeByDepth(r,!0);const l=r[0],a=r.at(-1);let h=!Pe.check.isListCell(l)&&!this.#J.component.is(l)||l.previousElementSibling?l.previousElementSibling:l.parentElement.previousElementSibling,c=!Pe.check.isListCell(a)&&!this.#J.component.is(a)||a.nextElementSibling?a.nextElementSibling:a.parentElement.nextElementSibling;const d=o.collapsed,u={sc:o.startContainer,so:o.startContainer===o.endContainer&&Pe.check.isZeroWidth(o.startContainer)&&0===o.startOffset&&1===o.endOffset?o.endOffset:o.startOffset,ec:o.endContainer,eo:o.endOffset};let p=null,g=!0;for(let t=0,e=r.length;tthis.#J.format.getBlock(e)&&e!==r[t])))){g=!1;break}if(!g||h&&l.tagName===h.tagName&&i===h.tagName.toUpperCase()||c&&a.tagName===c.tagName&&i===c.tagName.toUpperCase()){const t=h?h.parentNode:h,e=c?c.parentNode:c;h=t&&!Pe.check.isWysiwygFrame(t)&&t.nodeName===i?t:h,c=e&&!Pe.check.isWysiwygFrame(e)&&e.nodeName===i?e:c;const s=h?.tagName===i,o=c?.tagName===i;let l=s?h:Pe.utils.createElement(i,{style:"list-style-type: "+n}),a=null,d=null;const u=t=>!Pe.check.isComponentContainer(t)&&!Pe.check.isList(t);for(let t,e,o,h,c,p,g,m,f,v=0,b=r.length;v"),t.innerHTML+=e.outerHTML,s&&(t.innerHTML+="
")}else{Pe.utils.copyFormatAttributes(t,e);const s=e.childNodes;for(;s[0];)t.appendChild(s[0])}l.appendChild(t),h&&g===p&&!this.#J.format.isBlock(m)||(a||=l,s&&h&&g===p||h&&Pe.check.isList(p)&&p===c||l.parentNode!==g&&g.insertBefore(l,m)),Pe.utils.removeItem(e),s&&null===d&&(d=l.children.length-1),h&&(this.#J.format.getBlock(p,u)!==this.#J.format.getBlock(c,u)||Pe.check.isList(p)&&Pe.check.isList(c)&&Pe.query.getNodeDepth(p)!==Pe.query.getNodeDepth(c))&&(l=Pe.utils.createElement(i,{style:"list-style-type: "+n})),0===f?.children.length&&Pe.utils.removeItem(f)}else Pe.utils.removeItem(e);d&&(a=a.children[d]),o&&(l.innerHTML+=c.innerHTML,Pe.utils.removeItem(c))}else{if(s)for(let t=0,e=r.length;t=0;s--)if(r[s].contains(r[t])){r.splice(t,1),t--,e--;break}const t=this.#J.format.getBlock(l),e=t?.tagName===i;let o,a;const h=t=>!Pe.check.isComponentContainer(t);e||(a=Pe.utils.createElement(i,{style:"list-style-type: "+n}));for(let t,l,c=0,d=r.length;c!Pe.check.isComponentContainer(t);for(let a,h,c,d,u=0,p=t.length;u1){const t=Pe.query.getNodeFromPath(a.s,a.sl),e=Pe.query.getNodeFromPath(a.e,a.el);o={sc:t,so:0,ec:e,eo:e.textContent.length}}else o={sc:h,so:c,ec:d,eo:u}}return o}removeNested(t,e){const s=Ds(t);let i,n,o;if(s){i=s.cloneNode(!1),n=s.childNodes;const e=Pe.query.getPositionIndex(t);for(;n[e];)i.appendChild(n[e])}else i=t;if(e)o=Pe.query.getListChildren(i,(t=>Pe.check.isListCell(t)&&!t.previousElementSibling),null);else{const e=Pe.query.getNodeDepth(t)+2;o=Pe.query.getListChildren(t,(t=>Pe.check.isListCell(t)&&!t.previousElementSibling&&Pe.query.getNodeDepth(t)===e),null)}for(let t=0,e=o.length;t0){const t=n.cloneNode(!1),e=n.childNodes,o=Pe.query.getPositionIndex(i);for(;e[o];)t.appendChild(e[o]);s.appendChild(t)}0===n.children.length&&Pe.utils.removeItem(n),this.#J.nodeTransform.mergeSameTags(r);const l=Pe.query.getEdgeChildNodes(e,s);return{cc:e.parentNode,sc:l.sc,ec:l.ec}}},{_d:Hs}=Oe,qs=new RegExp(Re.zeroWidthSpace+"+","g");const Ws=/^<[a-z0-9]+:[a-z0-9]+/i,Us=/(?!<)[a-zA-Z0-9-]+/,Vs=/\s(?:on[a-z]+)\s*=\s*(?:(["'])[^"']*\1|\S+)/gi,js=/style=/i,Gs=/style\s*=\s*(?:"|')[^"']*(?:"|')/,Ks=/class\s*=\s*("|')(?:[^"']*\s)?se-component(?=[\s"'])/i,Ys=/^\s/,Xs=/<[^\s]+\s(.+)/,Zs=/^[ \t\n\r\f\v]+$/,Js=/\ssize="([^"]+)"/i,Qs=/\sface="([^"]+)"/i,ti=/\scolor="([^"]+)"/i,ei=/"/g,si=/([a-zA-Z0-9-]+)(:)([^"']+)/,ii=/inherit|initial|revert|unset/i,ni=/"/g,oi=/:\s*([^;]+)/,ri=/rgba\(([0-9]+\s*,\s*){3}0\)|windowtext/i,li=/[^;]+;/g,ai=/^span$/i,hi=/^(?:https?|ftps?|mailto|tel|blob|sms|geo|webcal|callto):|^[#/]|^data:image\//i,ci=/^(?:href|src)\s*=/i,di=/=\s*(?:"([^"]*)"|'([^']*)'|(\S+))/,ui=/:/i;function pi(t){const e=function(t){let e,s=5;do{e=t,t=t.replace(/&(#x([0-9a-f]+)|#([0-9]+)|([a-z]+));/gi,((t,e,s,i)=>s?String.fromCharCode(parseInt(s,16)):i?String.fromCharCode(parseInt(i,10)):""))}while(t!==e&&--s);try{t=decodeURIComponent(t)}catch{}return t.replace(/[\u0000-\u0020]+/g,"")}(t);return hi.test(e)||!ui.test(e)}function gi(t){if(!ci.test(t))return!0;const e=t.match(di);if(!e)return!0;return pi(e[1]??e[2]??e[3]??"")}function mi(t,e){return t?"*"===t?"[a-z-]+":e?t+"|"+e:t:"^"}const fi=class{#J;#t;#X;#Q;#rt;#ut;#Ht;#qt;#Wt;#Ut;#Vt;#jt;#Gt;#Kt;#Yt;#Xt;#Zt;#Jt;#Qt;#te;#ee;#se;#ie;#ne;#oe;#re;constructor(t){this.#J=t.$,this.#t=t.store;const e=this.#rt=this.#J.options;this.#Q=this.#J.frameOptions,this.#X=this.#J.frameContext,this.#ut=this.#J.instanceCheck,this.#qt=function(t){return this.test(t)?t:""}.bind(e.get("allowedClassName")),this.#Qt=e.get("_textStyleTags");const s=e.get("tagStyles"),i={};for(const t in s){const e=t.split("|");for(let n,o=0,r=e.length;o]*>([\\s\\S]*?)<\\/\\1>|<(${l})[^>]*\\/?>`,"gi"),this.#ee=new RegExp(`^(${l})$`,"i"),this.#se=new RegExp(`^(${r})$`,"i"),this.#ie=new RegExp(`<${e.get("defaultLine")}(?:\\s[^>]*)?>`,"i");const a=Object.keys(e.get("_defaultStyleTagMap")),h=e.get("elementWhitelist")?e.get("elementWhitelist").split("|").filter((t=>/b|i|ins|s|strike/i.test(t))):[];for(let t=0;t^<]+)?\\s*(?=>)","gi");const c=e.get("__defaultAttributeWhitelist");this.#Wt=e.get("_editorElementWhitelist").includes("//")||"*"===e.get("_editorElementWhitelist"),this.#Vt=new RegExp("^("+mi(e.get("_editorElementWhitelist").replace("|//",""),"")+")$","i"),this.#jt=new RegExp("^("+(e.get("elementBlacklist")||"^")+")$","i"),this.#Gt=ze.createElementWhitelist(mi(e.get("_editorElementWhitelist").replace("|//","|\x3c!--|--\x3e"),"")),this.#Kt=ze.createElementBlacklist(e.get("elementBlacklist").replace("|//","|\x3c!--|--\x3e"));const d='\\s*=\\s*(")[^"]*\\1',u=e.get("attributeWhitelist");let p={},g="";if(u)for(const t in u)/^on[a-z]+$/i.test(u[t])||("*"===t?g=mi(u[t],c):p[t]=new RegExp("\\s(?:"+mi(u[t],c)+")"+d,"ig"));this.#Yt=new RegExp("\\s(?:"+(g||c)+"|data-se-[^\\s]+"+(e.get("v2Migration")?"|data-index|data-file-size|data-file-name|data-exp|data-font-size":"")+")"+d,"ig"),this.#ne=p;const m=e.get("attributeBlacklist");if(p={},g="",m)for(const t in m)"*"===t?g=mi(m[t],""):p[t]=new RegExp("\\s(?:"+mi(m[t],"")+")"+d,"ig");this.#Xt=new RegExp("\\s(?:"+(g||"^")+")"+d,"ig"),this.#oe=p,this.__resetAutoStyleify(e.get("autoStyleify"))}filter(t,{tagWhitelist:e,tagBlacklist:s,validate:i,validateAll:n}){if(e&&(t=t.replace(ze.createElementWhitelist(e),"")),s&&(t=t.replace(ze.createElementBlacklist(s),"")),i){const e=(new DOMParser).parseFromString(t,"text/html");e.body.querySelectorAll("*").forEach((t=>{if(n||!t.closest(".se-component")&&!t.closest(".se-flex-component")){const e=i(t);null===e?t.remove():this.#ut.isNode(e)?t.replaceWith(e):"string"==typeof e&&(t.outerHTML=e)}})),t=e.body.innerHTML}return t}clean(t,{forceFormat:e,whitelist:s,blacklist:i,_freeCodeViewMode:n}={}){const{tagFilter:o,formatFilter:r,classFilter:l,textStyleTagFilter:a,attrFilter:h,styleFilter:c}=this.#rt.get("strictMode");let d="";if(t=this.compress(t),o&&(t=t.replace(this.#te,""),t=this.#le(t,this.#Gt,this.#Kt).replace(/$/i,"")),this.#re){const e=(new DOMParser).parseFromString(t,"text/html");Pe.query.getListChildNodes(e.body,ze.spanToStyleNode.bind(null,this.#re),null),t=e.body.innerHTML}(h||c)&&(t=t.replace(/(<[a-zA-Z0-9-]+)[^>]*(?=>)/g,this.#ae.bind(this,h,c)));const u=Hs.createRange().createContextualFragment(t);if(o)try{this.#he(u,this.#Vt,this.#jt,o,r,l,n)}catch(t){console.warn("[SUNEDITOR.html.clean.fail]",t.message)}const p=u.querySelectorAll("[data-se-iframe-holder]");for(let t=0,e=p.length;t{const i=0===e||">"===s[e-1],n=e+t.length===s.length||"<"===s[e+t.length];return i&&n?t:""}))),r&&!n&&(d=this.#ge(d)),d}insert(t,{selectInserted:e,skipCharCount:s,skipCleaning:i}={}){this.#X.get("wysiwyg").contains(this.#J.selection.get().focusNode)||this.#J.focusManager.focus(),this.remove(),this.#J.focusManager.focus();let n=null;if("string"==typeof t){i||(t=this.clean(t,{forceFormat:!1,whitelist:null,blacklist:null}));try{if(Pe.check.isListCell(this.#J.format.getLine(this.#J.selection.getNode(),null))){const e=Hs.createRange().createContextualFragment(t).childNodes;this.#ce(e)&&(t=this.#me(e))}const i=Hs.createRange().createContextualFragment(t).childNodes;if(!s){const t="byte-html"===this.#Q.get("charCounter_type")?"outerHTML":"textContent";let e="";for(let s=0,n=i.length;s0){n=t.at(-1);const e=3===n?.nodeType?n.textContent.length:1;this.#J.selection.setRange(n,e,n,e)}else this.#J.focusManager.focus()}else this.#J.focusManager.focus();this.#J.history.push(!1)}insertNode(t,{afterNode:e,skipCharCount:s}={}){let i=null;if(this.#X.get("isReadOnly")||!s&&!this.#J.char.check(t))return i;let n=null,o=null;if(e){const t=this.#J.format.isLine(e)||this.#J.format.isBlock(e)||this.#J.component.is(e)?this.#J.format.addLine(e,null):e;o=this.#J.selection.setRange(t,1,t,1)}else o=this.#J.selection.getRange();let r,l,a,h=Pe.check.isListCell(o.commonAncestorContainer)?o.commonAncestorContainer:this.#J.format.getLine(this.#J.selection.getNode(),null),c=Pe.check.isListCell(h)&&(Pe.check.isListCell(t)||Pe.check.isList(t)),d=null;const u=this.#J.format.isBrLine(h),p=this.#J.format.isLine(t)||this.#J.format.isBlock(t)||this.#J.component.isBasic(t);if(c&&(a=e||Pe.check.isList(t)?h.lastChild:h.nextElementSibling,d=Pe.check.isList(t)?h:(a||h).parentNode),!e&&(p||this.#J.component.isBasic(t)||Pe.check.isMedia(t))){const t=Pe.check.isEdgePoint(o.endContainer,o.endOffset,"end"),s=this.remove(),i=s.container,n=i===s.prevContainer&&o.collapsed?null:s.prevContainer;if(c&&n)if(d=3===n.nodeType?n.parentNode:n,d.contains(i)){let t=!0;for(a=i;a.parentNode&&a.parentNode!==d;)a=a.parentNode,t=!1;t&&i===n&&(a=a.nextSibling)}else a=null;else if(c&&Pe.check.isListCell(i)&&!h.parentElement)h=Pe.utils.createElement("LI"),d.appendChild(h),i.appendChild(d),a=null;else if(3===i.nodeType||Pe.check.isBreak(i)||c){const n=Pe.query.getParentElement(i,(t=>this.#J.format.isBlock(t)||Pe.check.isListCell(t)));if(e=this.#J.nodeTransform.split(i,s.offset,n?Pe.query.getNodeDepth(n)+1:0))if(c){if(h.contains(i)){const s=Pe.check.isList(h.lastElementChild);let i=null;t||(i=h.cloneNode(!1),i.appendChild(e.textContent.trim()?e:Pe.utils.createTextNode(Re.zeroWidthSpace))),s&&(i||(i=h.cloneNode(!1),i.appendChild(Pe.utils.createTextNode(Re.zeroWidthSpace))),i.appendChild(h.lastElementChild)),i&&(h.parentNode.insertBefore(i,h.nextElementSibling),a=e=i)}}else e=e.previousSibling;else Pe.check.isListCell(h)||(a=e=h)}}o=e||p?this.#J.selection.getRange():this.#J.selection.getRangeAndAddLine(this.#J.selection.getRange(),null);const g=o.commonAncestorContainer,m=o.startOffset,f=o.endOffset,v=o.startContainer===g&&this.#J.format.isLine(g),b=v&&(g.childNodes[m]||g.childNodes[0])||o.startContainer,y=v&&(g.childNodes[f]||g.childNodes[g.childNodes.length-1])||o.endContainer;if(!c)if(e)r=e.parentNode,e=e.nextSibling,l=!0;else if(r=b,3===b.nodeType&&(r=b.parentNode),o.collapsed)if(3===g.nodeType)e=g.textContent.length>f?g.splitText(f):g.nextSibling;else if(Pe.check.isBreak(r))e=r,r=r.parentNode;else{const s=r.childNodes[m],i=3===s?.nodeType&&Pe.check.isZeroWidth(s)&&Pe.check.isBreak(s.nextSibling)?s.nextSibling:s;i?!i.nextSibling&&Pe.check.isBreak(i)?(r.removeChild(i),e=null):e=Pe.check.isBreak(i)&&!Pe.check.isBreak(t)?i:i.nextSibling:e=null}else{if(b===y){e=Pe.check.isEdgePoint(y,f)?y.nextSibling:y.splitText(f);let t=b;Pe.check.isEdgePoint(b,m)||(t=b.splitText(m)),r.removeChild(t),0===r.childNodes.length&&p&&(r.innerHTML="
")}else{const s=this.remove(),i=s.container,n=s.prevContainer;if(0===i?.childNodes.length&&p&&(this.#J.format.isLine(i)?i.innerHTML="
":this.#J.format.isBlock(i)&&(i.innerHTML="<"+this.#rt.get("defaultLine")+">
")),Pe.check.isListCell(i)&&3===t.nodeType)r=i,e=null;else if(!p&&n)if(r=3===n.nodeType?n.parentNode:n,r.contains(i)){let t=!0;for(e=i;e.parentNode&&e.parentNode!==r;)e=e.parentNode,t=!1;t&&i===n&&(e=e.nextSibling)}else e=null;else Pe.check.isWysiwygFrame(i)&&!this.#J.format.isLine(t)?(r=i.appendChild(Pe.utils.createElement(this.#rt.get("defaultLine"))),e=null):r=(e=p?y:i===n?i.nextSibling:i)&&e.parentNode?e.parentNode:g;for(;e&&!this.#J.format.isLine(e)&&e.parentNode!==g;)e=e.parentNode}}try{const s=this.#X.get("wysiwyg");if(!c){if((Pe.check.isWysiwygFrame(e)||r===s.parentNode)&&(r=s,e=null),this.#J.format.isLine(t)||this.#J.format.isBlock(t)||!Pe.check.isListCell(r)&&this.#J.component.isBasic(t)){const t=r;if(Pe.check.isListCell(e))r=e.previousElementSibling||e;else if(!l&&!e){const t=this.remove(),s=3===t.container.nodeType?Pe.check.isListCell(this.#J.format.getLine(t.container,null))?t.container:this.#J.format.getLine(t.container,null)||t.container.parentNode:t.container,i=Pe.check.isWysiwygFrame(s)||this.#J.format.isBlock(s);r=i?s:s.parentNode,e=i?null:s.nextSibling}0===t.childNodes.length&&r!==t&&Pe.utils.removeItem(t)}if(!p||u||this.#J.format.isBlock(r)||Pe.check.isListCell(r)||Pe.check.isWysiwygFrame(r)||(e=r.nextElementSibling,r=r.parentNode),Pe.check.isWysiwygFrame(r)&&(3===t.nodeType||Pe.check.isBreak(t))){const e=Pe.utils.createElement(this.#rt.get("defaultLine"),null,t);n=t,t=e}}if(c?d.parentNode?(r=d,e=a):(r=s,e=null):e=r===e?r.lastChild:e,Pe.check.isListCell(t)&&!Pe.check.isList(r)){if(Pe.check.isListCell(r))e=r.nextElementSibling,r=r.parentNode;else{const t=Pe.utils.createElement("ol");r.insertBefore(t,e),r=t,e=null}c=!0}if(this.#fe(t,r),r.insertBefore(t,e),c)if(Pe.check.isZeroWidth(h.textContent.trim()))Pe.utils.removeItem(h),t=t.lastChild;else{const e=Pe.utils.arrayFind(h.children,Pe.check.isList);e&&(t!==e?(t.appendChild(e),t=e.previousSibling):(r.appendChild(t),t=r),Pe.check.isZeroWidth(h.textContent.trim())&&Pe.utils.removeItem(h))}}catch(e){r.appendChild(t),console.warn("[SUNEDITOR.html.insertNode.warn]",e)}finally{n&&(t=n);const e=r.querySelectorAll("[data-duple]");if(e.length>0)for(let s,i,n,o,r=0,l=e.length;r0&&f>-1&&v>-1){for(let t=f+1,e=a;t>=0;t--)m[t]===e.parentNode&&m[t].firstChild===e&&0===c&&(f=t,e=e.parentNode);for(let t=v-1,e=h;t>f;t--)m[t]===e.parentNode&&1===m[t].nodeType&&(m.splice(t,1),e=e.parentNode,--v)}else{if(0===m.length){if(this.#J.format.isLine(u)||this.#J.format.isBlock(u)||Pe.check.isWysiwygFrame(u)||Pe.check.isBreak(u)||Pe.check.isMedia(u))return{container:u,offset:0,commonCon:u};if(Pe.check.isText(u))return{container:u,offset:d,commonCon:u};m.push(u),a=h=u}else if(a=h=m[0],Pe.check.isBreak(a)||Pe.check.isZeroWidth(a))return{container:Pe.check.isMedia(u)?u:a,offset:0,commonCon:u};f=v=0}const b=Pe.check.isText,y=Pe.check.isElement,w=f===v;let C=null;for(let t=f;t<=v;t++){const e=m[t];if(!b(e)||void 0!==e.data&&0!==e.length)if(e!==a)if(e!==h)C=this.#be(e,w);else{if(b(h))g=Pe.utils.createTextNode(h.substringData(d,h.length-d));else{if(this.#J.component.is(h))continue;g=Pe.utils.createTextNode(h.textContent)}g.length>0?h.data=g.data:C=this.#be(h,w)}else{if(y(a)){if(this.#J.component.is(a))continue;p=Pe.utils.createTextNode(a.textContent)}else{const t=a,s=h;e===h?(p=Pe.utils.createTextNode(t.substringData(0,c)+s.substringData(d,s.length-d)),l=c):p=Pe.utils.createTextNode(t.substringData(0,c))}if(p.length>0?a.data=p.data:C=this.#be(a,w),e===h)break}else C=this.#be(e,w)}const _=Pe.query.getParentElement(h,"ul"),k=Pe.query.getParentElement(a,"li");if(_&&k&&k.contains(_)?(r=_.previousSibling,l=r.textContent.length):(r=h&&h.parentNode?h:a&&a.parentNode?a:t.endContainer||t.startContainer,(e||s)&&(s?1===r.nodeType&&0===r.childNodes.length?(r.appendChild(Pe.utils.createElement("BR")),l=1):l=r.textContent.length:l=0)),this.#J.format.getLine(r)||a&&a.parentNode||(o?(r=o,l=0):n&&(r=n,l=1)),!Pe.check.isWysiwygFrame(r)&&0===r.childNodes.length){const t=this.#J.nodeTransform.removeAllParents(r,null,null);t&&(r=t.sc||t.ec||this.#X.get("wysiwyg"))}return r&&(1!==r.nodeType||this.#J.format.isLine(r)||Pe.check.isBreak(r))||(r=C?.sc||C?.ec,l=3===r?.nodeType?r.textContent.length:1),this.#J.selection.setRange(r,l,r,l),{container:r,offset:l,prevContainer:i,commonCon:u?.parentElement?u:null}}get({withFrame:t,includeFullPage:e,rootKey:s}={}){s?Array.isArray(s)||(s=[s]):s=[this.#t.get("rootKey")];const i=this.#t.get("rootKey"),n={};for(let i,o=0,r=s.length;o{t.hasAttribute("contenteditable")&&c.push(t);const e=t.parentElement;return a(e)&&e.children.length<=1&&h(t)&&d.push(e),!1}),null);for(let t=0,e=c.length;t";this.#ye(r);const u=r.innerHTML;if(this.#Q.get("iframe_fullPage"))if(e){const t=Pe.utils.getAttributesToString(this.#X.get("_wd").body,["contenteditable"]);i=`${this.#X.get("_wd").head.outerHTML}${u}`}else i=u;else i=t?`
${u}
`:r.innerHTML;n[s[o]]=i}return this.#J.facade.changeFrameContext(i),s.length>1?n:n[s[0]]}set(t,{rootKey:e}={}){this.#J.ui.offCurrentController(),this.#J.selection.removeRange();const s=null==t?"":this.clean(t,{forceFormat:!0,whitelist:null,blacklist:null});e?Array.isArray(e)||(e=[e]):e=[this.#t.get("rootKey")];for(let t=0;t\s+ <").replace(/\n/g,"").trim()}_convertToCode(t,e){let s="";const i=RegExp,n=new i("^(BLOCKQUOTE|PRE|TABLE|THEAD|TBODY|TR|TH|TD|OL|UL|IMG|IFRAME|VIDEO|AUDIO|FIGURE|FIGCAPTION|HR|BR|CANVAS|SELECT)$","i"),o="string"==typeof t?Hs.createRange().createContextualFragment(t):t,r=t=>this.#J.format.isLine(t)||this.#J.component.is(t),l=e?"":"\n",a=e?0:1*this.#t.get("codeIndentSize"),h=a>0?new Array(a+1).join(" "):"";return function t(e,o){const a=e?.childNodes;if(!a)return;const c=n.test(e.nodeName),d=c?o:"";for(let u,p,g,m,f,v,b=0,y=a.length;b]*>","i"))[0]+p,t(u,o+h+""),s+=(/\n$/.test(s)?v:"")+""+(g||p||c||/^(TH|TD)$/i.test(u.nodeName)?l:"")):s+=(new XMLSerializer).serializeToString(u):s+=(/^HR$/i.test(u.nodeName)?l:"")+(/^PRE$/i.test(u.parentElement.nodeName)&&/^BR$/i.test(u.nodeName)?"":d)+u.outerHTML+p:Pe.check.isList(u.parentElement)||(s+=ze.htmlToEntity(/^\n+$/.test(u.data)?"":u.data)):s+="\n\x3c!-- "+u.textContent.trim()+" --\x3e"+p}(o,""),s.trim()+l}#be(t,e){const s=this.#J.format.getLine(t,null);if(Pe.utils.removeItem(t),!Pe.check.isListCell(s)||e)return;const i=this.#J.nodeTransform.removeAllParents(s,null,null);return Pe.check.isList(s?.firstChild)&&s.insertBefore(Pe.utils.createTextNode(Re.zeroWidthSpace),s.firstChild),i?{sc:i.sc,ec:i.ec}:null}#ve(t){const e=t.parentNode;let s,i;for(;this.#J.format.isLine(t)||this.#J.format.isBlock(t);){for(s=t.childNodes,i=null;s[0];)if(i=s[0],this.#J.format.isLine(i)||this.#J.format.isBlock(i)){if(this.#ve(i),!t.parentNode)break;s=t.childNodes}else e.insertBefore(i,t);0===t.childNodes.length&&Pe.utils.removeItem(t),t=Pe.utils.createElement("BR"),e.insertBefore(t,i.nextSibling)}return t}#ue(t,e){const s=this.#rt.get("defaultLine");if(1===t.nodeType){if(this.#ee.test(t.nodeName))return"";if(Pe.check.isExcludeFormat(t))return t.outerHTML;const i=Pe.query.getListChildNodes(t,(t=>Pe.check.isSpanWithoutAttr(t)&&!Pe.query.getParentElement(t,Pe.check.isExcludeFormat)),null)||[];for(let t,e=i.length-1;e>=0;e--)t=i[e],t.replaceWith(...t.childNodes);if(!e||this.#J.format.isLine(t)||this.#J.format.isBlock(t)||this.#J.component.is(t)||Pe.check.isMedia(t)||Pe.check.isFigure(t)||Pe.check.isAnchor(t)&&Pe.check.isMedia(t.firstElementChild)){const e=t;return Pe.check.isSpanWithoutAttr(t)?e.innerHTML:e.outerHTML}{const e=t;return"<"+s+">"+(Pe.check.isSpanWithoutAttr(t)?e.innerHTML:e.outerHTML)+""}}if(3===t.nodeType){if(!e)return ze.htmlToEntity(t.textContent);const i=t.textContent.split(/\n/g);let n="";for(let t,e=0,o=i.length;e0&&(n+="<"+s+">"+ze.htmlToEntity(t)+"");return n}return 8===t.nodeType&&this.#Wt?"\x3c!--"+t.textContent.trim()+"--\x3e":""}#ge(t){if(!this.#ie.test(t))return t;const e=Pe.utils.createElement("DIV",null,t),s=e.querySelectorAll(this.#rt.get("defaultLine"));let i=!1;for(let t=s.length-1;t>=0;t--)s[t].firstChild||(Pe.utils.removeItem(s[t]),i=!0);return i?e.innerHTML:t}#we(t){return!t||11===t.nodeType||Pe.check.isWysiwygFrame(t)||Pe.check.isList(t)||Pe.check.isTableElements(t)||this.#J.format.isBlock(t)}#he(t,e,s,i,n,o,r){const l=[],a=[],h=[],c=[],d=Pe.query.getListChildNodes(t,(d=>{if(1!==d.nodeType)return n&&Pe.check.isList(d.parentElement)&&l.push(d),3===d.nodeType&&(!d.textContent||Zs.test(d.textContent)&&(this.#we(d.parentNode)||!d.previousSibling!=!d.nextSibling))&&l.push(d),!1;if(i&&(s.test(d.nodeName)||!e.test(d.nodeName)&&0===d.childNodes.length&&Pe.check.isExcludeFormat(d)))return l.push(d),!1;"PRE"===d.nodeName&&this.#Ce(d);const u=!Pe.query.getParentElement(d,Pe.check.isExcludeFormat);if(n){if(!Pe.check.isTableElements(d)&&!Pe.check.isListCell(d)&&!Pe.check.isAnchor(d)&&(this.#J.format.isLine(d)||this.#J.format.isBlock(d)||this.#J.format.isTextStyleNode(d))&&0===d.childNodes.length&&u)return a.push(d),!1;if(Pe.check.isList(d.parentNode)&&!Pe.check.isList(d)&&!Pe.check.isListCell(d))return h.push(d),!1;if(Pe.check.isTableCell(d)){const t=d.firstElementChild;if(!this.#J.format.isLine(t)&&!this.#J.format.isBlock(t)&&!this.#J.component.is(t))return c.push(d),!1}}if(o&&u&&d.className){const t=Array.from(d.classList).map(this.#qt).join(" ").trim();t?d.className=t:d.removeAttribute("class")}if(!n)return!1;return!r&&d.parentNode!==t&&u&&(Pe.check.isListCell(d)&&!Pe.check.isList(d.parentNode)||(this.#J.format.isLine(d)||this.#J.component.is(d))&&!this.#J.format.isBlock(d.parentNode)&&!Pe.query.getParentElement(d,this.#J.component.is.bind(this.#J.component)))}),null);for(let t=0,e=l.length;t=0;i--)e.insertBefore(s[i],t);u.push(t)}else{const s=e.nextSibling;let i=null;if(t.nextSibling)for(i=e.cloneNode(!1);t.nextSibling;)i.appendChild(t.nextSibling);e.parentNode.insertBefore(t,s),i&&(e.parentNode.insertBefore(i,s),u.push(i)),u.push(e)}for(let t,e=0,s=u.length;ePe.check.isListCell(t)&&!Pe.check.isList(t.parentNode)),null);for(let t,s,i,n,o=0,r=e.length;o"}t.appendChild(e)}}#_e(t){const e=t.querySelectorAll("*"),s=this.#J.format;for(let t=0;ts+("string"==typeof e[i]?e[i]:i)+(n?" "+n:"")))}#de(t){let e,s="";const i=t.childNodes;for(let t,n=0,o=i.length;n"+(s.innerHTML.trim()||"
")+"":this.#J.format.isBlock(s)&&!Pe.check.isTableElements(s)?e+=this.#me(s.children):e+="
  • "+s.outerHTML+"
  • ":e+="
  • "+(s.textContent||"
    ")+"
  • ";return e}#ce(t){let e=!1;for(let s,i=0,n=t.length;i0&&e.push('style="'+o.join(";")+'"')}return e}#le(t,e,s){return e.test("")&&(t=t.replace(/(<\/?)font(\s?)/gi,"$1span$2")),t.replace(e,"").replace(s,"")}#fe(t,e){const s=t=>{this.#xe(t,e);const i=t.childNodes;for(let t=0,e=i.length;t-1&&s.splice(t,1);for(let e=0,s=r.classList.length;e0){const e=this.#rt.get("convertTextTags"),s={};t.forEach((t=>{switch(t){case"bold":s.bold={regex:/font-weight\s*:\s*bold/i,tag:e.bold};break;case"italic":s.italic={regex:/font-style\s*:\s*italic/i,tag:e.italic};break;case"underline":s.underline={regex:/text-decoration\s*:\s*underline/i,tag:e.underline};break;case"strike":s.strike={regex:/text-decoration\s*:\s*line-through/i,tag:e.strike}}})),this.#re=s}else this.#re=null}_destroy(){this.#Jt&&this.#Jt.clear()}#Ce(t){if(1!==t.children.length||"CODE"!==t.firstElementChild?.nodeName)return;const e=t.firstElementChild,s=(e.className||"").match(/language-(\S+)/);for(s&&(Pe.utils.addClass(t,"language-"+s[1]),t.setAttribute("data-se-lang",s[1]));e.firstChild;)t.insertBefore(e.firstChild,e);t.removeChild(e)}#ye(t){const e=t.querySelectorAll('pre[class*="language-"]');for(let t,s,i,n=0,o=e.length;ni))continue;o.appendChild(s[t])}t--,e--,i--}return n.childNodes.length>0&&t.parentNode.insertBefore(n,t),o.childNodes.length>0&&t.parentNode.insertBefore(o,t.nextElementSibling),t}const i=t.parentNode;let n,o,r,l=0,a=1,h=!0;if((!s||s<0)&&(s=0),Pe.check.isText(t)){if(l=Pe.query.getPositionIndex(t),(e=Number(e))>=0&&t.length!==e){t.splitText(e);const s=Pe.query.getNodeFromPath([l+1],i);Pe.check.isZeroWidth(s)&&(s.data=Re.zeroWidthSpace)}}else if(1===t.nodeType){if(0===e){for(;t.firstChild;)t=t.firstChild;if(3===t.nodeType){const e=Pe.utils.createTextNode(Re.zeroWidthSpace);t.parentNode.insertBefore(e,t),t=e}}t.previousSibling?t=t.previousSibling:Pe.query.getNodeDepth(t)===s&&(h=!1)}1===t.nodeType&&(a=0);let c=t;for(;Pe.query.getNodeDepth(c)>s;){if(l=Pe.query.getPositionIndex(c)+a,c=c.parentNode,r=n,n=c.cloneNode(!1),o=c.childNodes,r)if(Pe.check.isListCell(n)&&Pe.check.isList(r)&&r.firstElementChild){const t=r.firstElementChild;for(;t.firstChild;)n.appendChild(t.firstChild);Pe.utils.removeItem(t),r.children.length>0&&n.appendChild(r)}else n.appendChild(r);for(;o[l];)n.appendChild(o[l])}1===c.nodeType&&c.childNodes.length<=1&&!c.firstChild?.textContent?.length&&(c.innerHTML="
    ");const d=c.parentNode;return h&&(c=c.nextSibling),n?(this.mergeSameTags(n,null,!1),this.mergeNestedTags(n,Pe.check.isList),n.childNodes.length>0?d.insertBefore(n,c):n=c,Pe.check.isListCell(n)&&n.children&&Pe.check.isList(n.children[0])&&n.insertBefore(Pe.utils.createElement("BR"),n.children[0]),0===i.childNodes.length&&Pe.utils.removeItem(i),n):c}mergeSameTags(t,e,s){const i=e?e.length:0;let n=null;i&&(n=Array.apply(null,new Array(i)).map(Number.prototype.valueOf,0));const o=(t,r,l)=>{const a=t.childNodes;for(let h,c,d=0,u=a.length;d=0;){if(Pe.utils.getArrayIndex(o.childNodes,n)!==s[l]){a=!1;break}n=h.parentNode,o=n.parentNode,l--}a&&(s.splice(r,1),s[r]=d)}}Pe.utils.copyTagAttributes(h,t),t.parentNode.insertBefore(h,t),Pe.utils.removeItem(t)}if(!c){1===h.nodeType&&o(h,r+1,d);break}if(h.nodeName===c.nodeName&&Pe.check.isSameAttributes(h,c)&&h.getAttribute?.("href")===c.getAttribute?.("href")){const t=h.childNodes;let s=0;for(let e=0,i=t.length;e0&&s++;const o=h.lastChild,a=c.firstChild;let u=0;if(o&&a){const t=3===o.nodeType&&3===a.nodeType;u=o.textContent.length;let h=o.previousSibling;for(;h&&3===h.nodeType;)u+=h.textContent.length,h=h.previousSibling;if(s>0&&3===o.nodeType&&3===a.nodeType&&(o.textContent.length>0||a.textContent.length>0)&&s--,i){let h=null;for(let c=0;cd){if(r>0&&h[r-1]!==l)continue;h[r]-=1,h[r+1]>=0&&h[r]===d&&(h[r+1]+=s,t&&o&&3===o.nodeType&&a&&3===a.nodeType&&(n[c]+=u))}}}if(3===h.nodeType){if(u=h.textContent.length,h.textContent+=c.textContent,i){let t=null;for(let o=0;od){if(r>0&&t[r-1]!==l)continue;t[r]-=1,t[r+1]>=0&&t[r]===d&&(t[r+1]+=s,n[o]+=u)}}}else{for(;c.firstChild;)h.appendChild(c.firstChild);h.normalize()}Pe.utils.removeItem(c),d--}else 1===h.nodeType&&o(h,r+1,d)}};return o(t,0,0),n}mergeNestedTags(t,e){if("string"==typeof e){const t=new RegExp(`^(${e||".+"})$`,"i");e=e=>t.test(e.nodeName)}else"function"!=typeof e&&(e=()=>!0);!function t(s){let i=s.children;if(1===i.length&&i[0].nodeName===s.nodeName&&e(s)){const t=i[0];for(i=t.children;i[0];)s.appendChild(i[0]);s.removeChild(t)}for(let e=0,i=s.children.length;e{if(t===s||this.#J.component.is(t))return!1;const e=t.textContent.trim();return 0===e.length||/^(\n|\u200B)+$/.test(e)},function t(s){if(!Pe.check.isWysiwygFrame(s)){const n=s.parentNode;n&&e(s)&&(i={sc:s.previousElementSibling,ec:s.nextElementSibling},Pe.utils.removeItem(s),t(n))}}(t),i}removeEmptyNode(t,e,s){const i=this.#rt.get("allowedEmptyTags");e&&=Pe.query.getParentElement(e,(e=>t===e.parentElement));const n=s=>{if(this.#J.format._isNotTextNode(s)||s===e||Pe.check.isNonEditable(s))return 0;if(s===t||!Pe.check.isZeroWidth(s.textContent)||s.firstChild&&Pe.check.isBreak(s.firstChild)||s.querySelector(i)){const t=s.children;for(let e=0,s=t.length,i=0;e")}createNestedNode(t,e){"function"!=typeof e&&(e=()=>!0);const s=t[0].cloneNode(!1);let i=s;for(let s,n=1,o=t.length;n{ut(t,"se-blink")}),600))}const yi=class{#J;#X;#Q;constructor(t){this.#J=t.$,this.#X=this.#J.frameContext,this.#Q=this.#J.frameOptions}check(t){const e=this.#Q.get("charCounter_max");if(e){const s=this.getLength("string"==typeof t?t:"byte-html"===this.#Q.get("charCounter_type")&&1===t.nodeType?t.outerHTML:t.textContent);if(s>0&&s+this.getLength()>e)return bi(this.#X.get("charWrapper")),!1}return!0}getLength(t){return"string"!=typeof t&&(t="byte-html"===this.#Q.get("charCounter_type")?this.#X.get("wysiwyg").innerHTML:this.#X.get("wysiwyg").textContent),/byte/.test(this.#Q.get("charCounter_type"))?this.getByteLength(t):t.length}getByteLength(t){if(!t||!t.toString)return 0;let e,s;return t=t.toString(),u?(s=decodeURIComponent(encodeURIComponent(t)).length,e=0,null!==encodeURIComponent(t).match(/(%0A|%0D)/gi)&&(e=encodeURIComponent(t).match(/(%0A|%0D)/gi).length),s+e):(s=(new TextEncoder).encode(t).length,e=0,null!==encodeURIComponent(t).match(/(%0A|%0D)/gi)&&(e=encodeURIComponent(t).match(/(%0A|%0D)/gi).length),s+e)}getWordCount(t){"string"!=typeof t&&(t=this.#X.get("wysiwyg").innerText);const e=t.trim();return e?e.split(/\s+/).length:0}display(t){const e=t||this.#X,s=e.get("charCounter"),i=e.get("wordCounter");(s||i)&&o.setTimeout((()=>{s&&(s.textContent=String(this.getLength())),i&&(i.textContent=String(this.getWordCount()))}),0)}test(t,e){let s=0;t&&(s=this.getLength(t)),this.display();const i=this.#Q.get("charCounter_max");if(i>0){let t=!1;const n=this.getLength();if(n>i){if(t=!0,s>0&&e){this.#J.selection.init();const t=this.#J.selection.getRange(),e=t.endOffset-1,s=this.#J.selection.getNode().textContent,i=t.endOffset-1;this.#J.selection.getNode().textContent=s.slice(0,i<0?0:i)+s.slice(t.endOffset,s.length),this.#J.selection.setRange(t.endContainer,e,t.endContainer,e)}}else n+s>i&&(t=!0);if(t&&(bi(this.#X.get("charWrapper")),s>0))return!1}return!0}};const wi=class{#J;#rt;#$e=!1;constructor(t){this.#J=t.$,this.#rt=this.#J.options,this.keyMap=new Map,this.reverseKeys=new Set}command(t,e,s,i,n,o,r,l){if(this.#$e)return!1;let a=null;return a=e?this.keyMap.get(i+(s?"1000":"")):this.keyMap.get(n)||this.keyMap.get(n+t.key),!(!a||!s&&a.s||a.space&&!Fe.isSpace(i)||a.enter&&!Fe.isEnter(i)||a.textTrigger&&!t.key.trim()||a.edge&&!o)&&(a.plugin&&"string"==typeof a.method?this.#J.plugins[a.plugin][a.method]?.({range:l,line:r,info:a,event:t,keyCode:i}):"function"==typeof a.method?a.method({range:l,line:r,info:a,event:t,keyCode:i}):this.#J.commandDispatcher.run(a.command,a.type,a.button),!0)}disable(){this.#$e=!0}enable(){this.#$e=!1}_registerShortcuts(){const t=this.#rt.get("shortcuts"),e=this.#rt.get("_reverseCommandArray"),s=this.keyMap=new Map,i=this.reverseKeys;for(const n of Object.keys(t)){if(this.#J.plugins[n])continue;is(n.startsWith("_")?"":n,null,t[n],s,e,i)}}_destroy(){this.keyMap.clear(),this.reverseKeys.clear()}},Ci=new Map([["__figureInst",null],["__dragInst",null],["__dragHandler",null],["__dragContainer",null],["__dragCover",null],["__dragMove",null],["__overInfo",null]]),_i=Ci,{_w:ki,isMobile:xi,ON_OVER_COMPONENT:$i}=Oe,Si="2147483646",Ei="2147483645",Ti="2147483642",Mi="2147483641",Ni={left:0,right:0,top:0};let Bi=null;const Ii=class{#J;#Se;#Ee;#Te;#Me=Ni;#Ne=!1;#Be=!1;#Ie=null;#Le=null;#Ae=null;#Oe=[];#Re=new Map;constructor(t,e,s,i,n){this.#J=e,this.kind=n||t.constructor.key||t.constructor.name,this.host=t,this.form=s,this.isOpen=!1,this.currentTarget=null,this.currentPositionTarget=null,this.isWWTarget=i.isWWTarget??!0,this.position=i.position||"bottom",this.disabled=!!i.disabled,this.parents=i.parents||[],this.parentsForm=[],this.parentsHide=!!i.parentsHide,this.sibling=i.sibling||null,this.siblingMain=!!i.siblingMain,this.isInsideForm=!!i.isInsideForm,this.isOutsideForm=!!i.isOutsideForm,this.toTop=!1,this.__offset={},this.#Se="function"==typeof i.initMethod?i.initMethod:null,this.#Ee="function"==typeof i.escGuard?i.escGuard:null,this.#Te={keydown:this.#ze.bind(this),mousedown:this.#Pe.bind(this)};for(const t of this.parents)Pe.check.isElement(t)?this.parentsForm.push(t):(t.#Oe.push(this),this.parentsForm.push(t.form));this.form.setAttribute("popover","manual"),this.#J.contextProvider.carrierWrapper.appendChild(s),this.#J.eventManager.addEvent(s,"click",this.#De.bind(this)),this.#J.eventManager.addEvent(s,"mouseenter",this.#Fe.bind(this)),this.#J.eventManager.addEvent(s,"mouseleave",this.#He.bind(this))}open(t,e,{isWWTarget:s,passive:i,initMethod:n,disabled:o,addOffset:r}={}){if(Ci.get("__overInfo")===$i&&(i=!0),!t)return void console.warn("[SUNEDITOR.Controller.open.fail] The target element is required.");if(this.form.removeAttribute("data-se-hidden-by-parent"),this.form.removeAttribute("data-se-hidden-by-children"),this.#Re.clear(),i||(this.#J.store.mode.isBalloon?this.#J.toolbar.hide():this.#J.store.mode.isSubBalloon&&this.#J.subToolbar.hide(),this.#J.store.get("hasFocus")||(o??this.disabled?this.#J.ui.setControllerOnDisabledButtons(!0):this.#J.ui.setControllerOnDisabledButtons(!1))),this.currentPositionTarget=e||t,this.isWWTarget=s??this.isWWTarget,"function"==typeof n&&(this.#Se=n),i||(this.#J.ui.currentControllerName=this.kind),this.#Me={left:0,right:0,top:0,...r},!i){const t=this.isOutsideForm?this.parentsForm:[];this.#J.ui.opendControllers?.forEach((e=>{t.includes(e.form)||(e.form.style.zIndex=Mi)})),this.parentsHide&&this.parentsForm.forEach((t=>{t.style.display="none",t.setAttribute("data-se-hidden-by-children","1")}))}this.#qe(),this.#We(this.form,this.currentPositionTarget,!1);const l=this.#J.instanceCheck.isRange(t);this.currentTarget=l?null:t,this.#Ue(this.form,t,l,i),ki.setTimeout((()=>Ci.set("__overInfo",!1)),0)}close(t){(t||this.isOpen&&!this.#Be)&&(this.form.removeAttribute("data-se-hidden-by-parent"),this.form.removeAttribute("data-se-hidden-by-children"),this.#Re.clear(),this.#Ve("close"),this.toTop=!1,this.isOpen=!1,this.#Be=!1,this.__offset={},this.#Me=Ni,this.#je(),this.#Se?.(),this.#Ge(),this.parentsHide&&!t&&this.parentsForm.forEach((t=>{t.style.display="block",t.removeAttribute("data-se-hidden-by-children")})),this.host.controllerClose?.(),this.parentsForm.length>0||this.#J.component.deselect())}hide(){this.#Ve("hide"),this.form.style.display="none"}show(){this.#We(this.form,this.currentPositionTarget,!1)}bringToTop(t){this.toTop=t,this.form.style.zIndex=t?Si:Ei}resetPosition(t){this.#We(this.form,t||this.currentPositionTarget,!0)}_scrollReposition(){this.form.hasAttribute("data-se-hidden-by-parent")||this.form.hasAttribute("data-se-hidden-by-children")||this.#We(this.form,this.currentPositionTarget,!1)&&ki.setTimeout((()=>{this.#Ve("show")}),0)}#Ve(t){for(const e of this.#Oe)if("hide"===t&&"none"!==e.form.style.display){const t=this.#Ke(e);e.#Re.set(this,!0);const s=this.#Ke(e);!t&&s&&(e.form.setAttribute("data-se-hidden-by-parent","1"),e.hide())}else if("show"===t){if(e.form.hasAttribute("data-se-hidden-by-children")){e.#Ve("show");continue}const t=this.#Ke(e);e.#Re.set(this,!1);const s=this.#Ke(e);t&&!s&&(e.form.removeAttribute("data-se-hidden-by-parent"),e.show())}else e[t]?.(!0)}#Ke(t){for(const e of t.#Re.values())if(!0===e)return!0;return!1}async#Ue(t,e,s,i){const n={position:this.position,inst:this,form:t,target:e,isRangeTarget:s,notInCarrier:!this.#J.contextProvider.carrierWrapper.contains(t)};!1!==await this.#J.eventManager.triggerEvent("onBeforeShowController",{caller:this.kind,frameContext:this.#J.frameContext,info:n})&&(t.style.display="block",this.#J.contextProvider.shadowRoot&&(this.#Ie=this.#J.eventManager.addEvent(t,"mousedown",(t=>t.stopPropagation()))),i||(this.#J.ui.onControllerContext(),this.#J.store.set("controlActive",!0),this.#J.store.set("_preventBlur",!0)),this.isOpen||this.#J.ui.opendControllers.push(n),this.isOpen=!0,this.host.controllerOn?.(t,e),this.#J.eventManager.triggerEvent("onShowController",{caller:this.kind,frameContext:this.#J.frameContext,info:n}))}#Ge(){Bi===this&&(Bi=null),this.form.hidePopover?.(),this.form.style.display="none",this.#J.ui.opendControllers=this.#J.ui.opendControllers.filter((t=>t.form!==this.form)),this.#J.ui.currentControllerName!==this.kind&&this.#J.ui.opendControllers.length>0||(this.#J.ui.setControllerOnDisabledButtons(!1),this.#J.ui.offControllerContext(),this.#J.frameContext.get("lineBreaker_t").style.display=this.#J.frameContext.get("lineBreaker_b").style.display="none",this.#J.store.set("_lastSelectionNode",null),this.#J.ui.currentControllerName="",this.#J.store.set("_preventBlur",!1),ki.setTimeout((()=>{this.#J.store.set("controlActive",!1)}),0),this.#Ie&&=this.#J.eventManager.removeEvent(this.#Ie))}#We(t,e,s){if(!e)return!1;if(t.style.visibility="hidden",t.style.display="block",this.sibling&&"block"!==this.sibling.style.display&&(this.sibling.style.visibility="hidden",this.sibling.style.display="block"),this.#J.selection.isRange(e)){if(!this.#J.offset.setRangePosition(this.form,e,{position:"bottom"}))return this.hide(),!1}else{const i=this.#J.offset.setAbsPosition(t,e,{addOffset:this.#Me,position:this.position,isWWTarget:this.isWWTarget,inst:this,sibling:this.sibling});if(!i)return this.hide(),!1;if(s||!this.sibling||this.siblingMain)this.#Ne=!1;else{const e=t.offsetTop-this.#Me.top;"bottom"===i.position?(this.#Ne=!0,t.style.top=e+this.sibling.offsetHeight-1+"px"):(this.#Ne=!1,t.style.top=e-this.sibling.offsetHeight+2+"px")}}return t.style.zIndex=this.toTop?Ei:this.#Ne?Ti:Mi,t.style.visibility="",t.showPopover?.(),!0}#qe(){this.#je(),this.#Le=this.#J.eventManager.addGlobalEvent("keydown",this.#Te.keydown,!0),this.#Ae=this.#J.eventManager.addGlobalEvent(xi?"click":"mousedown",this.#Te.mousedown,!0)}#je(){this.#J.component.__removeGlobalEvent(),this.#Le&&=this.#J.eventManager.removeGlobalEvent(this.#Le),this.#Ae&&=this.#J.eventManager.removeGlobalEvent(this.#Ae)}#Ye(){if(this.#J.ui.selectMenuOn)return!0;const t=this.#J.ui.opendControllers;for(let e=0;e0&&this.parentsForm.some((s=>{if(s.contains(t))return e=!0,!0}));const s=this.host._element;return!e&&(!!Pe.query.getParentElement(t,".se-controller")||(this.#J.component.isInline(s)?t===s:t?.contains(s)))}#De(t){const e=Pe.query.getEventTarget(t),s=Pe.query.getCommandTarget(e);s&&(t.stopPropagation(),t.preventDefault(),"close"!==s.getAttribute("data-command")?this.host.controllerAction(s):this.close())}#Fe(t){if(this.#J.ui.currentControllerName=this.kind,this.parentsForm.length>0&&this.isInsideForm)return;Pe.query.getEventTarget(t).style.zIndex=this.toTop?Si:Ei,this.sibling&&Bi!==this&&this.form.matches?.(":popover-open")&&(Bi=this,this.form.hidePopover(),this.form.showPopover())}#He(t){if(this.parentsForm.length>0&&this.isInsideForm)return;Pe.query.getEventTarget(t).style.zIndex=this.toTop?Ei:this.#Ne?Ti:Mi}#ze(t){if(this.#Ye())return;const e=t.code;if(Fe.isCtrl(t)||!Fe.isNonResponseKey(e))return;const s=Pe.query.getEventTarget(t);if(Fe.isEsc(e)){if(this.#Oe.some((({isOpen:t})=>t)))return;if(this.#Ee?.())return}else{if(this.form.contains(s)||this.#Xe(s))return;if(this.#J.pluginManager.fileInfo.pluginRegExp.test(this.kind))return}this.#Ze(s),this.close()}#Pe(t){const e=Pe.query.getEventTarget(t);this.host?._element?.contains(e)?this.#Be=!0:(this.#Be=!1,e===this.host._element||e===this.currentTarget||this.#Ye()||this.form.contains(e)||this.#Xe(e)||Pe.query.getParentElement(e,".se-line-breaker-component")||(this.#Ze(e),this.close(!0)))}#Ze(t){this.#J.frameContext.get("wysiwyg").contains(t)||(this.#J.component.__prevent=!1)}},{_w:Li}=Oe;const Ai=class{#J;#Je;#Qe;#ts;#es;#Te;#ss=null;#is=null;#ns=null;#os=null;#rs=null;#Le=null;#ls=null;#as=null;#hs=null;#st=null;#cs=null;#ds=null;#us=new Map;#ps=-1;#gs=-1;#ms=!1;#fs=null;constructor(t,e){this.#J=t;const s=e.position.split("-");this.form=null,this.items=[],this.menus=null,this.menuLen=0,this.index=-1,this.item=null,this.isOpen=!1,this.checkList=!!e.checkList,this.position=s[0],this.subPosition=s[1],this.splitNum=e.splitNum||0,this.horizontal=!!this.splitNum,this.openMethod=e.openMethod,this.closeMethod=e.closeMethod,this.subEscMethod=e.subEscMethod||null,this.subCheckMethod=e.subCheckMethod||null,this.maxHeight=e.maxHeight||"",this.minWidth=e.minWidth||"",this.#os=e.keydownTarget||null,this.#Je=/^(left|right)$/.test(this.position)?"left"===this.position?"right":"left":this.position,this.#Qe=/^(left|right)$/.test(this.subPosition)?"left"===this.subPosition?"right":"left":this.subPosition,this.#ts="ltr"!==e.dir&&("rtl"===e.dir||null),this.#es={mousedown:this.#vs.bind(this),mousemove:this.#bs.bind(this),click:this.#ys.bind(this),keydown:this.#ws.bind(this)},this.#Te={keydown:this.#Cs.bind(this),mousedown:this.#Pe.bind(this),click:this.#_s.bind(this),submenuReposition:this.#ks.bind(this)}}create(t,e){this.#ss.innerHTML="";for(const[,t]of this.#us)t.element?.remove();this.#us.clear(),e||=t;let s="";for(let i=0,n=e.length;i0&&i%this.splitNum==0&&(this.#xs(s),s="");const n=t[i],o="string"==typeof e[i]?e[i]:e[i].outerHTML,r=n&&"object"==typeof n?n:{};if(r.children?.length>0){let t="";const e=r.childMenus||r.children;for(let s=0;s${"string"==typeof e[s]?e[s]:e[s].outerHTML}`;s+=`
  • ${o}${this.#J.icons.menu_arrow_right}
  • `;const n=Pe.utils.createElement("DIV",{class:"se-select-submenu",popover:"manual","data-parent-index":String(i)},`
      ${t}
    `);this.#us.set(i,{items:r.children,menus:e,element:n})}else s+=`
  • ${o}
  • `}this.#xs(s);for(const[,t]of this.#us)this.form.appendChild(t.element);this.items=t,this.menus=Array.from(this.form.querySelectorAll("li[data-index]")),this.menuLen=this.menus.length}on(t,e,s={}){this.#is=t,this.#ns=this.#os||(Pe.check.isInputElement(t)?t:this.#J.frameContext.get("_ww")),this.#rs=e;let i="";this.maxHeight&&(i+="max-height:"+this.maxHeight+";overflow-y:auto;"),this.minWidth&&(i+="min-width:"+this.minWidth+";"),this.form=Pe.utils.createElement("DIV",{class:"se-select-menu"+(!0===this.#ts?" se-rtl":"")+(s.class?" "+s.class:""),style:s.style||""},'
    "),this.#ss=this.form.firstElementChild,t.parentNode.insertBefore(this.form,t)}open(t,e){this.#J.ui.setSelectMenuOpen(this,!0),this.openMethod?.(),this.#$s(),this.#qe();const s=t?t.split("-"):[],i=s[0]||(null!==this.#ts&&this.#ts!==this.#J.options.get("_rtl")?this.#Je:this.position),n=s[1]||(null!==this.#ts&&this.#ts!==this.#J.options.get("_rtl")?this.#Qe:this.subPosition);this.#cs=i,this.#ds=n,this.#Ss(i,n,e),this.isOpen=!0}reposition(){this.isOpen&&this.#cs&&this.#Ss(this.#cs,this.#ds)}setHidden(t){this.isOpen&&(t?(this.#Es(),this.form.style.display="none"):this.reposition())}close(){this.#J.ui.setSelectMenuOpen(this,!1),Pe.utils.removeClass(this.#is,"on"),this.#Ts(),this.form?.removeAttribute("style"),this.#ss&&this.#Ms(),this.isOpen=!1,this.closeMethod?.()}getItem(t){return this.items[t]}setItem(t){this.#Ns(t)}hasOpenSubmenu(){return this.#ps>-1}#Bs(t){if(this.#ps===t)return;this.#Es();const e=this.menus[t];if(!e||!Pe.utils.hasClass(e,"se-has-submenu"))return;Pe.utils.addClass(e,"se-submenu-open"),this.#ps=t,this.#gs=-1,this.#ms=!1;const s=this.#us.get(t),i=s?.element;if(i){const t="function"==typeof i.showPopover;i.style.visibility="hidden",t?i.matches(":popover-open")||i.showPopover():i.style.display="block",this.#Is(e,i,t),i.style.visibility="",this.#hs=this.#J.eventManager.addGlobalEvent("scroll",this.#Te.submenuReposition,!0)}}#Is(t,e,s){const i=s?{top:0,left:0}:this.form.getBoundingClientRect(),n=t.getBoundingClientRect(),o=e.offsetWidth,r=e.offsetHeight,l=Li.innerWidth,a=Li.innerHeight,h=n.right,c=n.left-o,d=Math.max(0,h+o-l),u=Math.max(0,-c);let p;p=!0===this.#ts?0===u?c:0===d?h:u<=d?c+u:h-d:0===d?h:0===u?c:d<=u?h-d:c+u,e.style.left=p-i.left+"px",e.style.right="";const g=n.top,m=n.bottom-r,f=Math.max(0,g+r-a),v=Math.max(0,-m);let b;b=0===f?g:0===v?m:f<=v?g-f:m+v,e.style.top=b-i.top+"px"}#ks(){if(this.#ps<0)return;const t=this.#us.get(this.#ps),e=t?.element,s=this.menus[this.#ps];e&&s&&this.#Is(s,e,"function"==typeof e.showPopover)}#Es(){if(this.#fs&&(Li.clearTimeout(this.#fs),this.#fs=null),this.#hs&&=this.#J.eventManager.removeGlobalEvent(this.#hs),this.#ps>-1){const t=this.menus[this.#ps];t&&Pe.utils.removeClass(t,"se-submenu-open");const e=this.#us.get(this.#ps);e?.element&&("function"==typeof e.element.hidePopover?e.element.matches(":popover-open")&&e.element.hidePopover():e.element.style.display="",Pe.utils.removeClass(e.element.querySelectorAll(".se-select-item"),"se-select-cursor"))}this.#ps=-1,this.#gs=-1,this.#ms=!1}#Ls(t,e){const s=this.#us.get(t);if(s){if(this.checkList){const t=s.element?.querySelectorAll(".se-select-item")[e];t&&Pe.utils.toggleClass(t,"se-checked")}this.#rs(s.items[e])}}#As(t){const e=this.#us.get(this.#ps);if(!e?.element)return;const s=e.element.querySelectorAll(".se-select-item"),i=s.length;if(!i)return;t=this.#gs+t;const n=this.#gs=t>=i?0:t<0?i-1:t;Pe.utils.removeClass(this.form,"se-select-menu-mouse-move");for(let t=0;t${t}`}#Ts(){this.#Os(),this.#je(),this.#Es(),this.index=-1,this.item=null,this._onItem&&(Pe.utils.removeClass(this._onItem,"se-select-on"),this._onItem=null)}#Rs(t){t=this.index+t;const e=this.menuLen,s=this.index=t>=e?0:t<0?e-1:t;this.#Ns(s)}#Ms(){this.form.style.height="",this.#ss.style.maxHeight=this.maxHeight,this.#ss.style.overflowY=this.maxHeight?"auto":""}#zs(t){const e=this.form.offsetHeight-this.#ss.offsetHeight;this.form.style.height=t+"px",this.#ss.style.maxHeight=(t-e>0?t-e:0)+"px",this.#ss.style.overflowY="auto"}#Ps(t){if(!t)return;const e=this.#ss;if(!e.style.maxHeight)return;const s=e.getBoundingClientRect().top+e.clientTop,i=s+e.clientHeight,{top:n,bottom:o}=t.getBoundingClientRect();ni&&(e.scrollTop+=o-i)}#Ns(t){Pe.utils.removeClass(this.form,"se-select-menu-mouse-move");const e=this.menuLen;for(let s=0;s0&&(u-=i+4,o.style.top=u+"px"),s=this.#J.offset.getGlobal(o).top,s<0&&(t+=s-4,u-=s-4),this.#zs(t);break}case"top":if(m=38&&this.#zs(y)}u=g-o.offsetHeight+b;break;case"bottom":if(v=38&&this.#zs(y)}u=g+(c?0:f)}if(y<38&&!i&&"middle"!==t)return void this.#Ss("top"===t?"bottom":"top",e,s,!0);if(!c)switch(e){case"center":d=h+a/2-l/2;break;case"left":d=h;break;case"right":d=h-(l-a)}o.style.left=d+"px";let w=this.#J.offset.getGlobal(o).fixedLeft,C=0;switch(c+"-"+(c?n:e)){case"true-left":w<0&&(d=h+a+1);break;case"true-right":w+l>Li.innerWidth&&(d=h-l-1);break;case"false-center":C=Li.innerWidth-(w+l),C<0&&(d+=C-4),o.style.left=d+"px",w=this.#J.offset.getGlobal(o).fixedLeft,w<0&&(d-=w-4);break;case"false-left":C=Li.innerWidth-(w+l),C<0&&(d+=C-4);break;case"false-right":w<0&&(d-=w-4)}if(s){const t=this.#ss.querySelector(s);t&&(this._onItem=t,Pe.utils.addClass(t,"se-select-on"))}o.style.left=d+"px",o.style.top=u+"px",o.style.visibility=""}#Ds(t){this.checkList&&Pe.utils.toggleClass(this.menus[t],"se-checked"),this.#rs(this.getItem(t))}#$s(){this.#Os(),this.#st={mousedown:this.#J.eventManager.addEvent(this.form,"mousedown",this.#es.mousedown),mousemove:this.#J.eventManager.addEvent(this.form,"mousemove",this.#es.mousemove),click:this.#J.eventManager.addEvent(this.form,"click",this.#es.click),keydown:this.#J.eventManager.addEvent(this.#ns,"keydown",this.#es.keydown)}}#Os(){this.#st&&(this.#J.eventManager.removeEvent(this.#st.mousedown),this.#J.eventManager.removeEvent(this.#st.mousemove),this.#J.eventManager.removeEvent(this.#st.click),this.#J.eventManager.removeEvent(this.#st.keydown),this.#st=null)}#qe(){this.#je(),this.#Le=this.#J.eventManager.addGlobalEvent("keydown",this.#Te.keydown,!0),this.#ls=this.#J.eventManager.addGlobalEvent("mousedown",this.#Te.mousedown,!0)}#je(){this.#Le&&=this.#J.eventManager.removeGlobalEvent(this.#Le),this.#ls&&=this.#J.eventManager.removeGlobalEvent(this.#ls),this.#as&&=this.#J.eventManager.removeGlobalEvent(this.#as)}#ws(t){if(this.#ms)switch(t.code){case"ArrowUp":return t.preventDefault(),t.stopPropagation(),void this.#As(-1);case"ArrowDown":return t.preventDefault(),t.stopPropagation(),void this.#As(1);case"ArrowLeft":case"ArrowRight":{t.preventDefault(),t.stopPropagation();const e=this.#ps;return this.#Es(),void(e>-1&&this.#Ns(e))}case"Enter":return void(this.#gs>-1&&(t.preventDefault(),t.stopPropagation(),this.#Ls(this.#ps,this.#gs)))}let e;switch(t.code){case"ArrowUp":if(t.preventDefault(),t.stopPropagation(),this.horizontal&&this.index>-1){const t=this.splitNum;e=this.index-t<0?t:-t}else e=-1;break;case"ArrowDown":if(t.preventDefault(),t.stopPropagation(),this.horizontal&&this.index>-1){const t=this.splitNum;e=this.index+t>this.menuLen?-t:t}else e=1;break;case"ArrowLeft":case"ArrowRight":if(t.preventDefault(),t.stopPropagation(),this.#ps>-1){const t=this.#ps;return this.#Es(),void this.#Ns(t)}if(this.subEscMethod?.())return;if(this.index>-1){if(this.#us.has(this.index))return this.#Bs(this.index),this.#ms=!0,void this.#As(1);if(this.subCheckMethod?.(this.index))return void this.#Ds(this.index)}if(!this.horizontal)return;e="ArrowLeft"===t.code?-1:1;break;case"Enter":this.index>-1&&(t.preventDefault(),t.stopPropagation(),this.#us.has(this.index)?(this.#Bs(this.index),this.#ms=!0,this.#As(1)):this.#Ds(this.index))}e&&(this.#Es(),this.subEscMethod?.(),this.#Rs(e))}#vs(t){if(Oe.isGecko){const e=Pe.query.getEventTarget(t),s=Pe.query.getParentElement(e,".se-select-item");s&&this.#J.eventManager._injectActiveEvent(s)}}#bs(t){const e=Pe.query.getEventTarget(t);Pe.utils.addClass(this.form,"se-select-menu-mouse-move");const s=e.closest?.("[data-child-index]"),i=s?.getAttribute("data-child-index");if(null!=i){this.#gs=Number(i);const t=this.#us.get(this.#ps);if(t?.element){const e=t.element.querySelectorAll(".se-select-item");Pe.utils.removeClass(e,"se-select-cursor"),Pe.utils.addClass(e[this.#gs],"se-select-cursor")}return}const n=e.closest?.("[data-index]"),o=n?.getAttribute("data-index");if(!o)return;const r=Number(o);if(this.index=r,this.#us.has(r))this.#fs&&Li.clearTimeout(this.#fs),this.#Bs(r);else if(this.#ps>-1){const t=this.#us.get(this.#ps);t?.element?.contains(e)||this.#Es()}}#ys(t){let e=Pe.query.getEventTarget(t),s=null,i=null;for(;!(s||i||/UL/i.test(e.tagName)||Pe.utils.hasClass(e,"se-select-menu"));)i=e.getAttribute("data-child-index"),i||(s=e.getAttribute("data-index")),e=e.parentElement;if(null!==i){let t=e,s=null;for(;!s&&t;)s=t.getAttribute("data-parent-index")||t.getAttribute("data-index"),t=t.parentElement;return void(null!==s&&this.#Ls(Number(s),Number(i)))}if(!s)return;const n=Number(s);this.#us.has(n)?this.#ps===n?this.#Es():this.#Bs(n):this.#Ds(n)}#Cs(t){if(Fe.isEsc(t.code)){if(this.#ps>-1){t.preventDefault(),t.stopPropagation();const e=this.#ps;return this.#Es(),void this.#Ns(e)}if(this.subEscMethod?.())return t.preventDefault(),void t.stopPropagation();this.close()}}#Pe(t){const e=Pe.query.getEventTarget(t);this.form.contains(e)||this.#J.ui.opendControllers?.some((({form:t})=>t?.contains?.(e)&&!t.contains(this.#is)))||(this.#is.contains(e)?Pe.check.isInputElement(e)||(this.#as=this.#J.eventManager.addGlobalEvent("click",this.#Te.click,!0)):this.close())}#_s(t){this.#as=this.#J.eventManager.removeGlobalEvent(this.#as),t.target===this.#is&&(t.stopPropagation(),this.close())}},{_w:Oi,ON_OVER_COMPONENT:Ri}=Oe,zi={tl:"nwse-resize",tr:"nesw-resize",bl:"nesw-resize",br:"nwse-resize",lw:"ew-resize",th:"ns-resize",rw:"ew-resize",bh:"ns-resize"};let Pi=!1,Di=!1,Fi=0,Hi=0;class qi{#J;#Fs;#Hs;#qs="";#Ws="";#Us=0;#Vs=0;#js=0;#Gs=0;#Ks="__se__float-none|__se__float-left|__se__float-center|__se__float-right";#Ys=!1;#Xs={w:"",h:""};#Zs=null;constructor(t,e,s,i){this.#J=e,this.kind=t.constructor.key||t.constructor.name,this._alignIcons={none:this.#J.icons.format_float_none,left:this.#J.icons.format_float_left,right:this.#J.icons.format_float_right,center:this.#J.icons.format_float_center},this._action={};const n=function(t,e,s){let i=null;if(s?.length>0){const{lang:n,icons:o}=e;i='
    ';for(let e,r=0;r';for(let s,r=0,l=e.length;r\n\t\t\t\t\t\t${o[s.i]||s.i}\n\t\t\t\t\t\t${n[s.l]||s.l}\n\t\t\t\t\t`}i+=""}}return i?Pe.utils.createElement("DIV",{class:"se-controller se-controller-resizing"},i):null}(this,e,s||[]);if(this.controller=n?new Ii(this,e,n,{position:"bottom",disabled:!0},this.kind):null,n){this.alignButton=n.querySelector('[data-command="onalign"]');const t=function(t,e,s){if(!s)return null;const i=[t._alignIcons.none,t._alignIcons.left,t._alignIcons.center,t._alignIcons.right],n=[e.lang.basic,e.lang.left,e.lang.center,e.lang.right],o=["none","left","center","right"],r=[],l=[];for(let t=0;t\n\t\t\t${i[t]}\n\t\t\t\n\t\t\t\t${n[t]}\n\t\t\t\n\t\t`),l.push(o[t]);return{html:r,items:l}}(this,e,this.alignButton);t&&(this.selectMenu_align=new Ai(e,{checkList:!1,position:"bottom-center"}),this.selectMenu_align.on(this.alignButton,this.#Js.bind(this),{class:"se-figure-select-list"}),this.selectMenu_align.create(t.items,t.html)),this.asButton=n.querySelector('[data-command="onas"]');const s=function(t,e){if(!e)return null;const s=[t.icons.as_block,t.icons.as_inline],i=[t.lang.asBlock,t.lang.asInline],n=["block","inline"],o=[],r=[];for(let t=0;t\n\t\t\t${s[t]}\n\t\t\t\n\t\t\t\t${i[t]}\n\t\t\t\n\t\t`),r.push(n[t]);return{html:o,items:r}}(e,this.asButton);s&&(this.selectMenu_as=new Ai(e,{checkList:!1,position:"bottom-center"}),this.selectMenu_as.on(this.asButton,this.#Qs.bind(this),{class:"se-figure-select-list"}),this.selectMenu_as.create(s.items,s.html)),this.resizeButton=n.querySelector('[data-command="onresize"]');const i=function(t,e){if(!e)return null;const s=e.getAttribute("data-value").split(","),i=[];for(let e,n,o,r,l=0;l'+r+"");return{html:i,items:s}}(e,this.resizeButton);i&&(this.selectMenu_resize=new Ai(e,{checkList:!1,position:"bottom-left",dir:"ltr"}),this.selectMenu_resize.on(this.resizeButton,this.#ti.bind(this)),this.selectMenu_resize.create(i.items,i.html))}this.inst=t,this.sizeUnit=i.sizeUnit||"px",this.autoRatio=i.autoRatio,this.isVertical=!1,this.percentageButtons=n?.querySelectorAll('[data-command="resize_percent"]')||[],this.captionButton=n?.querySelector('[data-command="caption"]'),this.align="none",this.as="block",this.__offset={},this._element=null,this._cover=null,this._inlineCover=null,this._container=null,this._caption=null,this._resizeClientX=0,this._resizeClientY=0,this._resize_direction="",this.__containerResizingOff=this.#ei.bind(this),this.__containerResizing=this.#si.bind(this),this.__onContainerEvent=null,this.__offContainerEvent=null,this.#Fs=this.#ii.bind(this),this.#Hs=this.#ni.bind(this),this.#J.eventManager.addEvent(this.alignButton,"click",this.#oi.bind(this)),this.#J.eventManager.addEvent(this.asButton,"click",this.#ri.bind(this)),this.#J.eventManager.addEvent(this.resizeButton,"click",this.#li.bind(this)),this.#J.contextProvider.applyToRoots((t=>{if(!t.get("wrapper").querySelector(".se-controller.se-resizing-container")){const e=function(){const t='\n\t\t
    \n\t\t\t\n\t\t\t\n\t\t\t\n\t\t\t\n\t\t\t\n\t\t\t\n\t\t\t\n\t\t\t\n\t\t\t
    \n\t\t
    ';return Pe.utils.createElement("DIV",{class:"se-controller se-resizing-container",style:"display: none;"},t)}(),s=e.querySelectorAll(".se-resize-dot > span");t.set("_figure",{main:e,border:e.querySelector(".se-resize-dot"),display:e.querySelector(".se-resize-display"),handles:s}),t.get("wrapper").appendChild(e),this.#J.eventManager.addEvent(s,"mousedown",this.#ai.bind(this))}}))}static CreateContainer(t,e){return Pe.utils.createElement("DIV",{class:"se-component"+(e?" "+e:"")},Pe.utils.createElement("FIGURE",null,t)),qi.GetContainer(t)}static CreateInlineContainer(t,e){return Pe.utils.createElement("SPAN",{class:"se-component se-inline-component"+(e?" "+e:"")},t),qi.GetContainer(t)}static CreateCaption(t,e){const s=Pe.utils.createElement("FIGCAPTION",null,"
    "+e+"
    ");return t.appendChild(s),s}static GetContainer(t){const e=Pe.query.getParentElement(t,"FIGURE",2),s=Pe.query.getParentElement(t,"SPAN",2),i=e||s;let n=Pe.query.getParentElement(t,(t=>t.parentElement===i),0)||t;if(Pe.check.isAnchor(n)){const t=n.querySelector(":scope > img");t&&(n=t)}return{target:n,container:Pe.query.getParentElement(n,qi.is,3)||e,cover:e,inlineCover:Pe.utils.hasClass(s,"se-inline-component")?s:null,caption:Pe.query.getEdgeChild(n.parentElement,"FIGCAPTION",!1),isVertical:Ui(n)}}static GetRatio(t,e,s){let i=0,n=0;if(/\d+/.test(t+"")&&/\d+/.test(e+"")){if((!De.is(t)&&String(t).replace(/\d+|\./g,"")||s||"px")===(!De.is(e)&&String(e).replace(/\d+|\./g,"")||s||"px")){const s=De.get(t,4),o=De.get(e,4);i=s/o,n=o/s}}return{w:De.get(i,4),h:De.get(n,4)}}static CalcRatio(t,e,s,i){if(i?.w&&i?.h&&/\d+/.test(t+"")&&/\d+/.test(e+"")){const n=!De.is(t)&&String(t).replace(/\d+|\./g,"")||s||"px",o=!De.is(e)&&String(e).replace(/\d+|\./g,"")||s||"px";if(n===o){const s="%"===n?2:0,r=t,l=e;e=De.get(i.h*De.get(r,s),s)+o,t=De.get(i.w*De.get(l,s),s)+n}}return{w:t,h:e}}static is(t){return Pe.check.isComponentContainer(t)||/^(HR)$/.test(t?.nodeName)}close(){this.#J.store.set("_preventBlur",!1),Pe.utils.removeClass(this._cover,"se-figure-selected"),this.#J.component.__removeDragEvent(),this.#hi(),this.controller?.close()}open(t,{nonResizing:e,nonSizeInfo:s,nonBorder:i,figureTarget:n,infoOnly:o}){if(!t)return void console.warn('[SUNEDITOR.modules.Figure.open] The "targetNode" is null.');Ci.get("__overInfo")===Ri&&(i=!0);const r=qi.GetContainer(t),l=r.target;let a=!1;if(!r.container){if(this.#J.options.get("strictMode").formatFilter)return{container:null,cover:null,width:l.style.width||l.width||"",height:l.style.height||l.height||"",isVertical:this.isVertical};r.container=l,r.cover=l,a=!0}Ci.set("__figureInst",this),this.#ci(r);const h=n&&(this._cover||this._container)||l,c=h.offsetWidth||null,d=h.offsetHeight||null,{top:u,left:p,scrollX:g,scrollY:m}=this.#J.offset.getLocal(h),f=(l.getAttribute("data-se-size")||"").split(",");let v=De.get(l.style.width,2)||c,b=De.get(l.style.height,2)||d;this.isVertical&&([v,b]=[b,v]);const y=qi.GetRatio(v,b,this.sizeUnit),w={container:r.container,cover:r.cover,caption:r.caption,align:this.align,ratio:y,isVertical:this.isVertical,w:c||"",h:d||"",t:u,l:p,width:f[0]||"auto",height:f[1]||"auto",originWidth:l.naturalWidth||l.offsetWidth,originHeight:l.naturalHeight||l.offsetHeight};if(this.#qs=w.width,this.#Ws=w.height,o)return w;const C=this.#J.frameContext.get("_figure");this.#J.ui.setFigureContainer(C.main),this.#J.ui.opendControllers=this.#J.ui.opendControllers.filter((t=>t.form!==C.main)),C.main.style.top=u+"px",C.main.style.left=p+"px",C.main.style.width=(this.isVertical?d:c)+"px",C.main.style.height=(this.isVertical?c:d)+"px",C.border.style.top="0px",C.border.style.left="0px",C.border.style.width=(this.isVertical?d:c)+"px",C.border.style.height=(this.isVertical?c:d)+"px",this.__offset={left:p+g,top:u+m},this.#J.ui.opendControllers.push({position:"none",form:C.main,target:h,inst:this,notInCarrier:!0});const _=/%$/.test(l.style.width)&&/%$/.test(r.container.style.width)?De.get(r.container.style.width,0)/100+"":"";for(let t=0,e=this.percentageButtons.length;t{t.style.display=s}));const i=this.controller.form.querySelector('[data-command="onas"]');i&&(i.style.display=a?"none":"")}Pe.utils.removeClass(this._cover,"se-figure-over-selected"),this.controller?.open(C.main,null,{initMethod:this.#Fs,isWWTarget:!1,addOffset:null}),Oi.setTimeout((()=>Ci.set("__overInfo",!1)),0)}else Pe.utils.addClass(this._cover,"se-figure-over-selected");return Pe.utils.addClass(this._cover,"se-figure-selected"),this.#js=this.#Us=c,this.#Gs=this.#Vs=d,this._inlineCover||Ci.get("__overInfo")===Ri&&!Pe.utils.hasClass(r.container,"se-input-component")||this.#pi(C.main),w}controllerHide(){this.controller?.hide()}controllerShow(){this.controller?.show()}controllerOpen(t,e){this._element=t,this.controller?.open(t,null,e)}setFigureSize(t,e){/%$/.test(t+"")?this._setPercentSize(t,e):t&&"auto"!==t||e&&"auto"!==e?this._applySize(t,e,""):this.autoRatio?this._setPercentSize(100,this.autoRatio.default||this.autoRatio.current):this._setAutoSize()}setSize(t,e){const s=this.isVertical;s&&([t,e]=[e,t]),this.setFigureSize(t,e),s&&this.setTransform(this._element,t,e,0)}getSize(t){t||=this._element;const e=Ui(t);let s="",i="",n="",o="";if(!t)return{w:s,h:i,dw:n,dh:o};const r=qi.GetContainer(t),l=r.target;return r.container?(s=/%$/.test(l.style.width)?(r.container&&De.get(r.container.style.width,2)||100)+"%":l.style.width,i=r.inlineCover?r.inlineCover.style.height||t.style.height||String(t.height||""):De.get(r.cover?.style.paddingBottom,0)>0&&!e?r.cover?.style.height:/%$/.test(l.style.height)&&/%$/.test(l.style.width)?(r.container&&De.get(r.container.style.height,2)||100)+"%":l.style.height,s||="auto",i||="auto"):this.#J.options.get("strictMode").formatFilter?(s="",i=l.style.height):(s=l.style.width||"auto",i=l.style.height||"auto"),n=e?i:s,o=e?s:i,{w:s,h:i,dw:n,dh:o}}setAlign(t,e){t||=this._element,this.align=e||="none";const s=qi.GetContainer(t);if(!s.cover)return;const i=s.target,n=s.container,o=s.cover;if(/%$/.test(i.style.width)&&"center"===e&&!this.#J.component.isInline(n)?(n.style.minWidth="100%",o.style.width=n.style.width):(n.style.minWidth="",o.style.width=this.isVertical?i.style.height||i.offsetHeight+"px":i.style.width&&"auto"!==i.style.width?i.style.width||"100%":""),Pe.utils.hasClass(n,"__se__float-"+e)||(Pe.utils.removeClass(n,this.#Ks),Pe.utils.addClass(n,"__se__float-"+e)),this.autoRatio){const{w:t,h:e}=this.getSize(this._element);this.__setCoverPaddingBottom(t,e)}this.#di()}convertAsFormat(t,e){t||=this._element,this.as=e||"block";const{container:s,inlineCover:i,target:n}=qi.GetContainer(t),{w:o,h:r}=this.getSize(n),l=Pe.check.isAnchor(n.parentNode)?n.parentNode:null,a=n.cloneNode(!1);a.style.width="",a.style.height="",a.removeAttribute("width"),a.removeAttribute("height");let h=a;if(l){const t=l.cloneNode(!1);t.appendChild(a),h=t}switch(e){case"inline":{if(i)break;this.#J.component.deselect();const t=s.nextElementSibling,e=s.parentElement,n=qi.CreateInlineContainer(h);Pe.utils.addClass(n.container,s.className.split(" ").filter((t=>"se-figure-selected"!==t&&"se-component-selected"!==t)).join("|")),this.#gi(n,o,r);const l=Pe.utils.createElement(this.#J.options.get("defaultLine"),null,n.container);e.insertBefore(l,t),Pe.utils.removeItem(s);break}case"block":{if(!i)break;this.#J.component.deselect(),this.#J.selection.setRange(s,0,s,1);const t=this.#J.html.remove(),e=this.#J.nodeTransform.split(t.container,t.offset,0);e?.previousElementSibling&&Pe.check.isZeroWidth(e.previousElementSibling)&&Pe.utils.removeItem(e.previousElementSibling);const n=qi.CreateContainer(h);Pe.utils.addClass(n.container,s.className.split(" ").filter((t=>"se-inline-component"!==t&&"se-figure-selected"!==t&&"se-component-selected"!==t)).join("|")),this.#gi(n,o,r),(e||t.container).parentElement.insertBefore(n.container,e);break}}return a}controllerAction(t){const e=t.getAttribute("data-command"),s=t.getAttribute("data-value"),i=t.getAttribute("data-type"),n=this._element;if(!/^on.+/.test(e)&&"selectMenu"!==i){switch(e){case"mirror":{const t=Wi(n);let e=t.x,i=t.y;"h"===s&&!this.isVertical||"v"===s&&this.isVertical?i=i?"":"180":e=e?"":"180",this._setRotate(n,t.r,e,i);break}case"rotate":this.setTransform(n,null,null,Number(s));break;case"caption":if(this._caption)Pe.utils.removeItem(this._caption),Oi.setTimeout(this.#J.component.select.bind(this.#J.component,n,this.kind),0),this._caption=null;else{const t=qi.CreateCaption(this._cover,this.#J.lang.caption),e=Pe.query.getEdgeChild(t,(t=>3===t.nodeType),!1);e?this.#J.selection.setRange(e,0,e,e.textContent.length):t.focus(),this._caption=t,this.controller.close()}(/\d+/.test(n.style.height)||this.isVertical&&this._caption)&&(/%$/.test(n.style.width)||/auto/.test(n.style.height)?this.deleteTransform():this.setTransform(n,n.style.width,n.style.height,0));break;case"revert":this._setRevert();break;case"edit":this.inst.componentEdit(n);break;case"copy":this.#J.component.copy(this._container);break;case"remove":this.inst.componentDestroy(n),this.controller.close()}/^__c__/.test(e)?this._action[e](n,s,t):"edit"!==e&&(this.#J.history.push(!1),/^remove|caption$/.test(e)||this.#J.component.select(n,this.kind))}}retainFigureFormat(t,e,s,i){const n=this.#J.component.isInline(t),o=e.parentNode,r=1===o.children?.length&&!o.textContent.replace(Re.zeroWidthRegExp,"").trim();let l=this.#J.format.isBlock(o)||Pe.check.isWysiwygFrame(o)||o.nodeType>=9?e:qi.GetContainer(e)?.container||(r?o:e);if(Pe.query.getParentElement(e,Pe.check.isExcludeFormat))l=s&&s!==e?s:e,l.parentNode.replaceChild(t,l);else if(n&&this.#J.format.isLine(l)){const s=n&&/^SPAN$/i.test(e.parentElement.nodeName)?e.parentElement:e;s.parentElement.replaceChild(t,s)}else if(Pe.check.isListCell(l)){const s=Pe.query.getParentElement(e,(t=>t.parentNode===l));l.insertBefore(t,s),Pe.utils.removeItem(e),this.#J.nodeTransform.removeEmptyNode(s,null,!0)}else if(this.#J.format.isLine(l)){const s=Pe.query.getParentElement(e,(t=>t.parentNode===l));l=this.#J.nodeTransform.split(l,s),l.parentNode.insertBefore(t,l),Pe.utils.removeItem(e),this.#J.nodeTransform.removeEmptyNode(l,null,!0)}else if(this.#J.format.isLine(l.parentNode)){const e=l.parentNode;e.parentNode.insertBefore(t,l.previousSibling?e.nextElementSibling:e),(0===i?.__updateTags.map((t=>l.contains(t))).length||Pe.check.isZeroWidth(l))&&Pe.utils.removeItem(l)}else l=Pe.check.isFigure(l.parentNode)?Pe.query.getParentElement(l.parentNode,qi.is):l,l.parentNode.replaceChild(t,l)}deleteTransform(t){t||=this._element;const e=t,s=(e.getAttribute("data-se-size")||"").split(",");this.isVertical=!1,e.style.maxWidth="",e.style.transform="",e.style.transformOrigin="",this.#mi(e),this._applySize(s[0]||"auto",s[1]||"","")}setTransform(t,e,s,i){try{this.#Ys=!0;const n=Wi(t),o=n.r+1*(i||0);i=Math.abs(o)>=360?0:o;const r=this.isVertical=Ui(i);e=De.get(e,0),s=De.get(s,0);const l=t,a=(l.getAttribute("data-se-size")||"auto,auto").split(",");r&&this._setRotate(l,i,n.x,n.y);let h="";if(/auto|%$/.test(a[0])&&!r)"auto"===a[0]&&"auto"===a[1]?this._setAutoSize():this._setPercentSize(a[0],a[1]);else{const t=qi.GetContainer(l),n=t.cover||t.inlineCover,o=e||l.offsetWidth,a=s||l.offsetHeight,c=(r?a:o)+"px",d=(r?o:a)+"px";if(this.#fi(),this._applySize(o+"px",a+"px",""),n&&(n.style.width=c,n.style.height=t.caption||t.inlineCover?"":d),r){h=90===i||-270===i?a/2+"px "+a/2+"px 0":o/2+"px "+o/2+"px 0"}}l.style.transformOrigin=h,r||this._setRotate(l,i,n.x,n.y),l.style.maxWidth=r?"none":"",this.#vi(l)}finally{this.#Ys=!1}}_displayResizeHandles(t){const e=t?"flex":"none";this.controller&&(this.controller.form.style.display=e);const s=this.#J.frameContext.get("_figure"),i=s.handles;for(let t=0,s=i.length;tthis.#J.component.select(t.target,i),this.#ci(t),t.inlineCover&&(this.setAlign(t.target,"none"),this.deleteTransform()),this.setFigureSize(e,s)}#ci(t){this._inlineCover=t.inlineCover,this._cover=t.cover||this._inlineCover,this._container=t.container,this._caption=t.caption,this._element=t.target,this.align=(this._container.className.match(/(?:^|\s)__se__float-(none|left|center|right)(?:$|\s)/)||[])[1]||t.target.style.float||"none",this.as=this._inlineCover?"inline":"block",this.isVertical=Ui(t.target)}_setRotate(t,e,s,i){let n=(t.offsetWidth-t.offsetHeight)*(/^-/.test(e+"")?1:-1),o="";if(/[1-9]/.test(e+"")&&(s||i))switch(o=s?"Y":"X",e+""){case"90":o=s&&i?"X":i?o:"";break;case"270":n*=-1,o=s&&i?"Y":s?o:"";break;case"-90":o=s&&i?"Y":s?o:"";break;case"-270":n*=-1,o=s&&i?"X":i?o:"";break;default:o=""}e%180==0&&(t.style.maxWidth=""),t.style.transform="rotate("+e+"deg)"+(s?" rotateX("+s+"deg)":"")+(i?" rotateY("+i+"deg)":"")+(o?" translate"+o+"("+n+"px)":"")}_applySize(t,e,s){const i=/^(rw|lw)$/.test(s)&&/\d+/.test(this._element.style.height),n=/^(th|bh)$/.test(s)&&/\d+/.test(this._element.style.width);e=e||(this.autoRatio?this.autoRatio.current||this.autoRatio.default:e),t=De.is(t)?t+this.sizeUnit:t,/%$/.test(t)||/%$/.test(e)||i||n||this.#fi();const o=this._cover||this._element;this.autoRatio&&this._cover&&(this._cover.style.width=t),n||(o.style.width=this._element.style.width=t),i||(e=De.is(e)?e+this.sizeUnit:e,o.style.height=this._element.style.height=this.autoRatio&&!this.isVertical?"100%":e,this.autoRatio&&this._cover&&(this._cover.style.height=e,this.__setCoverPaddingBottom(t,e))),"center"===this.align&&this.setAlign(this._element,this.align),this.#bi()}__setCoverPaddingBottom(t,e){this._inlineCover!==this._cover&&(this.isVertical&&([t,e]=[e,t]),this._cover.style.height=e,/%$/.test(t)&&"center"===this.align?this._cover.style.paddingBottom=/%$/.test(e)?De.get(De.get(e,2)/100*De.get(t,2),2)+"%":e:this._cover.style.paddingBottom=e)}_setAutoSize(){this._caption&&(this._caption.style.marginTop=""),this.deleteTransform(),this.#fi(),this.autoRatio?this._setPercentSize("100%",this.autoRatio.current||this.autoRatio.default):(this._element.style.maxWidth="",this._element.style.width="",this._element.style.height="",this._cover&&(this._cover.style.width="",this._cover.style.height="")),this.setAlign(this._element,this.align),this.#bi()}_setPercentSize(t,e){e||=this.autoRatio?/%$/.test(this.autoRatio.current)?this.autoRatio.current:this.autoRatio.default:e,e=!e||/%$/.test(e+"")||De.get(e,0)?De.is(e)?e+this.sizeUnit:e||(this.autoRatio?this.autoRatio.default:""):De.is(e)?e+"%":e;const s=/%$/.test(e+"");this._container.style.width=String(De.is(t)?t+"%":t),this._container.style.height="",this._element!==this._cover||this.#J.options.get("strictMode").formatFilter?(this._inlineCover!==this._cover&&this._cover&&(this._cover.style.width="100%",this._cover.style.height=String(e)),this._element.style.width="100%",this._element.style.maxWidth="",this._element.style.height=String(this.autoRatio?"100%":s?"":e),"center"===this.align&&this.setAlign(this._element,this.align),this.autoRatio&&this.__setCoverPaddingBottom(String(t),String(e)),this.#vi(this._element),this.#bi()):this.#bi()}#fi(){this._cover&&(this._cover.style.width="",this._cover.style.height=""),this._container.style.width="",this._container.style.height="",Pe.utils.removeClass(this._container,this.#Ks),Pe.utils.addClass(this._container,"__se__float-"+this.align),"center"===this.align&&this.setAlign(this._element,this.align)}_setRevert(){this.setFigureSize(this.#Xs.w,this.#Xs.h)}#di(){this.alignButton&&Pe.utils.changeElement(this.alignButton.firstElementChild,this._alignIcons[this.align])}#ui(){this.asButton&&Pe.utils.changeElement(this.asButton.firstElementChild,this.#J.icons[`as_${this.as}`])}#bi(){if(this.#Ys)return;const t=(this._element.getAttribute("data-se-size")||",").split(",");this.#Xs.w=t[0],this.#Xs.h=t[1];const e=this.getSize(this._element);this._element.setAttribute("width",e.w.replace("px","")),this._element.setAttribute("height",e.h.replace("px","")),this._element.setAttribute("data-se-size",e.w+","+e.h),this.autoRatio&&(this.autoRatio.current=/%$/.test(e.h)?e.h:"")}#vi(t){const e=Pe.query.getEdgeChild(Pe.query.getParentElement(t,"FIGURE"),"FIGCAPTION",!1);e&&(e.style.marginTop=(this.isVertical&&!this.autoRatio?t.offsetWidth-t.offsetHeight:0)+"px",this.isVertical&&this.autoRatio?t.style.marginTop=e.offsetHeight+"px":t.style.marginTop="")}#mi(t){const e=Pe.query.getEdgeChild(Pe.query.getParentElement(t,"FIGURE"),"FIGCAPTION",!1);e&&(e.style.marginTop="")}#yi(){this.#J.component.__removeDragEvent(),this.#hi(),this._displayResizeHandles(!0),this.#J.ui.offCurrentController(),this.#J.ui.disableBackWrapper()}#hi(){this.#J.eventManager.removeGlobalEvent(this.__onContainerEvent),this.#J.eventManager.removeGlobalEvent(this.__offContainerEvent),this.#J.eventManager.removeGlobalEvent(this.#Zs)}#pi(t){const e=this.#J.frameContext.get("wrapper").querySelector(".se-drag-handle");Pe.utils.removeClass(e,"se-drag-handle-full"),e.style.opacity="",e.style.width="",e.style.height="",Ci.set("__dragHandler",e),Ci.set("__dragContainer",this._container),Ci.set("__dragCover",this._cover),Ci.set("__dragMove",this.#wi.bind(this,e,t)),Ci.get("__dragMove")(),e.style.display="block"}#wi(t,e){t.style.display="block",t.style.left=e.offsetLeft+(this.#J.options.get("_rtl")?t.offsetWidth:e.offsetWidth-1.5*t.offsetWidth)+"px",t.style.top=e.offsetTop-t.offsetHeight+.5+"px"}#ai(t){t.stopPropagation(),t.preventDefault();const e=Ci.get("__figureInst");if(!e)return;const s=Pe.query.getEventTarget(t),i=e._resize_direction=s.classList[0];e._resizeClientX=t.clientX,e._resizeClientY=t.clientY,this.#J.frameContext.get("_figure").main.style.float=/l/.test(i)?"right":/r/.test(i)?"left":"none",this.#J.ui.enableBackWrapper(zi[i]);const{w:n,h:o,dw:r,dh:l}=this.getSize(e._element);if(Pi=Di=!1,Fi=Hi=0,!this.isVertical){const t=!n||/auto|%$/.test(n),s=!o||/auto|%$/.test(o);if("tl|bl|tr|br".includes(i)&&t&&s?Pi=!0:"lw|rw".includes(i)&&t&&(Di=!0),Pi||Di){const t=e._cover||e._element;Hi=t.offsetWidth,Fi=ze.getWidthInPercentage(t,this.#J.frameContext.get("wysiwygFrame"))/100}}e.__onContainerEvent=this.#J.eventManager.addGlobalEvent("mousemove",e.__containerResizing),e.__offContainerEvent=this.#J.eventManager.addGlobalEvent("mouseup",e.__containerResizingOff),e._displayResizeHandles(!1);const a=this.#J.frameContext.get("_figure").display;a.style.display="block",Pe.utils.changeTxt(a,r+" * "+l)}#si(t){const e=this._resize_direction,s=t.clientX,i=t.clientY,n=this.isVertical;let o=n?this.#Gs:this.#js,r=n?this.#js:this.#Gs;const l=o+(/r/.test(e)?s-this._resizeClientX:this._resizeClientX-s),a=r+(/b/.test(e)?i-this._resizeClientY:this._resizeClientY-i),h=r/o*l,c=this.#J.frameContext.get("_figure").border;/t/.test(e)&&(c.style.top=r-(/h/.test(e)?a:h)+"px"),/l/.test(e)&&(c.style.left=o-l+"px"),/r|l/.test(e)&&(c.style.width=l+"px",o=l),/^(t|b)[^h]$/.test(e)?(c.style.height=h+"px",r=h):/^(t|b)h$/.test(e)&&(c.style.height=a+"px",r=a);const d=!n&&/h$/.test(e)?this.#qs:Math.round(o),u=!n&&/w$/.test(e)?this.#Ws:Math.round(r),p=Fi?d/Hi*Fi*100:d;Pe.utils.changeTxt(this.#J.frameContext.get("_figure").display,Fi?De.get(p>100?100:p,2).toFixed(2)+"%":p+" * "+u),this.#Us=d,this.#Vs=u}#ei(){this.#yi();let t=this.isVertical?this.#Vs:this.#Us,e=this.isVertical?this.#Us:this.#Vs;if(t=Math.round(t)||t,e=Math.round(e)||e,!this.isVertical&&!/%$/.test(t+"")){const s=this.#J.frameContext.get("wysiwygFrame").clientWidth-De.get(this.#J.frameContext.get("wwComputedStyle").getPropertyValue("padding-left"))+De.get(this.#J.frameContext.get("wwComputedStyle").getPropertyValue("padding-right"))-2;De.get(t,0)>s&&(e=Math.round(e/t*s),t=s)}if(Pi||Di){t=t/(this._cover||this._element).offsetWidth*Fi*100;const e=De.get(t>100?100:t,2)+"%";this._setPercentSize(e,Di?this.getSize(this._element).h:"")}else this._applySize(t,e,this._resize_direction),this.isVertical&&this.setTransform(this._element,t,e,0);this.#J.history.push(!1),this.#J.component.select(this._element,this.kind)}#ni(t){Fe.isEsc(t.code)&&(this.#yi(),this.#J.component.select(this._element,this.kind))}#Js(t){this.setAlign(this._element,t),this.selectMenu_align.close(),this.#J.component.select(this._element,this.kind),this.#J.history.push(!1)}#Qs(t){this.convertAsFormat(this._element,t),this.selectMenu_as.close(),this.#J.history.push(!1)}#ti(t){if("auto"===t)this.deleteTransform(),this._setAutoSize();else{let e=this.getSize(this._element).h;if(this.isVertical){const t=(this._element.getAttribute("data-se-size")||",").split(",");t[1]&&(e=t[1])}this.deleteTransform(),this._setPercentSize(1*t,null!==De.get(e,0)&&/%$/.test(e)?e:"")}this.selectMenu_resize.close(),this.#J.component.select(this._element,this.kind),this.#J.history.push(!1)}#ii(){const t=this.#J.frameContext.get("_figure");t.main.style.display="none",this.#J.ui.setFigureContainer(null),this.#J.ui.opendControllers=this.#J.ui.opendControllers.filter((e=>e.form!==t.main))}#oi(){this.selectMenu_align.open("",'[data-command="'+this.align+'"]')}#ri(){this.selectMenu_as.open("",'[data-command="'+this.as+'"]')}#li(){const t=this.getSize(this._element),e=t.w,s=t.h;let i="";if(this.autoRatio){if(s===this.autoRatio.default&&/%$/.test(e)){const t=De.get(e);i=100===t?"auto":"resize_percent"+t}}else"auto"===s&&("auto"===e?i="auto":/%$/.test(e)&&(i="resize_percent"+De.get(e)));this.selectMenu_resize.open("",'[data-command="'+i+'"]')}}function Wi(t){const e=t.style.transform;return e?{r:Number((e.match(/rotate\(([-0-9]+)deg\)/)||[])[1]||0),x:(e.match(/rotateX\(([-0-9]+)deg\)/)||[])[1]||"",y:(e.match(/rotateY\(([-0-9]+)deg\)/)||[])[1]||""}:{r:0,x:"",y:""}}function Ui(t){return/^(90|270)$/.test(Math.abs(De.is(t)?t:Wi(t).r).toString())}function Vi(t){const e=t.split("_"),s=e[0],i=e[1];let n,o,r,l;switch(s){case"resize":n="onresize",o=i,r="resize",l="resize";break;case"auto":n="auto",r="autoSize",l="auto_size";break;case"rotate":n="rotate",o="l"===i?-90:"r"===i?90:De.get(i),r=o<0?"rotateLeft":"rotateRight",l=o<0?"rotate_left":"rotate_right";break;case"mirror":n="mirror",o=i,r="h"===i?"mirrorHorizontal":"mirrorVertical",l="h"===i?"mirror_horizontal":"mirror_vertical";break;case"align":n="onalign",r="align",l="align_justify";break;case"caption":n="caption",r="caption",l="caption";break;case"revert":n="revert",r="revert",l="revert";break;case"edit":n="edit",r="edit",l="edit";break;case"as":n="onas",r="blockStyle",l="as_block";break;case"copy":n="copy",r="copy",l="copy";break;case"remove":n="remove",r="remove",l="delete"}return n?{c:n,v:o,l:r,t:undefined,i:l}:null}const ji=qi,{_w:Gi,ON_OVER_COMPONENT:Ki,isMobile:Yi}=Oe,Xi=/^Arrow(Left|Up|Right|Down)$/,Zi=/^Arrow(Left|Up)$/;function Ji(t,e,s){t.preventDefault(),t.stopPropagation(),Qi(e),s.setData("text/html",e.outerHTML)}function Qi(t){Pe.utils.removeClass(t,"se-component-selected"),Pe.utils.removeClass(t.querySelectorAll(".se-figure-selected"),"se-figure-selected"),Pe.utils.removeClass(t.querySelectorAll(".se-selected-table-cell"),"se-selected-table-cell"),Pe.utils.removeClass(t.querySelector(".se-selected-cell-focus"),"se-selected-cell-focus")}const tn=class{#H;#J;#t;#Ci;#ot;#rt;#X;#_i;#it;#ki=null;#xi=null;#$i=null;#ls=null;constructor(t){this.#H=t,this.#J=t.$,this.#t=t.store,this.#Ci=this.#J.contextProvider,this.#ot=this.#Ci.carrierWrapper,this.#rt=this.#J.options,this.#X=this.#J.frameContext,this.#_i=this.#J.eventManager,this.info=null,this.isSelected=!1,this.currentTarget=null,this.currentPlugin=null,this.currentPluginName="",this.currentInfo=null,this.#it={copy:this.#Si.bind(this),cut:this.#Ei.bind(this),keydown:this.#Ti.bind(this),mousedown:this.#Pe.bind(this)},this.__selectionSelected=!1,this.__prevent=!1}_init(){this.#Ci.applyToRoots((t=>{const e=Pe.utils.createElement("DIV",{class:"se-drag-handle",draggable:"true"},this.#Ci.icons.selection);t.get("wrapper").appendChild(e),this.#_i.addEvent(e,"mouseenter",this.#Mi.bind(this)),this.#_i.addEvent(e,"mouseleave",this.#Ni.bind(this)),this.#_i.addEvent(e,"dragstart",this.#Bi.bind(this)),this.#_i.addEvent(e,"dragend",this.#Ii.bind(this)),this.#_i.addEvent(e,"click",this.#Li.bind(this))}))}insert(t,{skipCharCount:e=!1,skipHistory:s=!1,scrollTo:i=!0,insertBehavior:n}={}){if(this.#X.get("isReadOnly")||!e&&!this.#J.char.check(t))return null;void 0===n&&(n=this.#rt.get("componentInsertBehavior")),this.isSelected&&this.__deselect();const o=this.#J.html.remove(),r=this.isInline(t);this.#J.selection.getRangeAndAddLine(this.#J.selection.getRange(),o.container);const l=this.#J.selection.getNode();let a=null,h=this.#J.format.getLine(l,null);try{if(Pe.check.isListCell(h))this.#J.html.insertNode(t,{afterNode:r?null:Pe.check.isZeroWidth(l)?(l||o.container||{}).nextSibling:null,skipCharCount:!0}),r||t.nextSibling||t.parentNode.appendChild(Pe.utils.createElement("BR"));else{if(!r&&this.#J.selection.getRange().collapsed&&(3===o.container?.nodeType||Pe.check.isBreak(o.container))){const t=Pe.query.getParentElement(o.container,this.#J.format.isBlock.bind(this.#J.format));a=this.#J.nodeTransform.split(o.container,o.offset,t?Pe.query.getNodeDepth(t)+1:0),a&&(h=a.previousSibling)}this.#J.html.insertNode(t,{afterNode:r||this.#J.format.isBlock(h)?null:h,skipCharCount:!0}),!r&&h&&Pe.check.isZeroWidth(h)&&Pe.utils.removeItem(h)}if(r){const e=Pe.utils.createTextNode(Re.zeroWidthSpace);t.parentNode.insertBefore(e,t.nextSibling)}}catch(t){console.error("Component insert error:",t)}s||this.#J.history.push(!1),this.#X.has("documentType_use_header")&&this.#X.get("documentType").reHeader();const c=a||t;return i&&this.#J.selection.scrollTo(c,{behavior:"auto",noFocus:!0}),null!==n&&this.applyInsertBehavior(t,a,n),c}applyInsertBehavior(t,e,s){const i=this.get(t);if(this.isInline(t)){const e=this.#J.selection.getNearRange(t);e?this.#J.selection.setRange(e.container,e.offset,e.container,e.offset):this.select(i.target,i.pluginName)}else switch(s){case"auto":this.#Ai(t)||this.select(i.target,i.pluginName);break;case"select":this.#J.selection.setRange(t,0,t,0),i?this.select(i.target,i.pluginName):e&&(e=Pe.query.getEdgeChildNodes(e,null).sc||e,this.#J.selection.setRange(e,0,e,0));break;case"line":if(!this.#Ai(t)){const e=this.#J.format.addLine(t,null);e&&this.#J.selection.setRange(e,0,e,0)}}}get(t){if(!t)return null;let e,s="",i={},n=!1,o=null;if(this.is(t)){if(Pe.check.isComponentContainer(t)&&!Pe.utils.hasClass(t,"se-inline-component")&&(t=t.firstElementChild||t),/^FIGURE$/i.test(t.nodeName)&&(t=t.firstElementChild),!t)return null;const n=this.#J.pluginManager.findComponentInfo(t);if(!n)return null;e=n.target,s=n.pluginName,i=n.options,o=n.launcher}if(!e&&t.nodeName){this.#Oi(t)&&(n=!0);const r=this.#J.pluginManager.findComponentInfo(t);if(!r)return null;e=r.target,s=r.pluginName,i=r.options,o=r.launcher}if(!e)return null;const r=ji.GetContainer(e),l=r.container||r.cover||e;return this.info={target:r.target,pluginName:s,options:i,container:l,cover:r.cover,inlineCover:r.inlineCover,caption:r.caption,isFile:n,launcher:o,isInputType:Pe.utils.hasClass(l,"se-input-component")}}select(t,e,{isInput:s=!1}={}){const i=this.get(t);if(!i||Pe.check.isUneditable(Pe.query.getParentElement(t,this.is.bind(this)))||Pe.check.isUneditable(t))return!1;const n=i.launcher||this.#J.plugins[e];if(!n)return;const o=_i.get("__overInfo")!==Ki;if(!s&&o){if(this.#t.get("_mousedown"))return;this.#t.set("_preventBlur",!0),this.__selectionSelected=!0,this.isInline(i.container)&&this.#J.selection.setRange(i.container,0,i.container,0),this.#J.focusManager.blur(),Gi.setTimeout((()=>{this.__selectionSelected=!1}))}let r;this.isSelected=!0,this.__prevent=!0,"function"==typeof n.componentSelect&&(r=n.componentSelect(t));const l=Pe.utils.hasClass(i.target,"se-component-line-break");(l||!r&&!Pe.utils.hasClass(i.container,"se-inline-component"))&&this._setComponentLineBreaker(i.container||i.cover||t),this.currentTarget=t,this.currentPlugin=n,this.currentPluginName=e,this.currentInfo=i,_i.set("__dragInst",this);const a=_i.get("__overInfo");if(Gi.setTimeout((()=>{_i.set("__overInfo",a===Ki&&void 0),a!==Ki&&this.#qe(),i.isFile||this.#Ri(),Pe.utils.addClass(i.container,"se-component-selected")}),0),!o||this.#t.get("hasFocus")||this.#t.get("_preventFocus")||(this.#H._eventOrchestrator.__postFocusEvent(this.#X,null),this.#t.set("_preventFocus",!0)),l||a===Ki){if(l||!Pe.utils.hasClass(i.container,"se-input-component")){const t=this.#X.get("wrapper").querySelector(".se-drag-handle");Pe.utils.addClass(t,"se-drag-handle-full"),this.#J.ui._visibleControllers(!1,!1);const e=i.caption?i.target:i.cover||i.container||i.target,s=e.offsetWidth,n=e.offsetHeight,{top:o,left:r}=this.#J.offset.getLocal(e);t.style.opacity="0",t.style.width=s+"px",t.style.height=n+"px",t.style.top=o+"px",t.style.left=r+"px",_i.set("__dragHandler",t),_i.set("__dragContainer",i.container),_i.set("__dragCover",i.cover),t.style.display="block"}}else{if(!this.isInline(i.container))return;const t=i.container;let e=null;t.previousSibling&&!Pe.check.isBreak(t.previousSibling)||(e=Pe.utils.createTextNode(Re.zeroWidthSpace),t.parentNode.insertBefore(e,t)),t.nextSibling&&!Pe.check.isBreak(t.nextSibling)||(e=Pe.utils.createTextNode(Re.zeroWidthSpace),t.parentNode.insertBefore(e,t.nextSibling)),this.#t.set("controlActive",!0)}}deselect(){Gi.setTimeout((()=>{this.#t.set("controlActive",!1)}),0),this.__deselect(),this.#J.ui.setControllerOnDisabledButtons(!1),!this.#t.get("_preventFocus")||this.#t.get("hasFocus")||this.__prevent||(this.#H._eventOrchestrator.__postBlurEvent(this.#X,null),this.#t.set("_preventFocus",!1))}is(t){return!!t&&(!(!/^FIGURE$/i.test(t.nodeName)&&!Pe.check.isComponentContainer(t))||!!this.#J.pluginManager.findComponentInfo(t))}isInline(t){if(!t)return!1;if(/^FIGURE$/i.test(t.nodeName)&&(t=t.parentElement),Pe.utils.hasClass(t,"se-inline-component"))return!0;return!(!this.#J.pluginManager.findComponentInfo(t)||!Pe.utils.hasClass(t,"se-inline-component")&&!Pe.utils.hasClass(t.parentElement,"se-inline-component"))}isBasic(t){return this.is(t)&&!this.isInline(t)}async copy(t){const e=Pe.utils.clone(t,!0);Qi(e),!1!==await this.#J.html.copy(e)&&Pe.utils.flashClass(t,"se-copy")}hoverSelect(t){const e=Pe.query.getParentElement(t,Pe.check.isFigure);let s=this.get(t);s||e?(s||=this.get(e),s&&!Pe.utils.hasClass(s.container,"se-component-selected")&&(this.#J.ui.offCurrentController(),_i.set("__overInfo",Ki),this.select(s.target,s.pluginName))):null===_i.get("__overInfo")||Pe.utils.hasClass(t,"se-drag-handle")||(this.__deselect(),_i.set("__overInfo",null))}__deselect(){if(this.#t.set("_preventBlur",!1),_i.set("__overInfo",null),this.__removeDragEvent(),this.currentInfo){const t=this.currentInfo.container,e=this.currentInfo.cover;Gi.setTimeout((()=>{Qi(t),Pe.utils.removeClass(e,"se-figure-over-selected")}),0)}this.#X.get("lineBreaker_t")&&(this.#X.get("lineBreaker_t").style.display=this.#X.get("lineBreaker_b").style.display="none"),this.currentPlugin&&this.currentPlugin.componentDeselect?.(this.currentTarget),this.isSelected=!1,this.currentPlugin=null,this.currentTarget=null,this.currentPluginName="",this.currentInfo=null,this.__removeGlobalEvent(),this.#J.ui._offControllers()}_setComponentLineBreaker(t){const e=_i.get("__overInfo")===Ki;this.#H._eventOrchestrator._lineBreakComp=null;const s=this.get(t);if(!s)return;const i=this.#X,n=s.container,o=Pe.utils.hasClass(n,"se-flex-component"),r=i.get("lineBreaker_t"),l=i.get("lineBreaker_b"),a=r.style,h=l.style,c=n.offsetWidtht.hasAttribute(e))))}#Mi(){this.#t.set("_preventBlur",!0),this.#J.ui._visibleControllers(!1,Pe.utils.hasClass(_i.get("__dragHandler"),"se-drag-handle-full")),Pe.utils.addClass(_i.get("__dragCover")||_i.get("__dragContainer"),"se-drag-over")}#Ni(){this.#t.set("_preventBlur",!1),Pe.utils.hasClass(_i.get("__dragHandler"),"se-drag-handle-full")||this.#J.ui._visibleControllers(!0,!0),Pe.utils.removeClass([_i.get("__dragCover"),_i.get("__dragContainer")],"se-drag-over")}#Bi(t){const e=_i.get("__dragCover")||_i.get("__dragContainer");e?(this.#t.set("_preventBlur",!1),Pe.utils.addClass(_i.get("__dragHandler"),"se-dragging"),Pe.utils.addClass(_i.get("__dragContainer"),"se-dragging"),t.dataTransfer.setDragImage(e,this.#rt.get("_rtl")?e.offsetWidth:-5,-5)):t.preventDefault()}#Ii(){this.#t.set("_preventBlur",!1),Pe.utils.removeClass([_i.get("__dragHandler"),_i.get("__dragContainer")],"se-dragging"),this.__removeDragEvent()}#Li(t){const e=Pe.query.getEventTarget(t);if(!Pe.utils.hasClass(e,"se-drag-handle-full"))return;const s=_i.get("__dragInst");s&&(this.__removeDragEvent(),this.select(s.currentTarget,s.currentPluginName))}#Pe(t){const e=Pe.query.getEventTarget(t);this.currentTarget?.contains(e)||Pe.query.getParentElement(e,".se-controller")||Pe.utils.hasClass(e,"se-drag-handle")||this.currentPluginName===this.#J.ui.currentControllerName&&this.#J.ui.opendControllers.some((({form:t})=>t.contains(e)))||this.deselect()}#Si(t){const e=Pe.query.getEventTarget(t);if(Pe.check.isInputElement(e)&&Pe.query.getParentElement(e,".se-modal"))return;const s=this.info;if(!s)return;const i=s.container.cloneNode(!0);"function"==typeof this.#J.plugins[s.pluginName]?.componentCopy&&!1!==this.#J.plugins[s.pluginName].componentCopy({event:t,cloneContainer:i,info:s})||Ji(t,i,t.clipboardData),Pe.utils.flashClass(s.container,"se-copy")}#Ei(t){const e=this.info;if(!e)return;const s=e.container.cloneNode(!0);Pe.utils.removeClass(s,"se-component-selected"),Ji(t,s,t.clipboardData),this.deselect(),Pe.utils.removeItem(e.container)}async#Ti(t){if(this.#J.ui.selectMenuOn)return;const e=t.code;if(Fe.isCtrl(t)){if("ControlRight"!==e&&"ControlLeft"!==e){const s=this.#J.shortcuts.keyMap.get(e+(t.shiftKey?"1000":""));/^(redo|undo)$/.test(s?.command)&&(t.preventDefault(),t.stopPropagation(),this.#J.commandDispatcher.run(s.command,s.type,s.button))}}else if(!Fe.isRemoveKey(e)||(t.preventDefault(),t.stopPropagation(),"function"!=typeof this.currentPlugin?.componentDestroy||this.info.isInputType&&this.#t.get("hasFocus"))){if(Fe.isEnter(e)){t.preventDefault();const e=this.currentInfo||this.get(this.currentTarget),s=e.container||e.target,i=s.previousElementSibling||s.nextElementSibling;let n=null;n=Pe.check.isListCell(s.parentNode)?Pe.utils.createElement("BR"):Pe.utils.createElement(this.#J.format.isLine(i)?i.nodeName:this.#rt.get("defaultLine"),null,"
    ");const o=this.currentPluginName;return this.deselect(),s.parentNode.insertBefore(n,s),!1===this.select(e.target,o)&&this.#J.focusManager.blur(),void this.#J.history.push(!1)}if(Xi.lastIndex=0,Xi.test(e)){const{container:s}=this.get(this.currentTarget);let i=null,n=1;if(this.isInline(s||this.currentTarget))switch(e){case"ArrowLeft":i=s.previousSibling,n=3===i?.nodeType?i.textContent.length:1;break;case"ArrowRight":i=s.nextSibling,n=0;break;case"ArrowUp":{const t=this.#J.format.getLine(s,null);i=t?.previousElementSibling,n=0;break}case"ArrowDown":{const t=this.#J.format.getLine(s,null);i=t?.nextElementSibling;break}}else Zi.lastIndex=0,Zi.test(e)?i=s.previousElementSibling:(i=s.nextElementSibling,n=0);if(!i)return;this.deselect();const o=this.get(i);if(o?.container)t.stopPropagation(),t.preventDefault(),this.select(o.target,o.pluginName);else try{this.#t.set("_preventBlur",!0),t.stopPropagation(),t.preventDefault(),this.#J.selection.setRange(i,n,i,n)}finally{this.#t.set("_preventBlur",!1)}}else Fe.isEsc(e)&&this.deselect()}else{const t=this.info.container.previousSibling;if(await this.currentPlugin.componentDestroy(this.currentTarget),this.deselect(),t){const e=3===t.nodeType?t.textContent.length:1;this.#J.selection.setRange(t,e,t,e)}else this.#J.focusManager.focus()}}_destroy(){this.__removeGlobalEvent(),this.__removeDragEvent()}};const en=class{#H;#J;#Pi;#Ci;#rt;#Di;#Fi;#Hi=[];#qi=[];#Wi={tags:null,regExp:null,pluginRegExp:null,pluginMap:null};#Ui=[];#Vi=new Map;#ji=new Map([["onMouseMove",[]],["onMouseLeave",[]],["onMouseDown",[]],["onMouseUp",[]],["onScroll",[]],["onClick",[]],["onBeforeInput",[]],["onInput",[]],["onKeyDown",[]],["onKeyUp",[]],["onFocus",[]],["onBlur",[]],["onPaste",[]],["onFilePasteAndDrop",[]]]);constructor(t,e){this.#H=t,this.#J=t.$,this.#Pi=e.plugins||{},this.#Ci=this.#J.contextProvider,this.#rt=this.#J.options,this.#Di=e.pluginCallButtons,this.#Fi=e.pluginCallButtons_sub}get plugins(){return this.#Pi}get fileInfo(){return this.#Wi}findComponentInfo(t){for(const e of this.#Ui){const s=e(t);if(s)return s}return null}applyRetainFormat(t){let e;(e=this.#rt.get("__pluginRetainFilter"))&&this.#Vi.forEach(((s,i)=>{let n;try{n=t.querySelectorAll(i)}catch(t){return void console.warn(`[SUNEDITOR.retainFormat.fail]-[${s.key}]`,t.message)}for(let t=0,i=n.length;t{if("function"==typeof i[s]){const n=i[s].bind(i);n.index=e[`eventIndex_${s}`]||e.eventIndex||0,t.push(n)}})),i.retainFormat){const t=i.retainFormat();this.#Vi.set(t.query,{key:i.constructor.key,method:t.method})}}for(const t of this.#ji.values())t.sort(((t,e)=>t.index-e.index));(this.#rt.get("buttons").has("pageBreak")||this.#rt.get("buttons_sub")?.has("pageBreak"))&&this.#Ui.push(function(t,e,s){if(!s||!Pe.utils.hasClass(s,"se-page-break"))return null;return{target:s,launcher:{componentDestroy:s=>{const i=s.previousElementSibling||s.nextElementSibling;Pe.utils.removeItem(s),t.focusEdge(i),e.push(!1)}}}}.bind(null,this.#J.focusManager,this.#J.history)),this.#Wi.regExp=new RegExp(`^(${this.#Wi.tags.join("|")||"\\^"})$`,"i"),this.#Wi.pluginRegExp=new RegExp(`^(${0===s.length?"\\^":s.join("|")})$`,"i"),this.#Di=null,this.#Fi=null}get(t){return this.#Pi[t]}_destroy(){for(const t in this.#Pi){const e=this.#Pi[t];e._destroy?.(),e.editor=null}this.#Pi=null,this.#Wi=null,this.#Ui=null,this.#ji?.clear(),this.#Vi?.clear()}};class sn{#H;#J;#t;#rt;#X;#Q;constructor(t){this.#H=t,this.#J=t.$,this.#t=t.store,this.#rt=this.#J.options,this.#X=this.#J.frameContext,this.#Q=this.#J.frameOptions}focus(t){if(t&&this.#J.facade.changeFrameContext(t),"none"!==this.#X.get("wysiwygFrame").style.display){if(this.#t.set("_preventBlur",!1),this.#Q.get("iframe")||!this.#X.get("wysiwyg").contains(this.#J.selection.getNode()))this.nativeFocus();else try{const t=this.#J.selection.getRange();if(t.startContainer===t.endContainer&&Pe.check.isWysiwygFrame(t.startContainer)){const e=t.commonAncestorContainer.children[t.startOffset];if(!this.#J.format.isLine(e)&&!this.#J.component.is(e)){const t=Pe.utils.createElement("BR"),s=Pe.utils.createElement(this.#rt.get("defaultLine"),null,t);return this.#X.get("wysiwyg").insertBefore(s,e),void this.#J.selection.setRange(t,0,t,0)}}this.#J.selection.setRange(t.startContainer,t.startOffset,t.endContainer,t.endOffset)}catch(t){console.warn("[SUNEDITOR.focus.warn] ",t),this.nativeFocus()}this.#t.mode.isBalloon&&this.#H._eventOrchestrator._toggleToolbarBalloon()}}focusEdge(t){this.#t.set("_preventBlur",!1),t||=this.#X.get("wysiwyg").lastElementChild;const e=this.#J.component.get(t);e?this.#J.component.select(e.target,e.pluginName):t?(3!==t.nodeType&&(t=Pe.query.getEdgeChild(t,(function(t){return 0===t.childNodes.length||3===t.nodeType}),!0)),t?this.#J.selection.setRange(t,t.textContent.length,t,t.textContent.length):this.nativeFocus()):this.focus()}nativeFocus(){this.#J.selection.__focus(),this.#J.selection.init()}blur(){this.#Q.get("iframe")?this.#X.get("wysiwygFrame").blur():this.#X.get("wysiwyg").blur()}}const nn=/^H[1-6]$/,on=/^(UL|OL)$/,rn=/^LI$/,ln=/^(THEAD|TBODY|TR|TD|TH)$/;function an(t){let e=t;for(;e&&!tt(e);){if("TABLE"===e.nodeName)return e;e=e.parentNode}return null}function hn(t){let e=t;for(;e&&!tt(e);){if(1===e.nodeType&&Q(e))return!0;e=e.parentNode}return!1}function cn(t){let e=t,s=null;for(;e&&!tt(e);)1===e.nodeType&&Q(e)&&(s=e),e=e.parentNode;return s&&s.parentNode&&tt(s.parentNode)?s:null}function dn(t,e){const s=t.querySelector(":scope > ul, :scope > ol");if(!s)return null;if(e=r.top&&e<=r.bottom)return dn(s,e)||s;const l=Math.min(Math.abs(e-r.top),Math.abs(e-r.bottom));l=r.top&&e<=r.bottom)return dn(o,e)||o;const l=Math.min(Math.abs(e-r.top),Math.abs(e-r.bottom));l{this.#sn(),this.#in(),i?.()},subCheckMethod:t=>this.#Zi.has(t),subEscMethod:()=>{if(!this.#Ji)return!1;const t=this.#Ji.anchorLi;this.#sn();const e=t?Number(t.getAttribute("data-index")):NaN;return Number.isNaN(e)||this.selectMenu.setItem(e),!0}})}attach(t,e,s={}){this.selectMenu.on(t,e,s),this.#J.eventManager.addEvent(this.selectMenu.form,"mousedown",(t=>{Oe.isMobile||Pe.check.isInputElement(Pe.query.getEventTarget(t))?this.#J.store.set("_preventBlur",!0):t.preventDefault()})),this.#J.eventManager.addEvent(this.selectMenu.form,"mousemove",this.#nn.bind(this))}setItems(t){this.#Ki=Array.isArray(t)?t:[],this.#Yi=null}getItems(){if(this.#Yi)return this.#Yi;const t=[];for(const i of this.#Ki)if("string"==typeof i){const e=this.#Gi(i,this.#J.plugins,this.#J.options,this.#J.icons,this.#J.lang);if(!e)continue;const s=e.type||"";if(/dropdown-free/.test(s)){t.push({kind:"dropdownFree",title:e.title,iconHTML:e.icon||"",search:(e.title+" "+i).toLowerCase(),name:i,type:s});continue}if(/dropdown/.test(s)){const s=this.#J.menu?.itemsMap?.[i]||[];if(s.length>0){t.push({kind:"submenu",title:e.title,iconHTML:e.icon||"",search:(e.title+" "+i).toLowerCase(),name:i,children:s.map((t=>({pluginName:i,element:t._element}))),childMenus:s.map((t=>{const e=t._element?.querySelector(".se-list-icon")||t._element?.querySelector("svg"),s=e?e.outerHTML:"";return`${s?`${s}${t.title}`:t.title}`}))});continue}}t.push({kind:"plugin",title:e.title,iconHTML:e.icon||"",search:(e.title+" "+i).toLowerCase(),name:i,type:s,command:e.command})}else if(i&&"object"==typeof i&&"function"==typeof i.action){const n=i.title||i.key||"",o=Array.isArray(i.keywords)?i.keywords.join(" "):"";t.push({kind:"custom",title:n,iconHTML:(e=i.icon,s=this.#J.icons,e&&"string"==typeof e?"<"===e.charAt(0)?e:s[e]||"":""),search:(n+" "+o).toLowerCase(),raw:i})}var e,s;return this.#Yi=t,t}filter(t,e=1/0){const s=this.getItems(),i=(t||"").toLowerCase().trim(),n=[];for(const t of s)if(i&&-1===t.search.indexOf(i)||n.push(t),n.length>=e)break;return n}renderRows(t){const e={icons:this.#J.icons},s=`${this.#J.icons.menu_arrow_right}`;return t.map((t=>{if("custom"===t.kind&&this.#Xi)return this.#Xi(t.raw,e);const i=(n=t.title,``);var n,o;return"dropdownFree"===t.kind?i+s:i}))}createRows(t){this.#in();const e=t.map((t=>"submenu"===t.kind?{children:t.children,childMenus:t.childMenus}:t));this.selectMenu.create(e,this.renderRows(t)),this.#Zi.clear(),this.#tn.length=0,t.forEach(((t,e)=>{"dropdownFree"===t.kind&&this.#Zi.set(e,{name:t.name,plugin:this.#J.plugins[t.name],li:this.selectMenu.menus[e]}),"plugin"!==t.kind&&"dropdownFree"!==t.kind||this.#tn.push({name:t.name,idx:e})})),this.selectMenu.isOpen&&this.#on()}open(t){this.selectMenu.open(t),0===this.#en.length&&this.#on()}close(){this.#in(),this.selectMenu.close()}hasOpenSubPanel(){return this.selectMenu.hasOpenSubmenu()||!!this.#Ji}#on(){const t=this.#J.commandDispatcher;for(const{name:e,idx:s}of this.#tn){const i=this.#rn(s);i&&(t.registerTargets(e,i),this.#en.push({name:e,target:i}))}this.#J.store.set("_lastSelectionNode",null),this.#J.eventManager.applyTagEffect()}#in(){if(0===this.#en.length)return;const t=this.#J.commandDispatcher;for(const{name:e,target:s}of this.#en)t.unregisterTargets(e,s);this.#en.length=0}#rn(t){const e=this.selectMenu.menus[t];return e?e.querySelector("button.se-cmd-row")||e:null}setItem(t){this.selectMenu.setItem(t)}setHidden(t){this.selectMenu.setHidden(t)}get isOpen(){return this.selectMenu.isOpen}dispatch(t,e){if(!t)return!1;const s=t;if(s.pluginName&&s.element){const t=this.#J.plugins[s.pluginName];return t?.action?.(s.element),this.#J.history.push(!1),!0}const i=t;if("custom"===i.kind){try{i.raw.action(this.#J,e)}catch(t){console.error("[SUNEDITOR.commandMenu.customAction]",t)}return!1}if("dropdownFree"===i.kind){const t=this.#J.plugins[i.name];if(!t)return!1;if(this.#Ji?.plugin===t)return this.#sn(),!1;const e=this.selectMenu.items.indexOf(i),s=e>=0?this.selectMenu.menus[e]:null;return s&&this.#ln(i.name,t,s),!1}const n=i.name?this.#J.plugins[i.name]:null;if(n){const t=i.type||"";return/modal/.test(t)?n.open?.():/browser/.test(t)?n.open?.(null):/popup/.test(t)?n.show?.():n.action?.(Pe.utils.createElement("BUTTON",{type:"button","data-command":i.name})),this.#J.history.push(!1),!0}return i.command&&this.#J.commandDispatcher.run(i.command,null,null),!1}#nn(t){if(0===this.#Zi.size)return;const e=t.target;if(this.#Ji?.dropdown?.contains(e))return;const s=e.closest?.("li[data-index]");if(!s)return;const i=Number(s.getAttribute("data-index")),n=this.#Zi.get(i);n?this.#Ji?.plugin!==n.plugin&&this.#ln(n.name,n.plugin,n.li):this.#Ji&&this.#sn()}#ln(t,e,s){this.#Ji&&this.#sn();const i=this.#J.menu?.targetMap?.[t];if(!i||!this.selectMenu.form)return;const n=i.parentNode;this.selectMenu.form.appendChild(i),this.#an(i,s,this.selectMenu.form),Pe.utils.addClass(s,"se-submenu-open"),e.on?.(s);const o=this.#hn(i),r=this.#J.menu.subscribeDropdownOff((()=>{this.#sn(),this.selectMenu.close()}));this.#Ji={dropdown:i,plugin:e,originalParent:n,anchorLi:s,unsub:r,offCommit:o}}#hn(t){if(!this.#Qi)return()=>{};let e=!1;const s=t=>{if(e)return;const s=Pe.query.getEventTarget(t);Pe.check.isInputElement(s)||(e=!0,this.#Qi())};return t.addEventListener("mousedown",s,!0),t.addEventListener("keydown",s,!0),t.addEventListener("submit",s,!0),()=>{t.removeEventListener("mousedown",s,!0),t.removeEventListener("keydown",s,!0),t.removeEventListener("submit",s,!0)}}#sn(){const t=this.#Ji;t&&(this.#Ji=null,t.unsub?.(),t.offCommit?.(),t.dropdown.style.cssText="",t.dropdown.style.display="none",t.anchorLi&&Pe.utils.removeClass(t.anchorLi,"se-submenu-open"),t.originalParent&&t.originalParent!==t.dropdown.parentNode&&t.originalParent.appendChild(t.dropdown),t.plugin?.off?.())}#an(t,e,s){const i=e.getBoundingClientRect(),n=s.getBoundingClientRect(),o=!!this.#J.options.get("_rtl");t.style.position="absolute",t.style.right="",t.style.visibility="hidden",t.style.display="block";const r=t.offsetWidth,l=t.offsetHeight,a=pn.innerWidth,h=pn.innerHeight,c=i.right+4,d=i.left-r-4,u=Math.max(0,c+r-a),p=Math.max(0,-d);let g;g="right"===(o?"left":"right")?0===u?c:0===p?d:u<=p?c-u:d+p:0===p?d:0===u?c:p<=u?d+p:c-u,t.style.left=g-n.left+"px";const m=i.top,f=i.bottom-l,v=Math.max(0,m+l-h),b=Math.max(0,-f);let y;y=0===v?m:0===b?f:v<=b?m-v:f+b,t.style.top=y-n.top+"px",t.style.visibility=""}},{_w:mn,_d:fn}=Oe;const vn=class{#J;#cn;#dn;#un;#pn;#gn;#mn;#fn;#vn;#bn=null;#yn=null;#wn=null;#Cn=null;#_n=void 0;#kn=null;#xn=!1;#$n=void 0;#Sn=[];#En=!1;#Tn=null;#Mn=null;#Nn=null;#Bn=null;#In=null;constructor(t,e,s,i,n,o){this.#J=t,this.#cn=e,this.#dn=s,this.#un=i,this.#pn=n;const r=Array.isArray(o)?{menu:o}:o||{};this.#gn=r.menu||null,this.#mn="string"==typeof r.maxHeight?r.maxHeight:"",this.#fn="string"==typeof r.minWidth?r.minWidth:"200px",this.#vn="function"==typeof r.onPlusClick?r.onPlusClick:null,this.#J.contextProvider.carrierWrapper.appendChild(this.#dn);const l=this.#J.eventManager;l.addEvent(this.#dn,"mousedown",this.#Ln.bind(this)),this.#Tn=Pe.utils.createElement("DIV",{class:"se-block-drag-indicator"}),this.#Tn.style.display="none",this.#cn.parentElement?.appendChild(this.#Tn),l.addEvent(this.#un,"click",this.#An.bind(this)),this.#pn.draggable=!0,l.addEvent(this.#pn,"dragstart",this.#On.bind(this)),l.addEvent(this.#pn,"dragend",this.#Rn.bind(this)),l.addEvent(this.#pn,"click",this.#zn.bind(this)),l.addEvent(this.#cn,"mousemove",this.#Pn.bind(this)),l.addEvent(this.#cn,"mouseleave",this.#Dn.bind(this));const a=this.#cn.parentElement;a&&(l.addEvent(a,"mouseleave",this.#Fn.bind(this)),l.addEvent(a,"dragover",this.#Hn.bind(this)),l.addEvent(a,"drop",this.#qn.bind(this)))}#Wn(){this.#dn.style.display="flex";try{this.#dn.showPopover?.()}catch{}}#Un(){try{this.#dn.hidePopover?.()}catch{}this.#dn.style.display="none"}positionForTarget(t,e){if(this.#Vn(),this.#bn?.isOpen||this.#En)return;if(this.#xn){if(e===this.#$n)return;this.#xn=!1}const s=null!==this.#Cn;this.#Cn=t,this.#$n=e,this.#_n=e,s||(this.#wn=mn.requestAnimationFrame((()=>{this.#wn=null;const t=this.#Cn;this.#Cn=null,t&&this.#jn(t,this.#_n)})))}hide(t){if(this.#bn?.isOpen)return;const e=t?.relatedTarget;e&&(this.#cn.contains(e)||this.#dn?.contains(e))||this.#Gn()}hideNow(){this.#Vn(),this.#Un(),this.#bn?.close(),this.#Kn(null)}syncScroll(){this.#yn&&(Pe.utils.addClass(this.#dn,"se-no-transition"),this.#Yn(this.#yn),this.#dn.offsetHeight,Pe.utils.removeClass(this.#dn,"se-no-transition"),this.#bn?.isOpen&&this.#bn.setHidden("none"===this.#dn.style.display))}destroy(){this.#wn&&(mn.cancelAnimationFrame(this.#wn),this.#wn=null),this.#En=!1,this.#Vn(),this.#pn&&(this.#pn.draggable=!1),this.#Tn?.remove(),this.#dn?.remove(),this.#bn?.close(),this.#bn=null,this.#Kn(null),this.#Cn=null,this.#_n=void 0,this.#J=null,this.#cn=null,this.#dn=null,this.#un=null,this.#pn=null}#Kn(t){if(this.#Xn(),this.#yn=t,!t)return;const e=this.#Zn(t);if(e){this.#Sn=e;for(let t=0;tthis.#J.format.isLine(t)),null),o=n.indexOf(s),r=n.indexOf(i);if(-1===o||-1===r)return null;const l=n.slice(Math.min(o,r),Math.max(o,r)+1);return-1===l.indexOf(t)?null:l}catch{}return null}#Jn(t){this.#Xn(),this.#Sn=t||[];for(let t=0;t{this.#kn=null,this.#Un(),this.#bn?.close(),this.#Kn(null)}),200))}#Vn(){this.#kn&&(mn.clearTimeout(this.#kn),this.#kn=null)}#Pn(t){if(!this.#J)return;if(this.#En)return;if(this.#xn=!1,this.#Vn(),this.#bn?.isOpen)return;const e=this.#J.frameContext.get("wysiwyg");if(!e)return;const s=this.#J.frameContext.get("wysiwygFrame");let i;if(s&&"IFRAME"===s.nodeName){const e=s.getBoundingClientRect(),n=s.contentDocument;n&&(i=n.elementFromPoint(e.width/2,t.clientY-e.top))}else{const s=e.getBoundingClientRect();i=document.elementFromPoint(s.left+s.width/2,t.clientY)}i&&e.contains(i)&&this.#jn(i,t.clientY)}#Dn(t){this.#bn?.isOpen||this.#Qn(t?.relatedTarget)||this.hideNow()}#Fn(t){this.#bn?.isOpen||this.#Qn(t?.relatedTarget)||this.hideNow()}#Qn(t){if(!t)return!1;const e=this.#cn?.parentElement;return!(!this.#dn?.contains(t)&&!e?.contains(t))}#jn(t,e){if(!this.#J)return;const s=this.#J.format,i=this.#J.frameContext.get("wysiwyg");if(!i)return;let n=t;if(n===i&&void 0!==e){const t=i.getBoundingClientRect(),s=document.elementFromPoint(t.left+t.width/2,e);s&&i.contains(s)&&s!==i&&(n=s)}const o=function(t,e,s,i){if(!t||!s)return null;if(3===t.nodeType&&!(t=t.parentNode))return null;if(tt(t))return null;if(hn(t)){const s=cn(t);return s?un(s,e,i):null}let n=null;if(ln.test(t.nodeName))n=an(t);else if(on.test(t.nodeName))n=t;else if(rn.test(t.nodeName))n=t;else if(X(t.parentNode))n=an(t);else{const s=e.getLine(t,null);if(s&&(n=s),!n){const s=e.getBlock(t,null);s&&(n=ln.test(s.nodeName)?an(s):s)}}if(!n){let e=t;for(;e&&!tt(e);){if(1===e.nodeType&&e.parentNode&&tt(e.parentNode)){n=e;break}e=e.parentNode}}if(!n)return null;if(hn(n)){const t=cn(n);return t?un(t,e,i):null}return un(n,e,i)}(n,{getLine:(t,e)=>s.getLine(t,e),getBlock:(t,e)=>s.getBlock(t,e),isLine:t=>s.isLine(t),isBlock:t=>s.isBlock(t)},i,e);if(o){if(o.element!==this.#yn||"flex"!==this.#dn.style.display){if(this.#yn?.isConnected&&"flex"===this.#dn.style.display&&void 0!==e&&!this.#yn.contains(o.element)){const t=this.#yn.getBoundingClientRect();if(e>=t.top&&e<=t.bottom)return}this.#Kn(o.element),this.#Yn(o.element)}}else this.#Gn()}#Yn(t){if(!t.isConnected)return void this.hideNow();const e=t.getBoundingClientRect(),s=this.#cn.getBoundingClientRect(),i=this.#J.frameContext.get("wysiwygFrame"),n=/^iframe$/i.test(i.nodeName),o=n?i.getBoundingClientRect():null;if(n){const t=i.clientHeight||0;if(e.bottom<=0||e.top>=t)return void this.#Un()}else{const t=i.getBoundingClientRect();if(e.bottom<=t.top||e.top>=t.bottom)return void this.#Un()}const r=mn.scrollX,l=mn.scrollY,a="flex"!==this.#dn.style.display;a&&(Pe.utils.addClass(this.#dn,"se-no-transition"),this.#dn.style.display="flex");const h=this.#dn.offsetHeight||0,c=this.#to(t,e),d=n?c+o.top:c,u=d+l-h/2,p=!!this.#J.options.get("_rtl"),g=this.#eo(t,p);let m=0;if(this.#J.frameOptions.get("innerWidth")){const t=this.#J.frameContext.get("wysiwyg");if(t){const e=mn.getComputedStyle(t),s=De.get(p?e.paddingRight:e.paddingLeft,-1)||0,i=function(t,e){const s=(t||"").trim(),i=De.get(s,-1);return i?/rem$/.test(s)?i*(De.get(mn.getComputedStyle(fn.documentElement).fontSize,-1)||16):/em$/.test(s)?i*(De.get(e.fontSize,-1)||16):i:0}(e.getPropertyValue("--se-edit-inner-padding"),e);m=Math.max(0,s-i)}}const f=g+m,v=this.#J.context?.get("toolbar_main");if(v){const t=v.getBoundingClientRect(),e=this.#dn.offsetWidth||0,i=d-h/2,n=p?s.right-f-e:s.left+f;if(t.height>0&&it.top+1&&nt.left)return void this.#Un()}this.#dn.style.top=u+"px",p?(this.#dn.style.left="",this.#dn.style.right=mn.innerWidth-s.right-r+f+"px"):(this.#dn.style.right="",this.#dn.style.left=s.left+r+f+"px"),this.#Wn(),a&&(this.#dn.offsetHeight,Pe.utils.removeClass(this.#dn,"se-no-transition"))}#to(t,e){try{const e=t.ownerDocument,s=e.createTreeWalker(t,NodeFilter.SHOW_TEXT,null);let i=null;for(;(i=s.nextNode())&&!i.textContent?.trim(););if(i){const t=e.createRange();t.setStart(i,0),t.setEnd(i,Math.min(1,i.length));const s=t.getClientRects();if(s.length)return(s[0].top+s[0].bottom)/2}}catch{}const s=De.get(mn.getComputedStyle(t).lineHeight,-1)||e.height;return e.top+Math.min(s,e.height)/2}#eo(t,e){const s=this.#J.frameContext.get("wysiwyg");if(!s)return 0;const i=this.#J.format,n=e?"marginRight":"marginLeft",o=e?"paddingRight":"paddingLeft";let r=0;r+=De.get(mn.getComputedStyle(t)[n],-1)||0;let l=t.parentElement;for(;l&&l!==s;){if(i.isBlock(l)){const t=mn.getComputedStyle(l);r+=(De.get(t[o],-1)||0)+(De.get(t[n],-1)||0)}l=l.parentElement}return r}#so(){if(!this.#yn)return;const t=this.#yn,e=this.#Zn(t),s=e?e[0]:t,i=e?e[e.length-1]:t;this.#J.selection.setRange(s,0,i,i.childNodes.length)}#An(t){if(t.preventDefault(),t.stopPropagation(),!this.#yn)return;const e=this.#J.format.addLineAfter(this.#yn);e&&(this.#J.selection.setRange(e,1,e,1),this.#J.history.push(!1),this.#vn&&(this.#Kn(e),this.#Yn(e),this.#vn(this.#J,{block:e,openMenu:()=>this.#io()})))}#Ln(t){const e=this.#pn&&(t.target===this.#pn||this.#pn.contains(t.target));Oe.isMobile?this.#J.store.set("_preventBlur",!0):e||t.preventDefault()}hideOnKeyDown(){this.#bn?.isOpen||(this.#xn=!0,this.hideNow())}#On(t){if(!this.#yn)return void t.preventDefault();this.#Mn=this.#yn,this.#En=!0,this.#bn?.close(),Pe.utils.addClass(this.#Mn,"se-block-dragging");const e=this.#J.frameContext.get("wysiwyg");this.#Bn=e||null,this.#In=e?Array.from(e.children):null;const s=!!this.#J.options.get("_rtl"),i=this.#Mn;t.dataTransfer.setDragImage(i,s?i.offsetWidth:-5,-5),t.dataTransfer.effectAllowed="move",t.dataTransfer.setData("application/x-suneditor-block-drag","1")}#Hn(t){this.#En&&(t.preventDefault(),t.stopPropagation(),t.dataTransfer.dropEffect="move",this.#no(t.clientY))}#qn(t){this.#En&&(t.preventDefault(),t.stopPropagation(),this.#oo())}#Rn(){if(this.#Mn&&Pe.utils.removeClass(this.#Mn,"se-block-dragging"),this.#Tn.style.display="none",this.#En=!1,this.#Mn=null,this.#Nn=null,this.#Bn=null,this.#In=null,this.#pn?.parentNode){const t=this.#pn.parentNode,e=this.#pn.nextSibling;t.removeChild(this.#pn),t.insertBefore(this.#pn,e)}}#no(t){if(!this.#J||!this.#Mn)return;const e=this.#Bn,s=this.#In;if(!e||!s)return;const i=e.getBoundingClientRect(),n=this.#cn.parentElement.getBoundingClientRect();let o=null,r="after",l=0,a=1/0;for(let e=0;e0&&this.#Jn(t);const e=this.#J.offset.getGlobal(this.#pn),s=Pe.utils.getClientSize().h-(e.top-mn.scrollY+e.height),i=e.top-mn.scrollY,n=`${this.#J.options.get("_rtl")?"left":"right"}-${s>=i?"bottom":"top"}`;this.#bn.open(n)}#ro(){const t=new gn(this,this.#J,{items:this.#gn,resolveButton:us,selectMenuParams:{position:"right-top",dir:this.#J.options.get("_rtl")?"rtl":"ltr",minWidth:this.#fn,maxHeight:this.#mn,keydownTarget:mn,closeMethod:()=>{Pe.utils.removeClass(this.#pn,"on"),this.#Xn()},openMethod:()=>{Pe.utils.addClass(this.#pn,"on")}}});return t.attach(this.#pn,this.#lo.bind(this),{class:"se-block-action-menu"}),t.createRows(t.getItems()),t}#lo(t){this.#yn&&this.#J&&t&&(this.#bn?.dispatch(t,{block:this.#yn}),"dropdownFree"!==t.kind&&this.#bn?.close())}},{NO_EVENT:bn}=Oe,yn={bold:["font-weight"],underline:["text-decoration"],italic:["font-style"],strike:["text-decoration"]};class wn{#H;#J;#t;#X;#rt;#_i;#ao=null;#ho=null;#co=null;#do=null;constructor(t){this.#H=t,this.#J=t.$,this.#t=t.store,this.#X=this.#J.frameContext,this.#rt=this.#J.options,this.#_i=this.#J.eventManager}async execute(t,e){if(!this.#X.get("isReadOnly")||/copy|cut|selectAll|selectAll_full|codeView|markdownView|fullScreen|print|preview|showBlocks|finder/.test(t))switch(t){case"selectAll":this.#uo();break;case"selectAll_full":this.#po();break;case"copy":{const t=this.#J.selection.getRange();if(t.collapsed)break;const e=Pe.utils.createElement("div",null,t.cloneContents());await this.#J.html.copy(e.innerHTML);break}case"newDocument":this.#J.html.set(`<${this.#rt.get("defaultLine")}>
    `),this.#J.focusManager.focus(),this.#J.history.push(!1),this.#X.has("documentType_use_header")&&this.#X.get("documentType").reHeader();break;case"finder":this.#J.finder.isOpen?this.#J.finder.close():this.#J.finder.open(!0);break;case"codeView":this.#J.viewer.codeView(!this.#X.get("isCodeView"));break;case"markdownView":this.#J.viewer.markdownView(!this.#X.get("isMarkdownView"));break;case"fullScreen":this.#J.viewer.fullScreen(!this.#X.get("isFullScreen"));break;case"indent":this.#J.format.indent();break;case"outdent":this.#J.format.outdent();break;case"undo":this.#J.history.undo();break;case"redo":this.#J.history.redo();break;case"removeFormat":this.#J.inline.remove(),this.#J.focusManager.focus();break;case"print":this.#J.viewer.print();break;case"preview":this.#J.viewer.preview();break;case"showBlocks":this.#J.viewer.showBlocks(!this.#X.get("isShowBlocks"));break;case"dir":this.#J.ui.setDir(this.#rt.get("_rtl")?"ltr":"rtl");break;case"dir_ltr":this.#J.ui.setDir("ltr");break;case"dir_rtl":this.#J.ui.setDir("rtl");break;case"save":await this.#go();break;case"copyFormat":this.#mo(e);break;case"pageBreak":this.#fo();break;case"pageUp":this.#X.get("documentType").pageUp();break;case"pageDown":this.#X.get("documentType").pageDown();break;default:this.#vo(t)}}copyFormat(){if(this.#co?.length)try{const t=[...this.#co],e=t.pop();if(this.#J.inline.remove(),e){const s=this.#J.inline.apply(e,{stylesToModify:null,nodesToRemove:[e.nodeName],strictRemove:!1}),{parent:i,inner:n}=this.#J.nodeTransform.createNestedNode(t);s.parentNode.insertBefore(i,s),n.appendChild(s),this.#J.selection.setRange(s,Pe.check.isZeroWidth(s)?1:0,s,1)}if(this.#rt.get("copyFormatKeepOn"))return;this.#do()}catch(t){console.warn("[SUNEDITOR.copyFormat.error] ",t),this.#do?.()||(this.#co=null,this.#do=null)}}#uo(){this.#J.ui.offCurrentController(),this.#J.menu.containerOff();const t=this.#X.get("wysiwyg");let e=null,s="";const i=this.#rt.get("scopeSelectionTags"),n=this.#J.selection.getRange();if(!n.collapsed){let o=e=n.commonAncestorContainer,r=s=o.nodeName?.toLowerCase();if(0===n.startOffset&&n.endOffset===n.endContainer.textContent?.length){const t=o.parentElement;(Pe.check.isList(t)||Pe.check.isListCell(t))&&t.firstChild.contains?.(n.startContainer)&&t.lastChild?.contains(n.endContainer)&&(e=o=t.parentElement,s=o.nodeName?.toLowerCase())}for(r=o.nodeName?.toLowerCase();o&&(!o.nextSibling&&!o.previousSibling&&!i.includes(r)||Pe.check.isContentLess(r))&&o!==t;)o=o.parentElement,r=o.nodeName?.toLowerCase();i.includes(r)&&(e=o,s=r)}const o=i.filter((t=>t!==s));let r=Pe.query.getParentElement(e||this.#J.selection.getNode(),(t=>o.includes(t.nodeName?.toLowerCase())))||t,{first:l,last:a}=Cn(r);if(!l||!a)return;const h=Pe.check.isZeroWidth;for(;h(l)&&h(a)&&r!==t;)r=r.parentElement,({first:l,last:a}=Cn(Pe.query.getParentElement(r,(t=>o.includes(t.nodeName?.toLowerCase())))||t));if(!l||!a)return;let c=null;if(Pe.check.isMedia(l)||(c=this.#J.component.get(l))||Pe.check.isTableElements(l)){c||=this.#J.component.get(l);const t=Pe.utils.createElement("BR"),e=Pe.utils.createElement(this.#rt.get("defaultLine"),null,t);l=c?c.container||c.cover:l,l.parentElement.insertBefore(e,l),l=t}if(Pe.check.isMedia(a)||(c=this.#J.component.get(a))||Pe.check.isTableElements(a)){c||=this.#J.component.get(a);const t=Pe.utils.createElement("BR"),e=Pe.utils.createElement(this.#rt.get("defaultLine"),null,t);a=c?c.container||c.cover:a,a.parentElement.appendChild(e),a=t}this.#J.toolbar._showBalloon(this.#J.selection.setRange(l,0,a,a.textContent.length))}#po(){this.#J.ui.offCurrentController(),this.#J.menu.containerOff();const t=this.#X.get("wysiwyg");let{first:e,last:s}=Cn(t);if(!e||!s)return;let i=null;if(Pe.check.isMedia(e)||(i=this.#J.component.get(e))||Pe.check.isTableElements(e)){i||=this.#J.component.get(e);const t=Pe.utils.createElement("BR"),s=Pe.utils.createElement(this.#rt.get("defaultLine"),null,t);e=i?i.container||i.cover:e,e.parentElement.insertBefore(s,e),e=t}if(Pe.check.isMedia(s)||(i=this.#J.component.get(s))||Pe.check.isTableElements(s)){i||=this.#J.component.get(s);const t=Pe.utils.createElement("BR"),e=Pe.utils.createElement(this.#rt.get("defaultLine"),null,t);s=i?i.container||i.cover:s,s.parentElement.appendChild(e),s=t}this.#J.toolbar._showBalloon(this.#J.selection.setRange(e,0,s,s.textContent.length))}async#go(){const t=this.#X;if(!t.get("isChanged"))return;const e=this.#J.html.get(),s=await this.#_i.triggerEvent("onSave",{frameContext:t,data:e});if(s===bn){const s=t.get("originElement");/^TEXTAREA$/i.test(s.nodeName)?s.value=e:s.innerHTML=e}else if(!1===s)return;t.set("isChanged",!1),t.set("savedIndex",this.#J.history.getRootStack()[this.#t.get("rootKey")].index),this.#J.commandDispatcher.applyTargets("save",(t=>{t.disabled=!0}))}#mo(t){if("function"==typeof this.#do)return void this.#do();const e=this.#X.get("wysiwyg");this.#co=[...this.#H._eventOrchestrator.__cacheStyleNodes],this.#do=this.#bo.bind(this,this.#_i,e,t),Pe.utils.addClass(e,"se-copy-format-cursor"),Pe.utils.addClass(t,"on"),this.#ao=this.#_i.addGlobalEvent("keydown",(t=>{Fe.isEsc(t.code)&&this.#do?.()})),this.#ho=this.#_i.addGlobalEvent("mousedown",(s=>{e.contains(s.target)||s.target===t||this.#do?.()}))}#bo(t,e,s){return this.#ao=t.removeGlobalEvent(this.#ao),this.#ho=t.removeGlobalEvent(this.#ho),this.#co=null,this.#do=null,Pe.utils.removeClass(e,"se-copy-format-cursor"),Pe.utils.removeClass(s,"on"),!0}#vo(t){t=this.#rt.get("_defaultTagCommand")[t.toLowerCase()]||t;let e=this.#rt.get("convertTextTags")[t]||t;const s=this.#t.get("currentNodesMap"),i=s.includes(this.#rt.get("_styleCommandMap")[e])?null:Pe.utils.createElement(e);/^sub$/i.test(e)&&s.includes("superscript")?e="sup":/^sup$/i.test(e)&&s.includes("subscript")&&(e="sub"),this.#J.inline.apply(i,{stylesToModify:yn[t]||null,nodesToRemove:[e],strictRemove:!1}),this.#J.focusManager.focus()}#fo(){const t=Pe.utils.createElement("DIV",{class:"se-component se-component-line-break se-page-break"});this.#J.component.insert(t,{skipCharCount:!0,insertBehavior:"line"});const e=t.nextElementSibling||this.#J.format.addLine(t);this.#J.selection.setRange(e,1,e,1),this.#J.history.push(!1)}}const Cn=function(t){const e=Pe.check.isContentLess;return{first:Pe.query.getEdgeChild(Pe.query.getEdgeChild(t,(t=>!e(t)),!1),(t=>0===t.childNodes.length||3===t.nodeType||Y(t)||K(t)),!1)||t.firstChild,last:Pe.query.getEdgeChild(t.lastChild,(t=>0===t.childNodes.length||3===t.nodeType||Y(t)||K(t)),!0)||t.lastChild}},_n=".se-menu-list .se-toolbar-btn[data-command]",kn=["bold","underline","italic","strike","subscript","superscript","indent","outdent"],xn=kn.concat(["undo","redo","save","fullScreen","showBlocks","codeView","markdownView","finder","dir","dir_ltr","dir_rtl"]);class $n{#J;#e;#rt;#yo;#wo=new Map;#Co=kn;constructor(t){this.#J=t.$,this.#e=this.#J.context,this.#rt=this.#J.options,this.#yo=new wn(t),this.allCommandButtons=new Map,this.subAllCommandButtons=new Map}get targets(){return this.#wo}get activeCommands(){return this.#Co}run(t,e,s){if(e){if(/more/i.test(e)){const e=Pe.query.getParentElement(s,".se-toolbar"),i=Pe.utils.hasClass(e,"se-toolbar-sub")?this.#J.subToolbar:this.#J.toolbar;if(s!==i.currentMoreLayerActiveButton){const n=e.querySelector("."+t);n&&(i._moreLayerOn(s,n),i._showBalloon(),i._showInline()),Pe.utils.addClass(s,"on")}else i.currentMoreLayerActiveButton&&(i._moreLayerOff(),i._showBalloon(),i._showInline());return void this.#J.viewer._resetFullScreenHeight()}if(/container/.test(e)&&(null===this.#J.menu.targetMap[t]||s!==this.#J.menu.currentContainerActiveButton))return void this.#J.menu.containerOn(s);if(this.#J.ui.isButtonDisabled(s))return;if(/dropdown/.test(e)&&(null===this.#J.menu.targetMap[t]||s!==this.#J.menu.currentDropdownActiveButton))return void this.#J.menu.dropdownOn(s);if(/modal/.test(e))return void this.#J.plugins[t].open(s);/command/.test(e)?this.#J.plugins[t].action(s):/browser/.test(e)?this.#J.plugins[t].open(null):/popup/.test(e)&&this.#J.plugins[t].show()}else t&&this.#yo.execute(t,s);/dropdown/.test(e)?this.#J.menu.dropdownOff():/command/.test(e)||(this.#J.menu.dropdownOff(),this.#J.menu.containerOff())}runFromTarget(t){if(Pe.check.isInputElement(t))return;const e=Pe.query.getCommandTarget(t);if(!e)return;const s=e.getAttribute("data-command"),i=e.getAttribute("data-type");(s||i)&&(e.disabled||this.run(s,i,t))}applyTargets(t,e){this.#wo.has(t)&&this.#wo.get(t).forEach(e)}registerTargets(t,e){if(!t||!e)return;(xn.includes(t)||this.#J.plugins[t])&&(this.#wo.get(t)?this.#wo.get(t).includes(e)||this.#wo.get(t).push(e):this.#wo.set(t,[e]))}unregisterTargets(t,e){const s=this.#wo.get(t);if(!s)return;const i=s.indexOf(e);-1!==i&&s.splice(i,1),0===s.length&&this.#wo.delete(t)}resetTargets(){this.#wo=new Map,this._initCommandButtons()}_initCommandButtons(){const t=this.#e;this.#_o(this.allCommandButtons,t.get("toolbar_buttonTray")),this.#_o(this.subAllCommandButtons,t.get("toolbar_sub_buttonTray"))}_copyFormat(){this.#yo.copyFormat()}#_o(t,e){if(!e)return;const s=e.querySelectorAll(_n),i=this.#rt.get("shortcuts"),n=this.#rt.get("_reverseCommandArray"),o=this.#J.shortcuts.keyMap,r=this.#J.shortcuts.reverseKeys;for(let e,l,a=0,h=s.length;a'+e.cancel+"
    ";return Pe.utils.createElement("DIV",{class:"se-alert-content"},s)}(this.#Ci);this.alertModal=e,this.alertMessage=e.querySelector("span");const s=function(){const t='
    ';return Pe.utils.createElement("DIV",{class:"se-toast"},t)}();s.setAttribute("popover","manual"),this.toastPopup=s,this.toastContainer=s.querySelector(".se-toast-container"),this.toastMessage=s.querySelector("span"),this.#ot.appendChild(s),this.#ko=this.#ot.querySelector(".se-alert"),this.#xo=this.#ot.querySelector(".se-alert .se-modal-inner"),this.#xo.appendChild(e),this.#$o=[this.#Do.bind(this),this.#Fo.bind(this)],this.#So=!1,this.#To=this.#ot.querySelector(".se-back-wrapper"),this.opendControllers=[],this.controllerTargetContext=null,this._figureContainer=null}get selectMenuOn(){return this.#Po.size>0}setSelectMenuOpen(t,e){e?this.#Po.add(t):this.#Po.delete(t)}setEditorStyle(t,e){e||=this.#X;const s=e.get("options");s.set("editorStyle",t);const i=ze._setDefaultOptionStyle(s,t);s.set("_defaultStyles",i),e.get("topArea").style.cssText=i.top;const n=e.get("code");if(this.#rt.get("hasCodeMirror")){const t=s.get("_defaultStyles").frame.split(";");for(let e,s=0,i=t.length;s{e&&(s&&Pe.utils.removeClass(e,s),t&&Pe.utils.addClass(e,t))};i(this.#ot),this.#Ci.applyToRoots((t=>{i(t.get("topArea")),i(t.get("wysiwyg"))})),i(this.#e.get("statusbar_wrapper")),i(this.#e.get("toolbar_wrapper"))}setDir(t){const e="rtl"===t;if(this.#rt.get("_rtl")===e)return;const s=this.#rt.get("textDirection"),i=this.#rt.get("_editableClass"),n=this.#rt.get("printClass");try{this.#rt.set("_rtl",e),this.#rt.set("textDirection",t);const s=e?this.#rt.get("_editableClass").replace(/\s*se-rtl/,"")+" se-rtl":this.#rt.get("_editableClass").replace(/\s*se-rtl/,"");this.#rt.set("_editableClass",s),this.#rt.get("printClass")&&this.#rt.set("printClass",e?this.#rt.get("printClass").replace(/\s*se-rtl/,"")+" se-rtl":this.#rt.get("printClass").replace(/\s*se-rtl/,"")),this.offCurrentController();const i=this.#X,n=this.#J.pluginManager.plugins;for(const e in n)n[e].setDir?.(t);const o=this.#e.get("toolbar_wrapper"),r=this.#e.get("statusbar_wrapper");e?(this.#Ci.applyToRoots((t=>{Pe.utils.addClass([t.get("topArea"),t.get("wysiwyg"),t.get("documentTypePageMirror")],"se-rtl"),t.get("wysiwyg").dir="rtl"})),Pe.utils.addClass([this.#ot,o,r],"se-rtl")):(this.#Ci.applyToRoots((t=>{Pe.utils.removeClass([t.get("topArea"),t.get("wysiwyg"),t.get("documentTypePageMirror")],"se-rtl"),t.get("wysiwyg").removeAttribute("dir")})),Pe.utils.removeClass([this.#ot,o,r],"se-rtl"));const l=Pe.query.getListChildren(i.get("wysiwyg"),(t=>this.#J.format.isLine(t)&&!!(t.style.marginRight||t.style.marginLeft||t.style.textAlign)),null);for(let t,e,s,i=0;t=l[i];i++)t=l[i],s=t.style.marginRight,e=t.style.marginLeft,(s||e)&&(t.style.marginRight=e,t.style.marginLeft=s),s=t.style.textAlign,"left"===s?t.style.textAlign="right":"right"===s&&(t.style.textAlign="left");this.#Ho(e),this.#t.mode.isBalloon?this.#J.toolbar._showBalloon():this.#t.mode.isSubBalloon&&this.#J.subToolbar._showBalloon()}catch(t){this.#rt.set("_rtl",!e),this.#rt.set("textDirection",s),this.#rt.set("_editableClass",i),null!==n&&this.#rt.set("printClass",n),console.warn(`[SUNEDITOR.ui.setDir.fail] ${t.toString()}`)}this.#t.set("_lastSelectionNode",null),this.#H._eventOrchestrator.applyTagEffect()}readOnly(t,e){const s=e?this.#O.get(e):this.#X;s.set("isReadOnly",!!t),this._toggleControllerButtons(!!t),t?(this.offCurrentController(),this.offCurrentModal(),this.#J.toolbar?.currentMoreLayerActiveButton?.disabled&&this.#J.toolbar._moreLayerOff(),this.#J.subToolbar?.currentMoreLayerActiveButton?.disabled&&this.#J.subToolbar._moreLayerOff(),this.#J.menu?.currentDropdownActiveButton?.disabled&&this.#J.menu.dropdownOff(),this.#J.menu?.currentContainerActiveButton?.disabled&&this.#J.menu.containerOff(),s.get("code").setAttribute("readOnly","true"),Pe.utils.addClass(s.get("wysiwyg"),"se-read-only")):(s.get("code").removeAttribute("readOnly"),Pe.utils.removeClass(s.get("wysiwyg"),"se-read-only")),this.#rt.get("hasCodeMirror")&&this.#J.viewer._codeMirrorEditor("readonly",!!t,e)}disable(t){const e=t?this.#O.get(t):this.#X;this.#J.toolbar.disable(),this.offCurrentController(),this.offCurrentModal(),e.get("wysiwyg").setAttribute("contenteditable","false"),e.set("isDisabled",!0),this.#rt.get("hasCodeMirror")?this.#J.viewer._codeMirrorEditor("readonly",!0,t):e.get("code").disabled=!0}enable(t){const e=t?this.#O.get(t):this.#X;this.#J.toolbar.enable(),e.get("wysiwyg").setAttribute("contenteditable","true"),e.set("isDisabled",!1),this.#rt.get("hasCodeMirror")?this.#J.viewer._codeMirrorEditor("readonly",!1,t):e.get("code").disabled=!1}show(t){const e=(t?this.#O.get(t):this.#X).get("topArea").style;"none"===e.display&&(e.display="block")}hide(t){(t?this.#O.get(t):this.#X).get("topArea").style.display="none"}showLoading(t){const e=(t?this.#O.get(t).get("container"):this.#ot).querySelector(".se-loading-box");e.style.display="block",e.showPopover?.()}hideLoading(t){const e=(t?this.#O.get(t).get("container"):this.#ot).querySelector(".se-loading-box");e.hidePopover?.(),e.style.display="none"}alertOpen(t,e){this.alertMessage.textContent=t,Pe.utils.removeClass(this.alertModal,"se-alert-error|se-alert-success"),e&&Pe.utils.addClass(this.alertModal,`se-alert-${e}`),this.#So&&(this.#Eo=this.#_i.addEvent(this.#xo,"click",this.#$o[1])),this.#No&&=this.#_i.removeGlobalEvent(this.#No),this.#No=this.#_i.addGlobalEvent("keydown",this.#$o[0]),this.#ko.style.display="block",this.#ko.showPopover?.(),Pe.utils.addClass(this.alertModal,"se-modal-show")}alertClose(){Pe.utils.removeClass(this.alertModal,"se-modal-show"),Pe.utils.removeClass(this.alertModal,"se-alert-*"),this.#ko.hidePopover?.(),this.#ko.style.display="none",this.#Eo&&=this.#_i.removeEvent(this.#Eo),this.#No&&=this.#_i.removeGlobalEvent(this.#No)}showToast(t,e=1e3,s){Pe.utils.hasClass(this.toastContainer,"se-toast-show")&&this.closeToast(),Pe.utils.removeClass(this.toastPopup,"se-toast-error|se-toast-success"),s&&Pe.utils.addClass(this.toastPopup,`se-toast-${s}`),this.toastPopup.style.display="block",this.toastPopup.showPopover?.(),this.toastMessage.textContent=t,Pe.utils.addClass(this.toastContainer,"se-toast-show"),this.#Bo=Tn.setTimeout((()=>{this.closeToast()}),e)}closeToast(){this.#Bo&&Tn.clearTimeout(this.#Bo),this.#Bo=null,Pe.utils.removeClass(this.toastContainer,"se-toast-show"),this.toastPopup.hidePopover?.(),this.toastPopup.style.display="none"}setControllerOnDisabledButtons(t){return t&&!this.#Mo?(this._toggleControllerButtons(!0),this.#Mo=!0):!t&&this.#Mo&&(this._toggleControllerButtons(!1),this.#Mo=!1),this.#Mo}onControllerContext(){this.controllerTargetContext=this.#X.get("topArea")}offControllerContext(){this.controllerTargetContext=null}enableBackWrapper(t){this.#To.style.cursor=t,this.#To.style.display="block",this.#To.showPopover?.()}disableBackWrapper(){this.#To.hidePopover?.(),this.#To.style.display="none",this.#To.style.cursor="default"}offCurrentController(){this.#J.component.__deselect()}offCurrentModal(){this.opendModal?.close()}getVisibleFigure(){return"block"===this._figureContainer?.style.display?this._figureContainer:null}setFigureContainer(t){this._figureContainer=t}preventToolbarHide(t){this.#Ao=t}get isPreventToolbarHide(){return this.#Ao}get blockHandle(){return this.#zo}reset(t){t.set("_editorHeight",t.get("wysiwygFrame").offsetHeight),this.#Oo=t.get("lineBreaker_t"),this.#Ro=t.get("lineBreaker_b");const e=this.#rt.get("blockHandle");e&&t.get("blockHandleArea")&&!this.#zo&&(this.#zo=new vn(this.#J,t.get("blockHandleArea"),t.get("blockHandle"),t.get("blockHandlePlus"),t.get("blockHandleDrag"),e))}_offControllers(){const t=this.opendControllers,e=[];for(let s,i=0;i{const e=i?.get(t);e&&([e.command,e.r]=[e.r,e.command])})),this.#J.commandDispatcher.applyTargets("dir",(s=>{Pe.utils.changeTxt(s.querySelector(".se-tooltip-text"),this.#Ci.lang[t?"dir_ltr":"dir_rtl"]),Pe.utils.changeElement(s.firstElementChild,e[t?"dir_ltr":"dir_rtl"])})),t?(Pe.utils.addClass(s.get("dir_rtl"),"active"),Pe.utils.removeClass(s.get("dir_ltr"),"active")):(Pe.utils.addClass(s.get("dir_ltr"),"active"),Pe.utils.removeClass(s.get("dir_rtl"),"active"))}_initToggleButtons(){const t=this.#e;this.#Lo=ze.nodeListToArray(t.get("toolbar_buttonTray").querySelectorAll(Sn)),this.#Io=ze.nodeListToArray(t.get("toolbar_buttonTray").querySelectorAll(En)),this.#rt.has("_subMode")&&(this.#Lo=this.#Lo.concat(ze.nodeListToArray(t.get("toolbar_sub_buttonTray").querySelectorAll(Sn))),this.#Io=this.#Io.concat(ze.nodeListToArray(t.get("toolbar_sub_buttonTray").querySelectorAll(En))))}_toggleCodeViewButtons(t){Pe.utils.setDisabled(this.#Lo,t)}_toggleControllerButtons(t){Pe.utils.setDisabled(this.#Io,t)}isButtonDisabled(t){return!(!this.#X.get("isReadOnly")||!Pe.utils.arrayIncludes(this.#Io,t))}_updatePlaceholder(t){t||=this.#X;const e=t.get("isMarkdownView")||t.get("isCodeView"),s=!e&&this.#Wo(t),i=t.get("placeholder");i&&(i.style.display=e||s||!this.#J.facade.isEmpty(t)?"none":"block")}resolveLinePlaceholder(t,e){if(!t||!e)return"";if("object"!=typeof e)return Pe.check.isListCell(t)||Pe.query.getParentElement(t,Pe.check.isTableCell)?"":e;const s=this.#J.format,i=t.nodeName.toLowerCase();if("string"==typeof e[i])return e[i];if(Pe.check.isListCell(t)&&"string"==typeof e["@list"])return e["@list"];if(s.isClosureBrLine(t)&&"string"==typeof e["@closureBrLine"])return e["@closureBrLine"];if(s.isBrLine(t)&&"string"==typeof e["@brLine"])return e["@brLine"];const n=s.getBlock(t);if(n&&n!==t){const t=n.nodeName.toLowerCase();if("string"==typeof e[t])return e[t];if(s.isClosureBlock(n)&&"string"==typeof e["@closureBlock"])return e["@closureBlock"];if("string"==typeof e["@block"])return e["@block"]}return s.isNormalLine(t)&&"string"==typeof e["@normalLine"]?e["@normalLine"]:"string"==typeof e["@line"]?e["@line"]:""}#Wo(t){const e=t.get("placeholder_line");if(!e)return!1;const s=t.get("wysiwyg"),i=this.#t.get("hasFocus")?this.#J.format.getLine(this.#J.selection.selectionNode):null,n=Pe.check.isEmptyLine(i)?this.resolveLinePlaceholder(i,e):"",o=n?i:null,r=s.querySelectorAll(".se-placeholder-line");for(let t=0;t{const s=e.offsetHeight,i=t.get("wysiwygFrame");if(!i)return;i.style.height=s+"px";const n=t.get("options");if(n?.get("iframe")){const t=n.get("maxHeight");t&&i.setAttribute("scrolling",s>De.get(t)?"auto":"no")}Oe.isResizeObserverSupported||this._emitResizeEvent(t,s,null)}),0);else if(!Oe.isResizeObserverSupported){const e=t.get("wysiwygFrame");e&&this._emitResizeEvent(t,e.offsetHeight,null)}}_emitResizeEvent(t,e,s){e=-1===e?s?.borderBoxSize&&s.borderBoxSize[0]?s.borderBoxSize[0].blockSize:s.contentRect.height+De.get(t.get("wwComputedStyle").getPropertyValue("padding-left"))+De.get(t.get("wwComputedStyle").getPropertyValue("padding-right")):e,t.get("_editorHeight")!==e&&(this.#_i.triggerEvent("onResizeEditor",{height:e,prevHeight:t.get("_editorHeight"),frameContext:t,observerEntry:s}),t.set("_editorHeight",e)),t.has("documentType_use_page")&&t.get("documentType").resizePage()}init(){this.#So=!this.#_i.addEvent(this.alertModal.querySelector('[data-command="close"]'),"click",this.alertClose.bind(this)),this._initToggleButtons()}#Fo(t){const e=Pe.query.getEventTarget(t);(/close/.test(e.getAttribute("data-command"))||e===this.#xo)&&this.alertClose()}#Do(t){Fe.isEsc(t.code)&&this.alertClose()}_destroy(){this.#Bo&&Tn.clearTimeout(this.#Bo),this.#No&&=this.#_i.removeGlobalEvent(this.#No),this.#Eo&&=this.#_i.removeEvent(this.#Eo),this.opendModal=null,this.opendBrowser=null,this.#Oo=null,this.#Ro=null,this.#zo?.destroy(),this.#zo=null,this.#Io=null,this.#Lo=null}},Nn=["se-component-selected","se-figure-over-selected","se-block-hover","se-pre-code-focus"],Bn=new RegExp(Nn.join("|")),In="."+Nn.join(", .");function Ln(t){if(!Bn.test(t))return t;const e=r.createElement("template");e.innerHTML=t;const s=e.content.querySelectorAll(In);for(let t=0;t0?s:u[d],o=p[n];o.index+=t;const l=o.value[o.index];if(!l)return console.warn("[SunEditor.history.setContent.fail] History state desynchronized. Aborting undo/redo operation."),o.index-=t,void(d-=t);r.get(n).get("wysiwyg").innerHTML=l.content,s!==n&&t<0&&1===d?d=0:s!==n&&t>0&&1===o.index?d++:(t<0&&o.index<1||t>0&&o.index>o.value.length)&&(d+=t);let h=n,c=l;if(t<0&&d>0&&0===o.index){const e=u[d+t];if(e!==n){const t=p[e];h=e,c=t.value[t.index]}}e.facade.changeFrameContext(h),e.selection.setRange(vt(c.s.path,c.frame),c.s.offset,vt(c.e.path,c.frame),c.e.offset),e.focusManager.focus(),d<0?d=0:d>=u.length&&(d=u.length-1),e.ui.offCurrentController(),e.pluginManager.checkFileInfo(!1),e.char.display(),e.ui._syncFrameState(a),a.has("documentType_use_header")&&a.get("documentType").reHeader(),b(a,o.index,!0)}function w(t,e,s,i){let n,o;e?(n={path:ft(e.startContainer,null,null),offset:e.startOffset},o={path:ft(e.endContainer,null,null),offset:e.endOffset}):(n={path:[0,0],offset:[0,0]},o={path:0,offset:0}),d+=i,u[d]=s;const l=p[s];l.index+=i,l.value[l.index]={content:t,s:n,e:o,frame:r.get(s).get("wysiwyg")}}function C(t){p[t]={value:[],index:-1},g[t]=r.get(t).get("wysiwyg").innerHTML}function _(t,s){e.pluginManager.checkFileInfo(!1);const i=r.get(t),n=Ln(i.get("wysiwyg").innerHTML),o=p[t];if(n&&(!o.value[o.index]||n!==o.value[o.index].content)){if(u.length>d+1&&function(t){const s=[];for(let t=d+1,e=u.length;t{t.disabled=!0}));for(let t=0,e=s.length;tc){const e=o.value.length-c;o.value.splice(0,e),o.index-=e;let s=0;for(let i=u.length-1;i>=0&&s{t.disabled=!1})),e.char.display(),b(i,o.index,!1)}}return{push(t,i){if(f)return;i=i||null===i?i:s.get("rootKey");const n=s.get("_range");o.setTimeout(e.ui._syncFrameState.bind(e.ui,r.get(i)),0);const l="number"==typeof t?t>0?t:0:t?h:0;l&&!m||(o.clearTimeout(m),l)?m=o.setTimeout((()=>{o.clearTimeout(m),m=null,_(i,n)}),l):_(i,n)},check(t,e){m&&(o.clearTimeout(m),m=null,_(t,e))},undo(){d>0&&y(-1)},redo(){u.length-1>d&&y(1)},overwrite(t){w(Ln(r.get(t||s.get("rootKey")).get("wysiwyg").innerHTML),null,s.get("rootKey"),0)},pause(){f=!0,v&&(o.clearTimeout(v),v=null),v=o.setTimeout((()=>{f=!1}),5e3)},resume(){v&&(o.clearTimeout(v),v=null),f=!1},reset(){e.commandDispatcher.applyTargets("undo",(t=>t.disabled=!0)),e.commandDispatcher.applyTargets("redo",(t=>t.disabled=!0)),e.commandDispatcher.applyTargets("save",(t=>t.disabled=!0)),i.applyToRoots((t=>t.set("historyIndex",-1))),i.applyToRoots((t=>t.set("isChanged",!1))),d=-1,u=[],p={},g={},f=!1;const t=i.rootKeys;for(let e=0,s=t.length;e{t.disabled=!(s>0&&s<=a)})),e.commandDispatcher.applyTargets("redo",(t=>{t.disabled=!(s>-1&&s-1?h!==s:i?o.index>0:s>0&&c!==s;l.set("historyIndex",s),l.set("isChanged",g),e.commandDispatcher.applyTargets("save",(t=>{t.disabled=!g})),n.triggerEvent("onResetButtons",{rootKey:t})},getRootStack:()=>p,resetDelayTime(t){h=t},_destroy(){m&&o.clearTimeout(m),v&&o.clearTimeout(v),d=u=p=g=null}}}const{_w:On}=Oe;const Rn=class{#H;#J;#t;#Uo;#Vo;#e;#X;#rt;#_i;#jo;#Go;#Ko;#Yo="default";#Xo=null;#Zo=null;#Jo=!1;#Qo=!1;#tr=!1;constructor(t,{keyName:e,balloon:s,inline:i,balloonAlways:n,res:o}){this.#H=t,this.#J=t.$,this.#t=t.store,this.#Uo=this.#J.icons,this.#Vo=this.#J.lang,this.#e=this.#J.context,this.#X=this.#J.frameContext,this.#rt=this.#J.options,this.#_i=this.#J.eventManager,this.isSub="toolbar_sub"===e,this.keyName={main:this.isSub?"toolbar_sub_main":"toolbar_main",buttonTray:this.isSub?"toolbar_sub_buttonTray":"toolbar_buttonTray",width:this.isSub?"toolbar_sub_width":"toolbar_width"},this.currentMoreLayerActiveButton=null,this.isBalloonMode=s,this.isInlineMode=i,this.isBalloonAlwaysMode=n,this.inlineToolbarAttr={top:"",width:"",isShow:!1},this.balloonOffset={top:0,left:0},this.#jo=o,this.#Go=o,this.#Ko="visualViewport"in On;const r=!this.isSub&&!s&&!i,l=this.#rt.get("_toolbar_sticky");if(this.#Jo=r&&l>=0&&!this.#rt.get("toolbar_container")&&!this.#rt.get("_toolbar_sticky_fixed")&&"undefined"!=typeof CSS&&CSS.supports("position","sticky"),this.isBottomMode=this.#t.mode.isBottom,this.#Jo){const t=this.#e.get(this.keyName.main);this.isBottomMode?(t.style.bottom=l+"px",t.style.top="auto"):l>0&&(t.style.top=l+"px")}else r&&Pe.utils.addClass(this.#e.get(this.keyName.main),"se-toolbar-relative");this._setResponsive()}get isSticky(){if(this.isSub)return!1;const t=this.#rt.get("_toolbar_sticky");if(t<0)return!1;if(this.#Jo){const e=this.#e.get(this.keyName.main);if(!e||0===e.offsetWidth||"none"===e.style.display)return!1;if(this.isBottomMode){const s=this.#Ko?On.visualViewport.height:On.innerHeight;return e.getBoundingClientRect().bottom>=s-t-1}return e.getBoundingClientRect().top<=t+1}return this.#Qo}get isCSSSticky(){return this.#Jo}disable(){this._moreLayerOff(),this.#J.menu.dropdownOff(),this.#J.menu.containerOff(),Pe.utils.setDisabled(this.#e.get(this.keyName.buttonTray).querySelectorAll(".se-menu-list .se-toolbar-btn[data-type]"),!0)}enable(){Pe.utils.setDisabled(this.#e.get(this.keyName.buttonTray).querySelectorAll(".se-menu-list .se-toolbar-btn[data-type]"),!1)}show(){this.isInlineMode?this._showInline():this.isBalloonMode?this._showBalloon():(this.#e.get(this.keyName.main).style.display="",this.isSub||(this.#X.get("_stickyDummy").style.display="")),this.isSub||this.resetResponsiveToolbar()}hide(){this.isInlineMode?(this.#e.get(this.keyName.main).style.display="none",this.#e.get(this.keyName.main).style.top="0px",this.inlineToolbarAttr.isShow=!1):(this.#e.get(this.keyName.main).style.display="none",this.isSub||(this.#X.get("_stickyDummy").style.display="none"),this.isBalloonMode&&(this.balloonOffset={top:0,left:0}))}resetResponsiveToolbar(){this.#J.menu.containerOff();const t=this.#Zo;if(t){let e=0;e=(this.isBalloonMode||this.isInlineMode)&&"auto"===this.#rt.get("toolbar_width")||this.#t.mode.isSubBalloon&&"auto"===this.#rt.get("toolbar_sub_width")?this.#X.get("topArea").offsetWidth:this.#e.get(this.keyName.main).offsetWidth;let s="default";for(let i=1,n=t.length;ifs(t.button,t.plugin,this.#Uo,this.#Vo))),this.#e.get(this.keyName.main).replaceChild(e.buttonTray,this.#e.get(this.keyName.buttonTray)),this.#e.set(this.keyName.buttonTray,e.buttonTray),this.#er(),this.#_i.triggerEvent("onSetToolbarButtons",{buttonTray:e.buttonTray,frameContext:this.#X})}_resetSticky(){if(this.#Jo)return void this.#sr();const t=this.#X.get("wrapper");if(!t)return;const e=this.#e.get(this.keyName.main),s=this.#rt.get("_toolbar_sticky");if(this.#X.get("isFullScreen")||0===e.offsetWidth||s<0)return;const i=this.#Ko?On.visualViewport.pageTop:On.scrollY,n=this.#X.get("_minHeight"),o=t.offsetHeight,r=this.#J.offset.getGlobal(this.#X.get("topArea"));if(this.isBottomMode){const t=i+On.innerHeight,l=r.top+o,a=t-s-(this.isInlineMode?e.offsetHeight:0),h=this.#rt.get("toolbar_container")?t-s-r.top-n-e.offsetHeight:a-r.top-n;a>l?this.#ir():h<0?(this.isSticky||this.#nr(1),e.style.bottom=1+h+this.#or()+"px",e.style.top="auto"):this.#nr(1)}else{const t=i+s,l=(this.isBalloonMode||this.isInlineMode?r.top:this.#J.offset.getGlobal(this.#rt.get("toolbar_container")).top)-(this.isInlineMode?e.offsetHeight:0),a=this.#rt.get("toolbar_container")?r.top-i+o-n-s-e.offsetHeight:o+l+s-t-n;tt-e)).unshift("default")}_showBalloon(t){if(!this.isBalloonMode)return;this.isSub&&this.resetResponsiveToolbar();const e=t||this.#J.selection.getRange(),s=this.#e.get(this.keyName.main),i=this.#J.selection.get();let n;if(this.isBalloonAlwaysMode&&e.collapsed)n=!0;else if(i.focusNode===i.anchorNode)n=i.focusOffset0)return;const t=Math.round(On.visualViewport.offsetTop);if(0===t&&!this.#tr)return;const e=this.#e.get(this.keyName.main),s=this.#rt.get("_toolbar_sticky_offset");if(t>0)if(this.#tr=!0,this.isBottomMode){const i=Math.round(On.innerHeight-On.visualViewport.height-t);e.style.bottom=s+i+"px",e.style.top="auto"}else e.style.top=s+t+"px";else{this.#tr=!1;const t=this.#rt.get("_toolbar_sticky");this.isBottomMode?(e.style.bottom=t+"px",e.style.top="auto"):e.style.top=t>0?t+"px":""}}#ir(){(this.#rt.get("toolbar_container")?this.#e.get("_stickyDummy"):this.#X.get("_stickyDummy")).style.display="none";const t=this.#e.get(this.keyName.main);this.isBottomMode?(t.style.bottom=this.isInlineMode?-t.offsetHeight+"px":"",t.style.top="auto",this.#X.get("wrapper").style.marginBottom=""):(t.style.top=this.isInlineMode?this.inlineToolbarAttr.top:"",this.#X.get("wrapper").style.marginTop=""),t.style.width=this.isInlineMode?this.inlineToolbarAttr.width:"",Pe.utils.removeClass(t,"se-toolbar-sticky"),this.#Qo=!1}_destroy(){this._moreLayerOff()}},{isMobile:zn,_w:Pn}=Oe;function Dn(t){return/free$/.test(t)}const Fn=class{#J;#t;#Ci;#e;#_i;#rr;#lr=[];#ar=null;#hr=null;#cr=null;#dr=null;#ur=null;#pr=null;#gr=null;#mr=null;#fr=null;#vr=null;#br=null;#yr=new Set;constructor(t){this.#J=t.$,this.#t=t.store,this.#Ci=this.#J.contextProvider,this.#e=this.#J.context,this.#_i=this.#J.eventManager,this.targetMap={},this.itemsMap={},this.index=-1,this.menus=[],this.currentButton=null,this.currentDropdown=null,this.currentDropdownActiveButton=null,this.currentDropdownName="",this.currentDropdownType="",this.currentContainer=null,this.currentContainerActiveButton=null,this.currentContainerName="",this.currentDropdownPlugin=null,this.#rr={mousedown:this.#wr.bind(this),containerDown:this.containerOff.bind(this),keydown:this.#Cr.bind(this),esc:this.#_r.bind(this),mousemove:this.#kr.bind(this),mouseout:this.#xr.bind(this)},this.#ar=null,this.#hr=null,this.#cr=null,this.#dr=null,this.#gr=null,this.#mr=null,this.#br=Pn.visualViewport||null}initDropdownTarget({key:t,type:e},s,i){if(!t)throw Error("[SUNEDITOR.init.fail] The plugin's key is not added.");let n;if(Array.isArray(s)){n=function(t,e={}){let s="";for(let e=0,i=t.length;e\n\t\t\t\n\t\t`}return Pe.utils.createElement("DIV",{class:"se-dropdown se-list-layer"+(e.className?" "+e.className:"")},`
      ${e.prependHTML||""}${s}
    `)}(s,i);const e=n.querySelectorAll(".se-list-inner li > button"),o=e.length-s.length;for(let t=0;t0&&(this.#hr=this.#_i.addGlobalEvent("keydown",this.#rr.keydown,!1),this.#ur=this.#_i.addEvent(n,"mousemove",this.#rr.mousemove,!1),this.#pr=this.#_i.addEvent(n,"mouseout",this.#rr.mouseout,!1))),this.currentDropdownPlugin=this.#J.plugins[i],this.currentDropdownPlugin?.on(s),this.#t.set("_preventBlur",!0)}dropdownOff(){this.#Tr(),this.#je(),Dn(this.currentDropdownType)&&this.currentDropdownPlugin?.off?.(),this.index=-1,this.menus=[],this.#gr=null,this.#mr=null,this.currentButton=null,this.currentDropdown&&(this.currentDropdownName="",this.currentDropdownType="",this.currentDropdown.style.display="none",this.currentDropdown=null,this.currentDropdownActiveButton&&Pe.utils.removeClass(this.currentDropdownActiveButton.parentElement.children,"on"),this.currentDropdownActiveButton=null,this.#J.ui.preventToolbarHide(!1),this.#e.get("menuTray").hidePopover?.()),this.#t.set("_preventBlur",!1),this.currentDropdownPlugin=null;for(const t of[...this.#yr])t()}subscribeDropdownOff(t){return this.#yr.add(t),()=>this.#yr.delete(t)}dropdownShow(){this.currentButton&&this.dropdownOn(this.currentButton)}dropdownHide(){this.currentDropdown&&(this.currentDropdown.style.display="none")}containerOn(t){this.#je(),this.currentContainerActiveButton=t;const e=this.currentContainerName=this.currentContainerActiveButton.getAttribute("data-command");this.currentContainer=this.targetMap[e],zn?this.#Sr(t,this.currentContainer):this.#Er(t,this.currentContainer),this.#e.get("menuTray").showPopover?.(),this.#dr=this.#_i.addGlobalEvent("mousedown",this.#rr.containerDown,!1),this.#J.plugins[e].on&&this.#J.plugins[e].on(t),this.#t.set("_preventBlur",!0)}containerOff(){this.#Tr(),this.#je(),this.currentContainer&&(this.currentContainerName="",this.currentContainer.style.display="none",this.currentContainer=null,Pe.utils.removeClass(this.currentContainerActiveButton,"on"),this.currentContainerActiveButton=null,this.#J.ui.preventToolbarHide(!1),this.#e.get("menuTray").hidePopover?.()),this.#t.set("_preventBlur",!1)}__resetMenuPosition(t,e){this.#J.offset.setRelPosition(e,this.#Ci.carrierWrapper,t.parentElement,Pe.query.getParentElement(t,".se-toolbar"),{preferUp:this.#t.mode.isBottom})}__restoreMenuPosition(){this.#gr&&this.#mr&&(this.#vr||this.#fr||this.#Er(this.#gr,this.#mr))}#Er(t,e){e.style.visibility="hidden",e.style.display="block",e.style.height="",Pe.utils.addClass(t.parentElement.children,"on"),this.#J.offset.setRelPosition(e,this.#Ci.carrierWrapper,t.parentElement,Pe.query.getParentElement(t,".se-toolbar"),{preferUp:this.#t.mode.isBottom}),e.style.visibility="",this.#gr=t,this.#mr=e}#Sr(t,e){this.#Tr(),e.style.display="none",Pe.utils.addClass(t.parentElement.children,"on"),this.#gr=t,this.#mr=e;let s=!1;const i=i=>{s||(s=!0,this.#Tr(),this.#fr=Pn.setTimeout((()=>{this.#fr=null,this.#gr===t&&this.#Er(t,e)}),i))};this.#br&&(this.#vr=()=>i(10),this.#br.addEventListener("resize",this.#vr,{once:!0})),this.#fr=Pn.setTimeout((()=>i(0)),50)}#Tr(){this.#fr&&(Pn.clearTimeout(this.#fr),this.#fr=null),this.#vr&&(this.#br?.removeEventListener("resize",this.#vr),this.#vr=null)}#$r(t){const e=Pe.query.getParentElement(t,".se-more-layer");return e&&"block"!==e.style.display&&e.getAttribute("data-ref")?e:null}#Rs(t){Pe.utils.removeClass(this.currentDropdown,"se-select-menu-mouse-move"),Pe.utils.addClass(this.currentDropdown,"se-select-menu-key-action"),t=this.index+t;const e=this.menus.length,s=this.index=t>=e?0:t<0?e-1:t;for(let t=0;tt&&Pe.utils.hasClass(t,"se-dropdown")))||(t.preventDefault(),t.stopPropagation(),this.dropdownOff()))}#kr(t){Pe.utils.addClass(this.currentDropdown,"se-select-menu-mouse-move"),Pe.utils.removeClass(this.currentDropdown,"se-select-menu-key-action");const e=this.menus.indexOf(t.target);-1!==e&&(this.index=1*e)}_destroy(){this.#je()}},{_w:Hn,_d:qn}=Oe;function Wn(t,e){const s="markdown"===e?"markdownNumbers":"codeNumbers",i="markdown"===e?"markdown":"code",n=t.get(s);if(!n)return;const o=t.get(i),r=(o.value.match(/\n/g)||[]).length+1;let l="";for(let t=1;t<=r;t++)l+=`${t}\n`;const a=Hn.getComputedStyle(o);n.style.lineHeight=a.lineHeight,n.style.fontSize=a.fontSize,n.style.fontFamily=a.fontFamily,n.style.paddingTop=a.paddingTop,n.style.paddingBottom=a.paddingBottom,n.value=l}const Un=class{#H;#J;#t;#Uo;#Vo;#O;#e;#X;#rt;#Q;#_i;#ee;#Mr="";#Nr="";#Br="";#Ir="";#Lr="";#Ar="";#Or="";#Rr="";#zr="";#Pr="";#Dr="";#Fr=0;#Hr=!1;#qr=!1;#Wr=!1;#Ur=null;#Vr="";constructor(t){this.#H=t,this.#J=t.$,this.#t=t.store,this.#Uo=this.#J.icons,this.#Vo=this.#J.lang,this.#O=this.#J.frameRoots,this.#e=this.#J.context,this.#X=this.#J.frameContext,this.#rt=this.#J.options,this.#Q=this.#J.frameOptions,this.#_i=this.#J.eventManager,this.#ee=new RegExp(`^(${this.#rt.get("_disallowedExtraTag")})$`,"i")}codeView(t){const e=this.#X;if(!e.get("codeWrapper"))return;if(void 0===t&&(t=!e.get("isCodeView")),t===e.get("isCodeView"))return;t&&e.get("isMarkdownView")&&this.markdownView(!1),e.set("isCodeView",t),this.#J.ui.offCurrentController(),this.#J.ui.offCurrentModal();const s=e.get("codeWrapper"),i=e.get("code"),n=e.get("wysiwygFrame"),o=e.get("wrapper");t?(this.#J.finder.close(),this.#jr(),s.style.setProperty("display","flex","important"),n.style.display="none",e.get("isFullScreen")?i.style.height="100%":"auto"!==this.#Q.get("height")||this.#rt.get("hasCodeMirror")||(i.style.height=i.scrollHeight>0?i.scrollHeight+"px":"auto"),this.#rt.get("hasCodeMirror")&&this._codeMirrorEditor("refresh",null,null),e.get("isFullScreen")||(this.#J.ui.preventToolbarHide(!0),this.#t.mode.isBalloon&&(this.#e.get("toolbar_arrow").style.display="none",this.#e.get("toolbar_main").style.left="",this.#t.mode.isInline=this.#J.toolbar.isInlineMode=!0,this.#t.mode.isBalloon=this.#J.toolbar.isBalloonMode=!1,this.#J.toolbar._showInline())),this.#t.mode.isBalloon&&this.#J.subToolbar.hide(),Wn(e),this.#t.set("_range",null),i.focus(),Pe.utils.addClass(this.#J.commandDispatcher.targets.get("codeView"),"active"),Pe.utils.addClass(o,"se-source-view-status")):(Pe.check.isNonEditable(n)||this.#Gr(),n.scrollTop=0,s.style.setProperty("display","none","important"),n.style.display="block","auto"!==this.#Q.get("height")||this.#rt.get("hasCodeMirror")||(e.get("code").style.height="0px"),e.get("isFullScreen")||(this.#J.ui.preventToolbarHide(!1),/balloon/.test(this.#rt.get("mode"))&&(this.#e.get("toolbar_arrow").style.display="",this.#t.mode.isInline=this.#J.toolbar.isInlineMode=!1,this.#t.mode.isBalloon=this.#J.toolbar.isBalloonMode=!0,this.#H._eventOrchestrator._hideToolbar())),this.#J.focusManager.nativeFocus(),Pe.utils.removeClass(this.#J.commandDispatcher.targets.get("codeView"),"active"),Pe.check.isNonEditable(n)||(this.#J.history.push(!1),this.#J.history.resetButtons(e.get("key"),null)),Pe.utils.removeClass(o,"se-source-view-status")),this.#J.ui._updatePlaceholder(e),this.#J.ui._toggleCodeViewButtons(t),e.has("documentType_use_header")&&(t?e.get("documentTypeInner").style.display="none":(e.get("documentTypeInner").style.display="",e.get("documentType").reHeader())),this.#_i.triggerEvent("onToggleCodeView",{frameContext:e,is:e.get("isCodeView")})}markdownView(t){const e=this.#X;if(!e.get("markdownWrapper"))return;if(void 0===t&&(t=!e.get("isMarkdownView")),t===e.get("isMarkdownView"))return;t&&e.get("isCodeView")&&this.codeView(!1),e.set("isMarkdownView",t),this.#J.ui.offCurrentController(),this.#J.ui.offCurrentModal();const s=e.get("markdownWrapper"),i=e.get("markdown"),n=e.get("wysiwygFrame"),o=e.get("wrapper");t?(this.#J.finder.close(),this.#Kr(),s.style.setProperty("display","flex","important"),n.style.display="none",e.get("isFullScreen")?i.style.height="100%":"auto"===this.#Q.get("height")&&(i.style.height=i.scrollHeight>0?i.scrollHeight+"px":"auto"),e.get("isFullScreen")||(this.#J.ui.preventToolbarHide(!0),this.#t.mode.isBalloon&&(this.#e.get("toolbar_arrow").style.display="none",this.#e.get("toolbar_main").style.left="",this.#t.mode.isInline=this.#J.toolbar.isInlineMode=!0,this.#t.mode.isBalloon=this.#J.toolbar.isBalloonMode=!1,this.#J.toolbar._showInline())),this.#t.mode.isBalloon&&this.#J.subToolbar.hide(),Wn(e,"markdown"),this.#t.set("_range",null),i.focus(),Pe.utils.addClass(this.#J.commandDispatcher.targets.get("markdownView"),"active"),Pe.utils.addClass(o,"se-source-view-status")):(Pe.check.isNonEditable(n)||this.#Yr(),n.scrollTop=0,s.style.setProperty("display","none","important"),n.style.display="block","auto"===this.#Q.get("height")&&(i.style.height="0px"),e.get("isFullScreen")||(this.#J.ui.preventToolbarHide(!1),/balloon/.test(this.#rt.get("mode"))&&(this.#e.get("toolbar_arrow").style.display="",this.#t.mode.isInline=this.#J.toolbar.isInlineMode=!1,this.#t.mode.isBalloon=this.#J.toolbar.isBalloonMode=!0,this.#H._eventOrchestrator._hideToolbar())),this.#J.focusManager.nativeFocus(),Pe.utils.removeClass(this.#J.commandDispatcher.targets.get("markdownView"),"active"),Pe.check.isNonEditable(n)||(this.#J.history.push(!1),this.#J.history.resetButtons(e.get("key"),null)),Pe.utils.removeClass(o,"se-source-view-status")),this.#J.ui._updatePlaceholder(e),this.#J.ui._toggleCodeViewButtons(t),e.has("documentType_use_header")&&(t?e.get("documentTypeInner").style.display="none":(e.get("documentTypeInner").style.display="",e.get("documentType").reHeader())),this.#_i.triggerEvent("onToggleMarkdownView",{frameContext:e,is:e.get("isMarkdownView")})}fullScreen(t){const e=this.#X;if(void 0===t&&(t=!e.get("isFullScreen")),t===e.get("isFullScreen"))return;e.set("isFullScreen",t);const s=e.get("topArea"),i=this.#e.get("toolbar_main"),n=e.get("wrapper"),o=e.get("wysiwygFrame"),r=e.get("codeWrapper"),l=e.get("code"),a=e.get("codeNumbers"),h=e.get("markdownWrapper"),c=e.get("markdown"),d=e.get("markdownNumbers"),u=this.#X.get("isCodeView"),p=this.#X.get("isMarkdownView"),g=this.#e.get("toolbar_arrow");this.#J.ui.offCurrentController();const m="none"===i.style.display||this.#t.mode.isInline&&!this.#J.toolbar.inlineToolbarAttr.isShow;if(t){this.#Vr=s.style.cssText,this.#Nr=n.style.cssText,this.#Br=o.style.cssText,this.#Ir=r?.style.cssText,this.#Lr=l.style.cssText,this.#Ar=a?.style.cssText,this.#Or=h?.style.cssText,this.#Rr=c?.style.cssText,this.#zr=d?.style.cssText,this.#Pr=i.style.cssText,g&&(this.#Dr=g.style.cssText),(this.#t.mode.isBalloon||this.#t.mode.isInline)&&(g&&(g.style.display="none"),this.#Wr=this.#t.mode.isInline,this.#qr=this.#t.mode.isBalloon,this.#t.mode.isInline=this.#J.toolbar.isInlineMode=!1,this.#t.mode.isBalloon=this.#J.toolbar.isBalloonMode=!1),this.#rt.get("toolbar_container")&&(this.#Ur=i.parentElement,e.get("container").insertBefore(i,n)),s.style.position="fixed",s.style.top="0",s.style.left="0",s.style.width="100%",s.style.maxWidth="100%",s.style.height="100%",s.style.zIndex="2147483639","none"!==e.get("_stickyDummy").style.display&&""!==e.get("_stickyDummy").style.display&&(this.#Hr=!0,e.get("_stickyDummy").style.display="none",Pe.utils.removeClass(i,"se-toolbar-sticky")),this.#Mr=qn.body.style.overflow,qn.body.style.overflow="hidden",n.style.cssText=i.style.cssText="",o.style.cssText=(o.style.cssText.match(/\s?display(\s+)?:(\s+)?[a-zA-Z]+;/)||[""])[0]+this.#Q.get("_defaultStyles").editor+(u||p?"display: none;":""),r&&(r.style.cssText=(r.style.cssText.match(/\s?display(\s+)?:(\s+)?[a-zA-Z]+;/)||[""])[0]+`display: ${u?"flex":"none"} !important;`,r.style.overflow="auto",r.style.height="100%"),h&&(h.style.cssText=(h.style.cssText.match(/\s?display(\s+)?:(\s+)?[a-zA-Z]+;/)||[""])[0]+`display: ${p?"flex":"none"} !important;`,h.style.overflow="auto",h.style.height="100%"),l.style.height="",c&&(c.style.height=""),i.style.width=o.style.height="100%",i.style.position="relative",i.style.display="block",this.#Fr=Hn.innerHeight-i.offsetHeight,n.style.height=this.#Fr-(e.has("statusbar")?e.get("statusbar").offsetHeight:0)-this.#rt.get("fullScreenOffset")+"px",this.#Q.get("iframe")&&"auto"===this.#Q.get("height")&&(n.style.overflow="auto",this.#J.ui._iframeAutoHeight(e)),e.get("topArea").style.marginTop=this.#rt.get("fullScreenOffset")+"px";const t=this.#Uo.reduction;this.#J.commandDispatcher.applyTargets("fullScreen",(e=>{Pe.utils.changeElement(e.firstElementChild,t),Pe.utils.addClass(e,"active")}))}else{o.style.cssText=this.#Br.replace(/\s?display(\s+)?:(\s+)?[a-zA-Z]+;/,"")+(u||p?"display: none;":""),r&&(r.style.cssText=this.#Ir.replace(/\s?display(\s+)?:(\s+)?[a-zA-Z]+;/,"")+`display: ${u?"flex":"none"} !important;`),l.style.cssText=this.#Lr,a&&(a.style.cssText=this.#Ar),h&&(h.style.cssText=this.#Or.replace(/\s?display(\s+)?:(\s+)?[a-zA-Z]+;/,"")+`display: ${p?"flex":"none"} !important;`),c&&(c.style.cssText=this.#Rr),d&&(d.style.cssText=this.#zr),i.style.cssText=this.#Pr,n.style.cssText=this.#Nr,s.style.cssText=this.#Vr,g&&(g.style.cssText=this.#Dr),qn.body.style.overflow=this.#Mr,"auto"!==this.#Q.get("height")||this.#rt.get("hasCodeMirror")||this._codeViewAutoHeight(e.get("code"),e.get("codeNumbers"),!0),this.#Ur&&(this.#Ur.appendChild(i),this.#Ur=null),this.#rt.get("_toolbar_sticky")>-1&&Pe.utils.removeClass(i,"se-toolbar-sticky"),this.#Hr&&!this.#rt.get("toolbar_container")&&(this.#Hr=!1,e.get("_stickyDummy").style.display="block",Pe.utils.addClass(i,"se-toolbar-sticky")),this.#t.mode.isInline=this.#J.toolbar.isInlineMode=this.#Wr,this.#t.mode.isBalloon=this.#J.toolbar.isBalloonMode=this.#qr,e.get("isCodeView")||(this.#t.mode.isInline?this.#J.toolbar._showInline():this.#t.mode.isBalloon&&this.#J.toolbar._showBalloon()),this.#J.toolbar._resetSticky(),e.get("topArea").style.marginTop="";const t=this.#Uo.expansion;this.#J.commandDispatcher.applyTargets("fullScreen",(e=>{Pe.utils.changeElement(e.firstElementChild,t),Pe.utils.removeClass(e,"active")}))}!m||e.get("isCodeView")||e.get("isMarkdownView")||this.#J.toolbar.hide(),this.#_i.triggerEvent("onToggleFullScreen",{frameContext:e,is:e.get("isFullScreen")})}showBlocks(t){const e=this.#X;void 0===t&&(t=!e.get("isShowBlocks")),e.set("isShowBlocks",!!t),t?(Pe.utils.addClass(e.get("wysiwyg"),"se-show-block"),Pe.utils.addClass(this.#J.commandDispatcher.targets.get("showBlocks"),"active")):(Pe.utils.removeClass(e.get("wysiwyg"),"se-show-block"),Pe.utils.removeClass(this.#J.commandDispatcher.targets.get("showBlocks"),"active")),this.#J.ui._syncFrameState(e)}_setButtonsActive(){const t=this.#X;if(t.get("isCodeView")?Pe.utils.addClass(this.#J.commandDispatcher.targets.get("codeView"),"active"):Pe.utils.removeClass(this.#J.commandDispatcher.targets.get("codeView"),"active"),t.get("isFullScreen")){const t=this.#Uo.reduction;this.#J.commandDispatcher.applyTargets("fullScreen",(e=>{Pe.utils.changeElement(e.firstElementChild,t),Pe.utils.addClass(e,"active")}))}else{const t=this.#Uo.expansion;this.#J.commandDispatcher.applyTargets("fullScreen",(e=>{Pe.utils.changeElement(e.firstElementChild,t),Pe.utils.removeClass(e,"active")}))}t.get("isMarkdownView")?Pe.utils.addClass(this.#J.commandDispatcher.targets.get("markdownView"),"active"):Pe.utils.removeClass(this.#J.commandDispatcher.targets.get("markdownView"),"active"),t.get("isShowBlocks")?Pe.utils.addClass(this.#J.commandDispatcher.targets.get("showBlocks"),"active"):Pe.utils.removeClass(this.#J.commandDispatcher.targets.get("showBlocks"),"active")}print(){const t=Pe.utils.createElement("IFRAME",{style:"display: none;"});qn.body.appendChild(t);const e=Hn.getComputedStyle(this.#X.get("wysiwyg")).padding,s=this.#rt.get("printTemplate")?this.#rt.get("printTemplate").replace(/\{\{\s*contents\s*\}\}/i,this.#J.html.get()):this.#J.html.get(),i=Pe.query.getIframeDocument(t),n=this.#X.get("_wd"),o=this.#rt.get("_rtl")?" se-rtl":"",r=(this.#rt.get("_themeClass")||"").trim(),l=t=>r?t.replace(r,"").trim():t,a=`\n\t\t\t`;if(this.#Q.get("iframe")){const t=this.#rt.get("printClass")?'class="'+l(this.#rt.get("printClass"))+o+'"':this.#Q.get("iframe_fullPage")?Pe.utils.getAttributesToString(n.body,["contenteditable"]).replace(r,""):'class="'+l(this.#rt.get("_editableClass"))+o+'"';i.write(`\n\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t${n.head.innerHTML}\n\t\t\t\t\t\t${a}\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t${s}\n\t\t\t\t\t\n\t\t\t\t`)}else{const t=qn.head.getElementsByTagName("link"),e=qn.head.getElementsByTagName("style");let n="";for(let e=0,s=t.length;e\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t${n}\n\t\t\t\t\t\t${a}\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t${s}\n\t\t\t\t\t\n\t\t\t\t`)}this.#J.ui.showLoading(),Hn.setTimeout((()=>{try{if(t.focus(),Oe.isEdge||Oe.isChromium||"StyleMedia"in Oe._w)try{t.contentWindow.document.execCommand("print",!1,null)}catch(e){console.warn("[SUNEDITOR.print.warn]",e),t.contentWindow.print()}else t.contentWindow.print()}catch(t){throw Error(`[SUNEDITOR.print.fail] error: ${t.message}`)}finally{this.#J.ui.hideLoading(),Pe.utils.removeItem(t)}}),1e3)}preview(){this.#J.menu.dropdownOff(),this.#J.menu.containerOff(),this.#J.ui.offCurrentController(),this.#J.ui.offCurrentModal();const t=this.#rt.get("previewTemplate")?this.#rt.get("previewTemplate").replace(/\{\{\s*contents\s*\}\}/i,this.#J.html.get({withFrame:!0})):this.#J.html.get({withFrame:!0}),e=Hn.open("","_blank"),s=this.#X.get("_wd"),i=this.#rt.get("_rtl")?" se-rtl":"";if(this.#Q.get("iframe")){const n=this.#rt.get("printClass")?'class="'+this.#rt.get("printClass")+i+'"':this.#Q.get("iframe_fullPage")?Pe.utils.getAttributesToString(s.body,["contenteditable"]):'class="'+this.#rt.get("_editableClass")+i+'"';e.document.write(`\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t${s.head.innerHTML}\n\t\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t${t}\n\t\t\t\t\t\n\t\t\t\t`)}else{const s=qn.head.getElementsByTagName("link"),n=qn.head.getElementsByTagName("style");let o="";for(let t=0,e=s.length;t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t${this.#Vo.preview}\n\t\t\t\t\t\t${o}\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t${t}\n\t\t\t\t\t\n\t\t\t\t`)}}_resetFullScreenHeight(){if(this.#X.get("isFullScreen"))return this.#Fr+=Hn.innerHeight-this.#e.get("toolbar_main").offsetHeight-(this.#X.has("statusbar")?this.#X.get("statusbar").offsetHeight:0)-this.#Fr,this.#X.get("wrapper").style.height=this.#Fr+"px",!0}_codeMirrorEditor(t,e,s){const i=s?this.#O.get(s).get("options"):this.#Q;switch(t){case"set":i.get("codeMirrorEditor").getDoc().setValue(e);break;case"get":return i.get("codeMirrorEditor").getDoc().getValue();case"readonly":i.get("codeMirrorEditor").setOption("readOnly",e);break;case"refresh":i.get("codeMirrorEditor").refresh()}}_setCodeView(t){this.#rt.get("hasCodeMirror")?this._codeMirrorEditor("set",t,null):this.#X.get("code").value=t}_getCodeView(){return this.#rt.get("hasCodeMirror")?this._codeMirrorEditor("get",null,null):this.#X.get("code").value}_codeViewAutoHeight(t,e,s){s&&(t.style.height=t.scrollHeight+"px"),this.#Xr(e,t)}_scrollLineNumbers(t){t.scrollTop=this.scrollTop,t.scrollLeft=this.scrollLeft}_markdownViewAutoHeight(t,e,s){s&&(t.style.height=t.scrollHeight+"px"),this.#Xr(e,t)}_scrollMarkdownLineNumbers(t){t.scrollTop=this.scrollTop,t.scrollLeft=this.scrollLeft}#Gr(){const t=this._getCodeView();if(this.#Q.get("iframe_fullPage")){const e=this.#X.get("_wd"),s=(new DOMParser).parseFromString(t,"text/html");if(!this.#ee.test("script")){const t=s.head.children;for(let e=0,i=t.length;e0?this.#J.html.clean(t,{forceFormat:!0,whitelist:null,blacklist:null,_freeCodeViewMode:this.#rt.get("freeCodeViewMode")}):"<"+this.#rt.get("defaultLine")+">
    "}#jr(){const t=this.#J.html._convertToCode(this.#X.get("wysiwyg"),!1);let e="";if(this.#Q.get("iframe_fullPage")){const s=Pe.utils.getAttributesToString(this.#X.get("_wd").body,null);e="\n\n"+this.#X.get("_wd").head.outerHTML.replace(/>(?!\n)/g,">\n")+"\n"+t+"\n"}else e=t;this._setCodeView(e)}#Kr(){const t=ze.htmlToJson(this.#X.get("wysiwyg").innerHTML),e=qe.jsonToMarkdown(t);this.#X.get("markdown").value=e}#Yr(){const t=this.#X.get("markdown").value,e=qe.markdownToHtml(t,this.#rt.get("defaultLine"));this.#X.get("wysiwyg").innerHTML=e.length>0?this.#J.html.clean(e,{forceFormat:!0,whitelist:null,blacklist:null}):"<"+this.#rt.get("defaultLine")+">
    "}#Xr(t,e){if(!t)return;const s=(e.value.match(/\n/g)||[]).length+1;if(s!==(t.value.match(/\n/g)||[]).length){let e="";for(let t=1;t<=s;t++)e+=`${t}\n`;t.value=e}}_destroy(){}},{_d:Vn,_w:jn}=Oe;class Gn{#J;#t;#Zr;#Jr;#Qr;#tl;#el;#sl;#il;#nl;#ol;#rl;#ll;#al;#hl=!1;#cl=!0;#dl=[];#ul=-1;#pl="";#gl={matchCase:!1,wholeWord:!1,regex:!1};#ml;#fl=[];#vl=null;#bl=null;#yl=null;#wl=null;#Cl=null;#_l=!1;static#kl=!1;static#xl(){if(Gn.#kl)return;Gn.#kl=!0;const t=Vn.createElement("style");t.textContent="::highlight(se-find-match){background-color:var(--se-find-match-color,rgba(255,213,0,.4));color:inherit}::highlight(se-find-current){background-color:var(--se-find-current-color,rgba(255,150,50,.7));color:inherit}",Vn.head.appendChild(t)}constructor(t){if(this.#J=t.$,this.#t=t.store,this.#ml=!!jn.Highlight&&!!CSS?.highlights,this.#J.options.get("finder_panel")){const t=function({lang:t,icons:e}){const s=`\n\t
    \n\t\t
    \n\t\t\t\n\t\t\t
    \n\t\t\t\t
    \n\t\t\t\t\t\n\t\t\t\t
    \n\t\t\t\t\n\t\t\t\t\n\t\t\t\t\n\t\t\t
    \n\t\t
    \n\t\t
    \n\t\t\t\n\t\t\t\n\t\t\t\n\t\t\t\n\t\t
    \n\t
    \n\t
    \n\t\t
    \n\t\t\t\n\t\t
    \n\t\t
    \n\t\t\t\n\t\t\t\n\t\t
    \n\t
    `,i=Pe.utils.createElement("DIV",{class:"se-find-replace"},s);return{panel:i,findInput:i.querySelector(".se-find-replace-input"),replaceInput:i.querySelector(".se-replace-input"),countDisplay:i.querySelector(".se-find-replace-count"),replaceRow:i.querySelector(".se-find-replace-row-replace"),btnCase:i.querySelector(".se-find-opt-case"),btnWord:i.querySelector(".se-find-opt-word"),btnRegex:i.querySelector(".se-find-opt-regex"),btnPrev:i.querySelector('[data-command="prev"]'),btnNext:i.querySelector('[data-command="next"]'),btnReplace:i.querySelector('[data-command="replace"]'),btnReplaceAll:i.querySelector('[data-command="replace-all"]')}}(this.#J);this.#Zr=t.panel,this.#Jr=t.findInput,this.#Qr=t.replaceInput,this.#tl=t.countDisplay,this.#el=t.replaceRow,this.#sl=t.btnCase,this.#il=t.btnWord,this.#nl=t.btnRegex,this.#ol=t.btnPrev,this.#rl=t.btnNext,this.#ll=t.btnReplace,this.#al=t.btnReplaceAll,this.#$l();const e=this.#J.frameRoots.values().next().value.get("container");if(this.#t.mode.isBottom){const t=this.#J.context.get("toolbar_main");e.insertBefore(this.#Zr,t)}else{const t=e.querySelector(".se-wrapper");e.insertBefore(this.#Zr,t)}Oe.isResizeObserverSupported&&(this.#yl=new ResizeObserver((()=>this.#Sl())).observe(this.#J.context.get("toolbar_main")))}}get isOpen(){return this.#hl}open(t=!0){const e=this.#J.frameContext;if(!e.get("isCodeView")&&!e.get("isMarkdownView")&&(this.#hl=!0,Pe.utils.addClass(this.#J.commandDispatcher.targets.get("finder"),"active"),this.#El(),this.#Zr)){this.#ol.disabled=!0,this.#rl.disabled=!0,this.#ll.disabled=!0,this.#al.disabled=!0,this.#Sl();const e=this.#J.selection.get(),s=e&&!e.isCollapsed?e.toString().trim():"";Pe.utils.addClass(this.#Zr,"se-find-replace-open"),this.#t.set("_preventBlur",!0),this.#Tl(),t&&this.#Ml(t),s&&(this.#Jr.value=s),this.#Jr.focus(),this.#Jr.select(),this.#Jr.value&&this.#Nl()}}#Sl(){if(!this.#hl||!this.#Zr)return;const t=this.#J.options.get("_toolbar_sticky");this.#t.mode.isBottom?(this.#Zr.style.top="auto",this.#Zr.style.bottom=t>=0?t+this.#J.context.get("toolbar_main").offsetHeight+"px":"0px"):this.#Zr.style.top=t>=0?t+this.#J.context.get("toolbar_main").offsetHeight+"px":"0px"}close(){this.#hl&&(this.#hl=!1,Pe.utils.removeClass(this.#J.commandDispatcher.targets.get("finder"),"active"),this.#Bl(),this.#dl=[],this.#ul=-1,this.#Il(),this.#Ll(),this.#Zr&&(Pe.utils.removeClass(this.#Zr,"se-find-replace-open"),this.#Al(),this.#t.set("_preventBlur",!1),this.#J.focusManager.nativeFocus()))}findNext(){this.#hl&&0!==this.#dl.length&&(this.#ul=(this.#ul+1)%this.#dl.length,this.#Ol())}findPrev(){this.#hl&&0!==this.#dl.length&&(this.#ul=(this.#ul-1+this.#dl.length)%this.#dl.length,this.#Ol())}search(t,{matchCase:e,wholeWord:s,regex:i}={}){return this.#hl||this.open(),void 0!==e&&(this.#gl.matchCase=e),void 0!==s&&(this.#gl.wholeWord=s),void 0!==i&&(this.#gl.regex=i),this.#pl=t||"",this.#Jr&&(this.#Jr.value=this.#pl),this.#Nl(),this.#dl.length}replace(t){this.#Rl(t)}replaceAll(t){this.#zl(t)}get matchInfo(){return{current:this.#ul+1,total:this.#dl.length}}refresh(){this.#hl&&this.#pl&&!this.#_l&&(this.#_l=!0,this.#Pl(),this.#fl=[],this.#_l=!1,clearTimeout(this.#bl),this.#bl=setTimeout((()=>this.#Nl()),300))}#Tl(){this.#Al(),this.#wl=this.#J.eventManager.addGlobalEvent("keydown",(t=>{"Escape"===t.key&&(t.preventDefault(),t.stopPropagation(),this.close())}),!0)}#Al(){this.#wl&&=this.#J.eventManager.removeGlobalEvent(this.#wl)}#El(){this.#Ll();const t=this.#J.frameContext.get("wysiwyg");this.#Cl=new MutationObserver((()=>this.refresh())),this.#Cl.observe(t,{childList:!0,subtree:!0,characterData:!0})}#Ll(){this.#Cl&&(this.#Cl.disconnect(),this.#Cl=null)}#$l(){const t=this.#J.eventManager;t.addEvent(this.#Jr,"input",this.#Dl.bind(this)),t.addEvent(this.#Jr,"keydown",this.#Fl.bind(this)),t.addEvent(this.#Qr,"keydown",this.#Hl.bind(this)),t.addEvent(this.#Zr,"click",this.#ql.bind(this)),Oe.isGecko&&t.addEvent(this.#Zr,"mousedown",(t=>{if("BUTTON"===t.target.tagName){t.preventDefault();const e=Pe.query.getCommandTarget(t.target);e&&this.#J.eventManager._injectActiveEvent(e)}this.#t.set("_preventBlur",!0)}))}#Dl(){this.#J.options.get("finder_liveSearch")&&(clearTimeout(this.#bl),this.#bl=setTimeout((()=>this.#Nl()),120))}#Fl(t){"Escape"===t.key?(t.preventDefault(),this.close()):"Enter"===t.key&&(t.preventDefault(),this.#J.options.get("finder_liveSearch")||this.#Jr.value===this.#pl?t.shiftKey?this.findPrev():this.findNext():this.#Nl())}#Hl(t){"Escape"===t.key?(t.preventDefault(),this.close()):"Enter"===t.key&&(t.preventDefault(),this.#Rl())}#ql(t){const e=Pe.query.getEventTarget(t),s=Pe.query.getCommandTarget(e);if(!s)return;t.preventDefault();switch(s.getAttribute("data-command")){case"prev":this.findPrev();break;case"next":this.findNext();break;case"toggle-replace":this.#Ml(!this.#cl);break;case"close":this.close();break;case"replace":this.#Rl();break;case"replace-all":this.#zl();break;case"opt-case":this.#gl.matchCase=!this.#gl.matchCase,Pe.utils.toggleClass(this.#sl,"on",this.#gl.matchCase),this.#Nl();break;case"opt-word":this.#gl.wholeWord=!this.#gl.wholeWord,Pe.utils.toggleClass(this.#il,"on",this.#gl.wholeWord),this.#Nl();break;case"opt-regex":this.#gl.regex=!this.#gl.regex,Pe.utils.toggleClass(this.#nl,"on",this.#gl.regex),this.#Nl()}}#Ml(t){this.#cl=t,this.#el.style.display=t?"":"none",Pe.utils.toggleClass(this.#Zr.querySelector(".se-find-toggle-replace"),"on",t),t&&this.#Qr.focus()}#Nl(){const t=this.#Jr?this.#Jr.value:this.#pl;if(this.#_l=!0,this.#Bl(),this.#dl=[],this.#ul=-1,!t)return this.#pl="",this.#Il(),void Pe.utils.removeClass(this.#Jr,"se-find-no-match");this.#pl=t;const e=this.#J.frameContext.get("wysiwyg");this.#vl=this.#Wl(),this.#dl=this.#Ul(t,e),this.#dl.length>0?(this.#ul=0,this.#Vl(),this.#Ol(),Pe.utils.removeClass(this.#Jr,"se-find-no-match")):this.#Jr&&Pe.utils.toggleClass(this.#Jr,"se-find-no-match",t.length>0),this.#Il(),this.#_l=!1}#Ul(t,e){const s=[];if(!t||!e)return s;const i=this.#gl.matchCase?"g":"gi";let n;if(this.#gl.regex)try{n=new RegExp(t,i)}catch{return s}else{const e=t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");n=this.#gl.wholeWord?new RegExp(`\\b${e}\\b`,i):new RegExp(e,i)}const o=this.#vl,r=this.#J.format,l=o.createTreeWalker(e,NodeFilter.SHOW_TEXT,null),a=[];let h,c,d="",u=null;for(;h=l.nextNode();){const t=r.getLine(h,null)||e;u&&t!==u&&(d+="\n"),u=t,a.push({node:h,start:d.length}),d+=h.textContent.replace(/\u00A0/g," ")}if(!d)return s;n.lastIndex=0;let p=0;for(;null!==(c=n.exec(d));){if(0===c[0].length){n.lastIndex++;continue}const t=c.index,e=t+c[0].length,i=o.createRange();let r=!1;for(let s=p;s=n.start&&tn.start&&e<=o){i.setEnd(n.node,e-n.start);break}}r&&s.push(i)}return s}#Vl(){if(0===this.#dl.length)return;const t=this.#J.frameContext.get("options").get("iframe");this.#ml&&!t?this.#jl():this.#Gl()}#jl(){Gn.#xl();const t=new Highlight(...this.#dl);CSS.highlights.set("se-find-match",t),this.#Kl()}#Kl(){if(this.#ul>=0&&this.#ul=0;e--){const s=this.#dl[e],i=this.#Yl(t,s,e);for(let t=0;t=0;l--){const a=r[l],h=a===i?e.startOffset:0,c=a===n?e.endOffset:a.textContent.length;h>=c||o.push(this.#Zl(t,a,h,c,s))}}return o}#Zl(t,e,s,i,n){const o=s>0?e.splitText(s):e;i-s=0)for(const t of this.#fl)t.getAttribute("data-se-find-idx")===String(this.#ul)&&Pe.utils.addClass(t,"se-find-current")}#Bl(){const t=this.#J.frameContext.get("options").get("iframe");this.#ml&&!t&&(CSS.highlights.delete("se-find-match"),CSS.highlights.delete("se-find-current")),this.#Pl()}#Pl(){const t=this.#J.frameContext.get("wysiwyg").querySelectorAll("mark.se-find-mark");if(0!==t.length){for(const e of t){const t=e.parentNode;if(t){for(;e.firstChild;)t.insertBefore(e.firstChild,e);t.removeChild(e),t.normalize()}}this.#fl=[]}}#Ol(){if(this.#ul<0||this.#ul>=this.#dl.length)return;const t=this.#J.frameContext.get("options").get("iframe");if(this.#ml&&!t){this.#Kl();const t=this.#dl[this.#ul];this.#J.selection.scrollTo(t,{behavior:"auto"})}else{this.#Xl();const t=this.#fl.find((t=>t.getAttribute("data-se-find-idx")===String(this.#ul)));t&&this.#J.selection.scrollTo(t,{behavior:"auto",noFocus:!0})}this.#Il()}#Rl(t){if(this.#ul<0||0===this.#dl.length)return;this.#Bl();const e=this.#J.frameContext.get("wysiwyg"),s=this.#Ul(this.#pl,e);this.#ul>=s.length||(this.#Ql(s[this.#ul],t??(this.#Qr?this.#Qr.value:"")),this.#J.history.push(!1),this.#Nl(),this.#ul>=this.#dl.length&&this.#dl.length>0&&(this.#ul=0,this.#Ol()))}#zl(t){if(0===this.#dl.length)return;this.#Bl();const e=this.#J.frameContext.get("wysiwyg"),s=this.#Ul(this.#pl,e);if(0!==s.length){t=t??(this.#Qr?this.#Qr.value:"");for(let e=s.length-1;e>=0;e--)this.#Ql(s[e],t);e.normalize(),this.#J.history.push(!1),this.#Nl()}}#Ql(t,e){const s=t.startContainer,i=this.#vl.createTextNode(e);if(s===t.endContainer)return t.deleteContents(),t.insertNode(i),void s.parentNode?.normalize();t.deleteContents(),3===s.nodeType?s.parentNode&&(s.parentNode.insertBefore(i,s.nextSibling),s.parentNode.normalize()):(t.insertNode(i),i.parentNode?.normalize())}#Il(){if(!this.#Zr)return;const t=this.#dl.length>0;this.#tl.textContent=t?`${this.#ul+1}/${this.#dl.length}`:this.#pl?"0":"",this.#ol.disabled=!t,this.#rl.disabled=!t,this.#ll.disabled=!t,this.#al.disabled=!t}#Wl(){const t=this.#J.frameContext;return t.get("options").get("iframe")?t.get("_wd"):Vn}_destroy(){this.#Al(),this.#Ll(),this.#yl&&=this.#yl.disconnect(),clearTimeout(this.#bl)}}const Kn=Gn;const Yn=class{$;constructor(t){this.$=t.$}},{isMobile:Xn,_w:Zn}=Oe;function Jn(t){const e=Pe.query.getEventTarget(t);let s=e;this.$.store.mode.isBalloon&&!this.$.context.get("toolbar_sub_main")?.contains(s)&&this._hideToolbar_sub();const i=Pe.check.isInputElement(s);if(i?this.$.store.set("_preventBlur",!1):this.$.frameContext.get("wysiwyg").contains(this.$.selection.getNode())||this.$.focusManager.focus(),Pe.query.getParentElement(s,".se-dropdown"))t.stopPropagation(),this.$.ui.preventToolbarHide(!0);else{let n=s.getAttribute("data-command"),o=s.className;for(;s&&!n&&!/(se-menu-list|sun-editor-common|se-menu-tray)/.test(o);)s=s.parentElement,n=s.getAttribute("data-command"),o=s.className;if(i&&/^INPUT$/i.test(s?.getAttribute("data-type"))){if(this.$.store.set("_preventBlur",!0),this._inputFocus=!0,this.$.store.get("hasFocus")||this.applyTagEffect(),!Pe.check.isInputElement(e)||e.disabled)return;const t=this.$.plugins[n];if(!t)return;if(this.__inputBlurEvent&&this.__removeInput(),"function"==typeof t.toolbarInputChange&&(this.__inputPlugin={obj:t,target:e,value:e.value}),this.__inputBlurEvent=this.$.eventManager.addEvent(e,"blur",(s=>{if(!t.isInputActive)try{const i=e.value.trim();"function"==typeof t.toolbarInputChange&&i!==this.__inputPlugin.value&&t.toolbarInputChange({target:e,value:i,event:s})}finally{Zn.setTimeout((()=>this._inputFocus=!1),0),this.__removeInput()}})),!t)return;"function"==typeof t.toolbarInputKeyDown&&(this.__inputKeyEvent=this.$.eventManager.addEvent(e,"keydown",(s=>{t.toolbarInputKeyDown({target:e,event:s})})))}else{if(this.__inputBlurEvent&&this.__inputPlugin){const e=this.__inputPlugin.target.value.trim();return e!==this.__inputPlugin.value&&this.__inputPlugin.obj.toolbarInputChange({target:this.__inputPlugin.target,value:e,event:t}),void this.__removeInput()}this.$.frameContext.get("isCodeView")||(Xn?this.$.store.set("_preventBlur",!0):(t.preventDefault(),Oe.isGecko&&n&&this.$.eventManager._injectActiveEvent(s)))}n!==this.$.menu.currentDropdownName&&n!==this.$.menu.currentContainerName||t.stopPropagation()}}function Qn(t){const e=Pe.query.getEventTarget(t),s=Pe.query.getCommandTarget(e);if(!s)return;let i=s,n="";for(;i&&!/se-menu-tray/.test(i.className)&&!n;)i=i.parentElement,n=i?.getAttribute("data-key");if(!n)return;const o=this.$.plugins[n];o&&"function"==typeof o.action&&(t.stopPropagation(),o.action(s))}function to(t){const e=Pe.query.getEventTarget(t);this.$.commandDispatcher.runFromTarget(e)}const{_w:eo}=Oe,so=new WeakMap;async function io(t,e){const s=Pe.query.getEventTarget(e);this.$.store.set("_mousedown",!0),this.__onDownEv&&no.call(this),this.__onDownEv=this.$.eventManager.addGlobalEvent("mouseup",no.bind(this)),t.get("isReadOnly")||Pe.check.isNonEditable(t.get("wysiwyg"))||(this.$.format._isExcludeSelectionElement(s)?e.preventDefault():(this._setSelectionSync(),eo.setTimeout(this.$.selection.init.bind(this.$.selection),0),!1!==await this.$.eventManager.triggerEvent("onMouseDown",{frameContext:t,event:e})&&!1!==await this._callPluginEventAsync("onMouseDown",{frameContext:t,event:e})&&(this.$.store.mode.isBalloon?this._hideToolbar():this.$.store.mode.isSubBalloon&&this._hideToolbar_sub(),/FIGURE/i.test(s?.nodeName)&&e.preventDefault())))}function no(){this.$.store.set("_mousedown",!1),this.__onDownEv=this.$.eventManager.removeGlobalEvent(this.__onDownEv)}async function oo(t,e){!1!==await this.$.eventManager.triggerEvent("onMouseUp",{frameContext:t,event:e})&&await this._callPluginEventAsync("onMouseUp",{frameContext:t,event:e})}async function ro(t,e){const s=Pe.query.getEventTarget(e);if(t.get("isReadOnly"))return e.preventDefault(),Pe.check.isAnchor(s)&&eo.open(s.href,s.target),!1;if(Pe.check.isNonEditable(t.get("wysiwyg")))return;if(!1===await this.$.eventManager.triggerEvent("onClick",{frameContext:t,event:e}))return;if(!1===await this._callPluginEventAsync("onClick",{frameContext:t,event:e}))return;const i=this.$.component.get(s);if(i)return e.preventDefault(),void this.$.component.select(i.target,i.pluginName);if(this.$.selection.init(),3===e.detail){const t=this.$.selection.getRange();this.$.format.isLine(t.endContainer)&&0===t.endOffset&&this.$.selection.setRange(t.startContainer,t.startOffset,t.startContainer,t.startContainer.textContent.length)}const n=this.$.selection.getNode(),o=this.$.format.getLine(n,null),r=this.$.format.getBlock(n,null);if(!o&&!Pe.check.isNonEditable(s)&&!Pe.check.isList(r)){const t=this.$.selection.getRange();if(this.$.format.getLine(t.startContainer)===this.$.format.getLine(t.endContainer))if(Pe.check.isList(r)){e.preventDefault();const t=n.nextElementSibling,s=Pe.utils.createElement("LI",null,n);r.insertBefore(s,t),this.$.focusManager.focus()}else Pe.check.isWysiwygFrame(n)||this.$.component.is(n)||Pe.check.isTableElements(n)&&!Pe.check.isTableCell(n)||null===this._setDefaultLine(this.$.format.isBlock(r)?"DIV":this.$.options.get("defaultLine"))||(e.preventDefault(),this.$.focusManager.focus())}this.$.commandDispatcher._copyFormat(),(this.$.store.mode.isBalloon||this.$.store.mode.isSubBalloon)&&eo.setTimeout(this._toggleToolbarBalloon.bind(this),0)}function lo(t,e){if(t.get("isReadOnly")||t.get("isDisabled"))return!1;let s=so.get(t);s||(s={rafId:null,event:null},so.set(t,s)),s.event=e,null===s.rafId&&(s.rafId=eo.requestAnimationFrame((()=>{const e=s.event;if(s.rafId=null,s.event=null,!e)return;const i=Pe.query.getEventTarget(e);!1===_i.get("__overInfo")||this.$.ui.selectMenuOn||this.$.component.hoverSelect(i),this.$.ui.blockHandle?.positionForTarget(i,e.clientY),this._callPluginEvent("onMouseMove",{frameContext:t,event:e})})))}async function ao(t,e){this.$.ui.blockHandle?.hide(e),!1!==await this.$.eventManager.triggerEvent("onMouseLeave",{frameContext:t,event:e})&&await this._callPluginEventAsync("onMouseLeave",{frameContext:t,event:e})}const ho={"event.prevent":({ctx:t})=>t.e.preventDefault(),"event.stop":({ctx:t})=>t.e.stopPropagation(),"event.prevent.stop":({ctx:t})=>{t.e.preventDefault(),t.e.stopPropagation()},"cache.styleNode":({ports:t})=>t.styleNodeCache(),"cache.formatAttrsTemp":({ports:t},{attrs:e})=>t.formatAttrsTempCache(e),"focusManager.nativeFocus":({ports:t})=>t.focusManager.nativeFocus(),"history.push":({ports:t},e)=>t.history.push(e),"documentType.refreshHeader":({ctx:t})=>{o.setTimeout((()=>{t.fc.get("documentType").reHeader()}),0)},"component.deselect":({ports:t})=>t.component.deselect(),"selection.setRange":({ports:t},{sc:e,so:s,ec:i,eo:n})=>t.selection.setRange(e,s,i,n),"format.removeBlock":({ports:t},{rangeEl:e,selectedFormats:s,newBlockElement:i,shouldDelete:n,skipHistory:o})=>t.format.removeBlock(e,{selectedFormats:s,newBlockElement:i,shouldDelete:n,skipHistory:o}),"dom.utils.removeItem":(t,{item:e})=>Pe.utils.removeItem(e),"select.component.fallback":({ports:t},{cmponentInfo:e})=>{!1===t.component.select(e.target,e.pluginName)&&t.focusManager.blur()}};function co(t){const e=t.selection.getRange(),s=e.startContainer,i=e.endContainer,n=t.format.getBlock(s),o=t.format.getBlock(i),r=Pe.check.isTableCell(n),l=Pe.check.isTableCell(o);if((r&&!n.previousElementSibling&&!n.parentElement.previousElementSibling||l&&!o.nextElementSibling&&!o.parentElement.nextElementSibling)&&n!==o){const s=Pe.query.getParentElement(e.commonAncestorContainer,Pe.check.isFigure)?.parentElement||e.commonAncestorContainer;if(r){if(l)return Pe.utils.removeItem(Pe.query.getParentElement(n,(t=>s===t.parentNode))),t.focusManager.nativeFocus(),!0;Pe.utils.removeItem(Pe.query.getParentElement(n,(t=>s===t.parentNode)))}else Pe.utils.removeItem(Pe.query.getParentElement(o,(t=>s===t.parentNode)))}const a=1===s.nodeType?Pe.query.getParentElement(s,".se-component"):null,h=1===i.nodeType?Pe.query.getParentElement(i,".se-component"):null;return a&&Pe.utils.removeItem(a),h&&Pe.utils.removeItem(h),!1}function uo(t,e,s){const i=s?e.startContainer:e.endContainer,n=s?e.startOffset:e.endOffset,o=s?"previousSibling":"nextSibling";let r;return 1===i.nodeType?(r=po(t,i.childNodes[n],o,i),Pe.check.isComponentContainer(r)||Pe.check.isNonEditable(r)?r:null):(r=po(t,i,o,i),Pe.check.isEdgePoint(i,n,s?"front":"end")&&(Pe.check.isComponentContainer(r)||Pe.check.isNonEditable(r))?r:null)}function po(t,e,s,i){if(!e)return null;let n=e[s];if(!n){if(n=t.format.getLine(i),n=n?n[s]:null,!n||t.component.is(n))return null;n="previousSibling"===s?n.firstChild:n.lastChild}return n}function go(t,e,s,i){if(!t.collapsed||!e)return!1;const n=t.getBoundingClientRect();if(n.height<=0)return!1;const o=i.createRange();o.selectNodeContents(e);const r=o.getBoundingClientRect();return!(r.width<=2)&&("front"===s?n.left<=r.left+2:n.left>=r.right-2)}function mo(t,e,s){if(!t.collapsed||!Pe.check.isBreak(e))return!1;const i="front"===s?"previousSibling":"nextSibling";let n=e[i];for(;3===n?.nodeType&&Pe.check.isZeroWidth(n);)n=n[i];return!n||Pe.check.isList(n)}function fo(t,e,s){const i="front"===s?"previousElementSibling":"nextElementSibling",n="front"===s?"lastElementChild":"firstElementChild";let o=e,r=null;for(;o&&!(r=o[i]);){const e=o.parentElement;if(!e||t.isClosureBlock(e)||Pe.check.isWysiwygFrame(e))return null;if(t.isBlock(e))o=e;else{if(!Pe.check.isListCell(e))return null;if("front"===s)return e;o=e}}for(;r&&t.isBlock(r)&&!t.isClosureBlock(r);)r=r[n];return r}function vo(t,e,s){if(!e||!t.isNormalLine(e)||!Pe.check.isEmptyLine(e))return null;if(Pe.utils.arrayFind(e.children,Pe.check.isList))return null;const i="front"===s?e.previousElementSibling:e.nextElementSibling;return t.isNormalLine(i)||t.isBrLine(i)?i:null}function bo(t,e){const s=Pe.utils.arrayFind(t.children,Pe.check.isList)||t.nextElementSibling||e?.parentElement?.nextElementSibling;return s&&(Pe.check.isList(s)||Pe.utils.arrayFind(s.children,Pe.check.isList))?s:null}const yo={"del.format.removeAndMove":({ports:t},{container:e,formatEl:s})=>{const i=t.html.remove();if(i.commonCon!==i.container&&s.parentElement)if(s.contains(e)){const e=function(t){const e=t.lastChild,s=t.nextElementSibling;if(!s)return e;if(Pe.check.isZeroWidth(s))return Pe.utils.removeItem(s),e;const i=s.childNodes;for(;i[0];)t.appendChild(i[0]);return Pe.utils.removeItem(s),e}(s);t.selection.setRange(e,e.textContent.length,e,e.textContent.length)}else{const{focusNode:e,focusOffset:i}=function(t){const e=t.childNodes,s=t.previousElementSibling;let i=e[0],n=0;if(!s)return{focusNode:i,focusOffset:n};if(Pe.check.isZeroWidth(s))return Pe.utils.removeItem(s),{focusNode:i,focusOffset:n};if(e.length>1||e[0]?.textContent.length>0)for(;e[0];)s.appendChild(e[0]);else i=s.lastChild,n=i.textContent.length;return Pe.utils.removeItem(t),{focusNode:i,focusOffset:n}}(s);t.selection.setRange(e,i,e,i)}},"backspace.brline.strip":({ctx:t,ports:e},{formatEl:s})=>{const i=t.options.get("defaultLine"),n=s.parentNode,o=Pe.utils.createElement(i);for(;s.firstChild&&!Pe.check.isBreak(s.firstChild);)o.appendChild(s.firstChild);s.firstChild&&Pe.check.isBreak(s.firstChild)&&s.removeChild(s.firstChild),o.firstChild||(o.innerHTML="
    "),n.insertBefore(o,s),s.firstChild&&(s.textContent.trim()||s.querySelector("br"))||n.removeChild(s);const r=o.firstChild;e.selection.setRange(r,0,r,0)},"backspace.format.maintain":({ctx:t},{formatEl:e})=>{if(e.nodeName.toUpperCase()===t.options.get("defaultLine").toUpperCase()){e.innerHTML="
    ";const t=e.attributes;for(;t[0];)e.removeAttribute(t[0].name)}else e.parentNode.replaceChild(Pe.utils.createElement(t.options.get("defaultLine"),null,"
    "),e)},"backspace.component.select":({ports:t},{selectionNode:e,range:s,fileComponentInfo:i})=>{let n=null;Pe.check.isBreak(e)?Pe.utils.removeItem(e):Pe.check.isBreak(n=s.startContainer.childNodes?.[s.startOffset])&&Pe.utils.removeItem(n),!1===t.component.select(i.target,i.pluginName)&&t.focusManager.blur()},"backspace.component.remove":({ports:t},{isList:e,sel:s,formatEl:i,fileComponentInfo:n})=>{e&&Pe.utils.removeItem(s),0===i.textContent.length&&Pe.utils.removeItem(i),!1===t.component.select(n.target,n.pluginName)&&t.focusManager.blur()},"backspace.list.mergePrev":({ports:t},{prev:e,formatEl:s,rangeEl:i})=>{let n=e===i.parentNode?i.previousSibling:e.lastChild;n||(n=Pe.utils.createTextNode(Re.zeroWidthSpace),i.parentNode.insertBefore(n,i.parentNode.firstChild));const o=3===n.nodeType?n.textContent.length:1;_o(s);const r=s.childNodes;let l=n,a=r[0];for(;a=r[0];)e.insertBefore(a,l.nextSibling),l=a;Pe.utils.removeItem(s),0===i.children.length&&Pe.utils.removeItem(i),t.selection.setRange(n,o,n,o)},"backspace.list.removeNested":({ports:t},{range:e})=>{t.html.remove(),3===e.startContainer.nodeType&&t.selection.setRange(e.startContainer,e.startContainer.textContent.length,e.startContainer,e.startContainer.textContent.length)},"backspace.emptyLine.mergePrev":({ports:t},{formatEl:e,prev:s})=>{Pe.utils.removeItem(e),wo(t,s,!0)},"backspace.brline.rowMerge":({ports:t},{rowEndBr:e,rowStartBr:s})=>{const i=s.nextSibling;i!==e&&3===i?.nodeType&&Pe.check.isZeroWidth(i)&&Pe.utils.removeItem(i);const n=s.previousSibling;if(Pe.utils.removeItem(s),n&&3===n.nodeType)t.selection.setRange(n,n.textContent.length,n,n.textContent.length);else if(Pe.check.isBreak(n))t.selection.setRange(e,0,e,0);else{const s=e.parentNode;t.selection.setRange(s,0,s,0)}},"backspace.softBreak.merge":({ports:t},{zws:e})=>{const s=e.previousSibling,i=e.parentNode,n=s?.previousSibling;Pe.utils.removeItem(e),s&&Pe.utils.removeItem(s),n?Co(t,n):i&&t.selection.setRange(i,0,i,0)},"delete.component.select":({ports:t},{formatEl:e,fileComponentInfo:s})=>{if(Pe.check.isListCell(e)){const t=s.container.previousSibling;Pe.check.isZeroWidth(t)&&Pe.utils.removeItem(t)}else Pe.check.isZeroWidth(e)&&Pe.utils.removeItem(e);!1===t.component.select(s.target,s.pluginName)&&t.focusManager.blur()},"delete.component.selectNext":({ports:t,ctx:e},{formatEl:s,nextEl:i})=>{if(Pe.check.isZeroWidth(s)&&(Pe.utils.removeItem(s),Pe.check.isTable(i))){let e=Pe.query.getEdgeChild(i,Pe.check.isTableCell,!1);return e=e.firstElementChild||e,void t.selection.setRange(e,0,e,0)}const n=t.component.get(i);n?(e.e.stopPropagation(),!1===t.component.select(n.target,n.pluginName)&&t.focusManager.blur()):t.component.is(i)&&(e.e.stopPropagation(),Pe.utils.removeItem(i))},"delete.list.removeNested":({ports:t,ctx:e},{range:s,formatEl:i,rangeEl:n})=>{s.startContainer!==s.endContainer&&t.html.remove();const o=bo(i,n);if(o){let s,n;if(e.e.preventDefault(),Pe.check.isList(o)){const t=o.firstElementChild;for(n=t.childNodes,s=n[0];n[0];)i.insertBefore(n[0],o);Pe.utils.removeItem(t)}else{for(s=o.firstChild,n=o.childNodes;n[0];)i.appendChild(n[0]);Pe.utils.removeItem(o)}t.selection.setRange(s,0,s,0),t.history.push(!0)}},"delete.emptyLine.mergeNext":({ports:t},{formatEl:e,next:s})=>{Pe.utils.removeItem(e),wo(t,s,!1)},"line.merge":({ports:t},{into:e,from:s})=>{const i=t.format,n=s.parentElement;_o(e);const o=e.lastChild;for(_o(s);s.firstChild;)e.appendChild(s.firstChild);Pe.utils.removeItem(s);let r=n;for(;r&&r!==e.parentElement&&i.isBlock(r)&&!i.isClosureBlock(r)&&Pe.check.isZeroWidth(r);){const t=r.parentElement;Pe.utils.removeItem(r),r=t}e.firstChild||e.appendChild(Pe.utils.createElement("BR")),o?Co(t,o):t.selection.setRange(e,0,e,0)},"delete.brline.rowMerge":({ports:t},{rowEndBr:e})=>{let s=e.nextSibling;3===s?.nodeType&&Pe.check.isZeroWidth(s)&&(s=s.nextSibling);const i=e.parentNode;Pe.utils.removeItem(e),s&&(3===s.nodeType||Pe.check.isBreak(s))?t.selection.setRange(s,0,s,0):t.selection.setRange(i,i.childNodes.length,i,i.childNodes.length)},"delete.softBreak.merge":({ports:t},{br:e})=>{const s=e.previousSibling,i=e.parentNode,n=e.nextSibling;n&&3===n.nodeType&&Pe.check.isZeroWidth(n.textContent)&&Pe.utils.removeItem(n),Pe.utils.removeItem(e),s?Co(t,s):i&&t.selection.setRange(i,0,i,0)},"tab.format.indent":({ports:t,ctx:e},{range:s,formatEl:i,shift:n})=>{const o=t.format.getLines(null),r=[],l=[],a=Pe.check.isListCell(o[0]),h=Pe.check.isListCell(o.at(-1));let c={sc:s.startContainer,so:s.startOffset,ec:s.endContainer,eo:s.endOffset};for(let t,e=0,s=o.length;e0&&(c=t.listFormat.applyNested(r,n)),l.length>0)if(n){const t=l.length-1;for(let e,s=0;s<=t;s++){e=l[s].childNodes;for(let t,s=0,i=e.length;st.component.is(e))),o=t.format.isLine(i.previousElementSibling)?Pe.query.findTabEndIndex(i.previousElementSibling,e,2):0;o>e&&(n=o-e)}const o=Pe.utils.createTextNode(new Array(n).join(" "));if(!t.html.insertNode(o,{afterNode:null,skipCharCount:!1}))return!1;a||(c.sc=o,c.so=o.length),h||(c.ec=o,c.eo=o.length)}else{const t=Pe.utils.createTextNode(new Array(e.store.get("tabSize")+1).join(" ")),s=l.length-1;for(let e,i=0;i<=s;i++)e=l[i].firstChild,e&&(Pe.check.isBreak(e)?l[i].insertBefore(t.cloneNode(!1),e):e.textContent=t.textContent+e.textContent);const i=Pe.query.getEdgeChild(l[0],"text",!1),n=Pe.query.getEdgeChild(l[s],"text",!0);!a&&i&&(c.sc=i,c.so=0),!h&&n&&(c.ec=n,c.eo=n.textContent.length)}t.selection.setRange(c.sc,c.so,c.ec,c.eo)},"caret.scrollTo":({ports:t},{range:e})=>{t.caretScrollTo(e)},"enter.line.addDefault":({ports:t},{formatEl:e})=>{const s=t.format.addLineAfter(e).firstChild;t.selection.setRange(s,0,s,0)},"enter.list.addItem":({ports:t},{formatEl:e,selectionNode:s})=>{const i=Pe.utils.createElement("BR"),n=Pe.utils.createElement("LI",null,i);e.parentNode.insertBefore(n,e.nextElementSibling),n.appendChild(s.nextSibling),t.selection.setRange(i,1,i,1)},"enter.format.exitEmpty":({ports:t,ctx:e},{formatEl:s,rangeEl:i})=>{let n=null;if(Pe.check.isListCell(i.parentElement)){const t=s.parentNode.parentElement;i=t.parentElement;const o=Pe.utils.createElement("LI");o.innerHTML="
    ",Pe.utils.copyTagAttributes(o,s,e.options.get("lineAttrReset")),n=o,i.insertBefore(n,t.nextElementSibling)}else{let o;o=Pe.check.isTableCell(i.parentElement)?"DIV":Pe.check.isList(i.parentElement)?"LI":t.format.isLine(i.nextElementSibling)?i.nextElementSibling.nodeName:t.format.isLine(i.previousElementSibling)?i.previousElementSibling.nodeName:e.options.get("defaultLine"),n=Pe.utils.createElement(o);const r=t.format.removeBlock(i,{selectedFormats:[s],newBlockElement:null,shouldDelete:!0,skipHistory:!0});r.cc.insertBefore(n,r.sc?r.sc.nextSibling:r.cc.firstChild)}n.innerHTML="
    ",t.nodeTransform.removeAllParents(s,null,null),t.selection.setRange(n,1,n,1)},"enter.format.cleanBrAndZWS":({ports:t},{selectionNode:e,selectionFormat:s,brBlock:i,children:n,offset:o})=>{s?Pe.utils.removeItem(n[o-1]):Pe.utils.removeItem(e);const r=i.nextElementSibling,l=t.format.addLine(i,t.format.isLine(r)?r:null);Pe.utils.copyFormatAttributes(l,i),t.selection.setRange(l,1,l,1)},"enter.format.insertBrHtml":({ports:t},{brBlock:e,range:s,wSelection:i,offset:n})=>{t.html.insert(s.collapsed&&Pe.check.isBreak(s.startContainer.childNodes[s.startOffset-1])?"
    ":"

    ",{selectInserted:!1,skipCharCount:!0,skipCleaning:!0});let o=i.focusNode;const r=i.focusOffset;e===o&&(o=o.childNodes[r-n>1?r-1:r]),t.selection.setRange(o,1,o,1),t.setOnShortcutKey(!0)},"enter.brline.insert":({ports:t},{range:e})=>{t.selection.setRange(e.startContainer,e.startOffset,e.endContainer,e.endOffset),e.collapsed||t.html.remove();const s=Pe.utils.createElement("BR");t.html.insertNode(s,{afterNode:null,skipCharCount:!0}),s.nextSibling||s.parentNode.appendChild(Pe.utils.createElement("BR"));const i=s.nextSibling;t.selection.setRange(i,0,i,0),t.setOnShortcutKey(!0)},"enter.shift.br":({ports:t,ctx:e},{range:s})=>{const i=e.fc.get("_wd"),n=t.selection.get(),o=n?.rangeCount>0&&e.fc.get("wysiwyg").contains(n.focusNode)?n.getRangeAt(0):s,r=i.createRange();if(r.setStart(o.startContainer,o.startOffset),r.setEnd(o.endContainer,o.endOffset),o.collapsed||(r.deleteContents(),r.collapse(!0)),1===r.startContainer.nodeType&&Pe.check.isBreak(r.startContainer)){const t=r.startContainer;r.setStart(t.parentNode,Pe.utils.getArrayIndex(t.parentNode.childNodes,t)+r.startOffset),r.collapse(!0)}const l=Pe.utils.createElement("BR");r.insertNode(l);const a=l.nextSibling;if(a&&3===a.nodeType&&!Pe.check.isZeroWidth(a.textContent))t.selection.setRange(a,0,a,0);else{const e=Pe.utils.createTextNode(Re.zeroWidthSpace);l.parentNode.insertBefore(e,l.nextSibling),t.selection.setRange(e,1,e,1)}t.history.push(!1)},"enter.brline.exit":({ports:t},{brBlock:e})=>{const s=e.lastChild;s&&(Pe.check.isBreak(s)||Pe.check.isZeroWidth(s.textContent))&&Pe.utils.removeItem(s);const i=e.nextElementSibling,n=t.format.addLine(e,t.format.isLine(i)?i:null);Pe.utils.copyFormatAttributes(n,e),t.selection.setRange(n,1,n,1)},"enter.format.insertBrNode":({ports:t},{wSelection:e})=>{const s=e.focusNode.nextSibling,i=Pe.utils.createElement("BR");t.html.insertNode(i,{afterNode:null,skipCharCount:!0});const n=i.previousSibling,o=i.nextSibling;Pe.check.isBreak(s)||Pe.check.isBreak(n)||o&&!Pe.check.isZeroWidth(o)?t.selection.setRange(o,0,o,0):(i.parentNode.insertBefore(i.cloneNode(!1),i),t.selection.setRange(i,1,i,1)),t.setOnShortcutKey(!0)},"enter.format.breakAtEdge":({ports:t,ctx:e},{formatEl:s,selectionNode:i,formatStartEdge:n,formatEndEdge:o,bidiSwapped:r})=>{const l=Pe.utils.createElement("BR"),a=Pe.utils.createElement(s.nodeName,null,l);Pe.utils.copyTagAttributes(a,s,e.options.get("lineAttrReset"));let h=l;if(!o||!e.options.get("lineBreakClearStyle")){let t=i;do{if(!Pe.check.isBreak(t)&&1===t.nodeType){const e=t.cloneNode(!1);e.appendChild(h),h=e}t=t.parentElement}while(s!==t&&s.contains(t))}if(a.appendChild(h),s.parentNode.insertBefore(a,n&&!o?s:s.nextElementSibling),o)t.selection.setRange(l,1,l,1);else if(r)t.selection.setRange(s,1,s,1);else{const e=s.firstChild||s;t.selection.setRange(e,0,e,0)}},"enter.format.breakWithSelection":({ports:t,ctx:e},{formatEl:s,range:i,formatStartEdge:n,formatEndEdge:o})=>{const r=t.format.getLine(i.startContainer,null)!==t.format.getLine(i.endContainer,null),l=s.cloneNode(!1);l.innerHTML="
    ";const a=i.commonAncestorContainer,h=a===i.startContainer&&a===i.endContainer&&Pe.check.isZeroWidth(a)?{container:a,offset:i.endOffset,prevContainer:a.previousElementSibling,commonCon:a}:t.html.remove();let c=t.format.getLine(h.container,null),d=0;if(!c)return void(Pe.check.isWysiwygFrame(h.container)&&(t.enterPrevent(e.e),e.fc.get("wysiwyg").appendChild(l),c=l,Pe.utils.copyTagAttributes(c,s,e.options.get("lineAttrReset")),t.selection.setRange(c,d,c,d)));const u=t.format.getBlock(h.container);c=c.contains(u)?Pe.query.getEdgeChild(u,(e=>Boolean(t.format.getLine(e))),!1):c,r?o&&!n?(c.parentNode.insertBefore(l,h.prevContainer&&h.container!==h.prevContainer?c:c.nextElementSibling),c=l,d=0):(d=h.offset,n&&(c.parentNode.insertBefore(l,c),o&&(d=0))):o&&n?(c.parentNode.insertBefore(l,c),d=0):o?(c=c.parentNode.insertBefore(l,c.nextElementSibling),c=l,d=0):c=t.nodeTransform.split(h.container,h.offset,Pe.query.getNodeDepth(s)),t.enterPrevent(e.e),Pe.utils.copyTagAttributes(c,s,e.options.get("lineAttrReset")),t.selection.setRange(c,d,c,d)},"enter.format.breakAtCursor":({ports:t,ctx:e},{formatEl:s,range:i})=>{let n=null;n=Pe.check.isZeroWidth(s)?t.format.addLine(s,s.cloneNode(!1)):t.nodeTransform.split(i.endContainer,i.endOffset,Pe.query.getNodeDepth(s)),t.enterPrevent(e.e),Pe.utils.copyTagAttributes(n,s,e.options.get("lineAttrReset")),t.selection.setRange(n,0,n,0)},"enter.figcaption.exitInList":({ports:t},{formatEl:e})=>{const s=t.format.addLine(e,null);t.selection.setRange(s,0,s,0)},"keydown.input.insertNbsp":({ports:t})=>{const e=t.html.insertNode(Pe.utils.createTextNode(" "),{afterNode:null,skipCharCount:!0});e&&t.selection.setRange(e,e.length,e,e.length)},"keydown.input.insertZWS":({ports:t})=>{const e=Pe.utils.createTextNode(Re.zeroWidthSpace);t.html.insertNode(e,{afterNode:null,skipCharCount:!0}),t.selection.setRange(e,1,e,1)}};function wo(t,e,s){const i=s?e.childNodes.length:0;t.selection.setRange(e,i,e,i)}function Co(t,e){const s=3===e.nodeType?e.textContent.length:e.childNodes.length;t.selection.setRange(e,s,e,s)}function _o(t){let e=t.lastChild;for(;e&&(Pe.check.isBreak(e)||3===e.nodeType&&Pe.check.isZeroWidth(e));){const t=e.previousSibling;Pe.utils.removeItem(e),e=t}}async function ko(t,e){const s={...ho,...yo};for(const i of t){if("action.stop"===i.t)return!1;const t=s[i.t];if(t){if(!1===await t(e,i.p))return!1}}}const xo=()=>({t:"event.prevent"}),$o=()=>({t:"event.prevent.stop"}),So=()=>({t:"cache.styleNode"}),Eo=t=>({t:"cache.formatAttrsTemp",p:{attrs:t}}),To=()=>({t:"component.deselect"}),Mo=()=>({t:"focusManager.nativeFocus"}),No=t=>({t:"history.push",p:t}),Bo=()=>({t:"documentType.refreshHeader"}),Io=(t,e,s,i,n)=>({t:"format.removeBlock",p:{rangeEl:t,selectedFormats:e,newBlockElement:s,shouldDelete:i,skipHistory:n}}),Lo=t=>({t:"dom.utils.removeItem",p:{item:t}}),Ao=t=>({t:"select.component.fallback",p:{cmponentInfo:t}}),Oo=(t,e)=>({t:"del.format.removeAndMove",p:{container:t,formatEl:e}}),Ro=t=>({t:"backspace.format.maintain",p:{formatEl:t}}),zo=t=>({t:"backspace.brline.strip",p:{formatEl:t}}),Po=(t,e,s)=>({t:"backspace.component.select",p:{selectionNode:t,range:e,fileComponentInfo:s}}),Do=(t,e,s,i)=>({t:"backspace.component.remove",p:{isList:t,sel:e,formatEl:s,fileComponentInfo:i}}),Fo=(t,e,s)=>({t:"backspace.list.mergePrev",p:{prev:t,formatEl:e,rangeEl:s}}),Ho=t=>({t:"backspace.list.removeNested",p:{range:t}}),qo=(t,e)=>({t:"backspace.emptyLine.mergePrev",p:{formatEl:t,prev:e}}),Wo=(t,e)=>({t:"backspace.brline.rowMerge",p:{rowEndBr:t,rowStartBr:e}}),Uo=t=>({t:"backspace.softBreak.merge",p:{zws:t}}),Vo=(t,e)=>({t:"delete.component.select",p:{formatEl:t,fileComponentInfo:e}}),jo=(t,e)=>({t:"delete.component.selectNext",p:{formatEl:t,nextEl:e}}),Go=(t,e,s)=>({t:"delete.list.removeNested",p:{range:t,formatEl:e,rangeEl:s}}),Ko=(t,e)=>({t:"delete.emptyLine.mergeNext",p:{formatEl:t,next:e}}),Yo=t=>({t:"delete.brline.rowMerge",p:{rowEndBr:t}}),Xo=t=>({t:"delete.softBreak.merge",p:{br:t}}),Zo=(t,e)=>({t:"line.merge",p:{into:t,from:e}}),Jo=(t,e,s)=>({t:"tab.format.indent",p:{range:t,formatEl:e,shift:s}}),Qo=t=>({t:"caret.scrollTo",p:{range:t}}),tr=t=>({t:"enter.line.addDefault",p:{formatEl:t}}),er=(t,e)=>({t:"enter.list.addItem",p:{formatEl:t,selectionNode:e}}),sr=(t,e)=>({t:"enter.format.exitEmpty",p:{formatEl:t,rangeEl:e}}),ir=(t,e,s,i)=>({t:"enter.format.insertBrHtml",p:{brBlock:t,range:e,wSelection:s,offset:i}}),nr=t=>({t:"enter.format.insertBrNode",p:{wSelection:t}}),or=t=>({t:"enter.brline.insert",p:{range:t}}),rr=t=>({t:"enter.shift.br",p:{range:t}}),lr=t=>({t:"enter.brline.exit",p:{brBlock:t}}),ar=(t,e,s,i,n)=>({t:"enter.format.breakAtEdge",p:{formatEl:t,selectionNode:e,formatStartEdge:s,formatEndEdge:i,bidiSwapped:n}}),hr=(t,e,s,i)=>({t:"enter.format.breakWithSelection",p:{formatEl:t,range:e,formatStartEdge:s,formatEndEdge:i}}),cr=(t,e)=>({t:"enter.format.breakAtCursor",p:{formatEl:t,range:e}}),dr=t=>({t:"enter.figcaption.exitInList",p:{formatEl:t}}),ur=()=>({t:"keydown.input.insertNbsp"}),pr=()=>({t:"keydown.input.insertZWS"});function gr(t,e,s){const{format:i,component:n}=e,{fc:o,options:r,range:l,selectionNode:a}=s;let{formatEl:h}=s;const c=!l.collapsed||l.startContainer!==l.endContainer,d=r.get("_rtl")&&!c&&0===l.startOffset&&go(l,h,"front",o.get("_wd"));if(t.push(To()),t.push(So()),c&&co(e))return t.push($o()),t.push(Qo(l)),!0;if(!(i.isNormalLine(h)||i.isBrLine(h)||o.get("wysiwyg").firstElementChild||n.is(a)||null===function(t,e){return t.setDefaultLine(e)}(e,r.get("defaultLine"))))return t.push($o()),!1;if(i.isLine(h)&&c&&Pe.check.isEdgePoint(l.startContainer,l.startOffset,"front")&&(!l.startContainer.previousSibling||Pe.check.isZeroWidth(l.startContainer.previousSibling))&&i.getLine(l.startContainer)!==i.getLine(l.endContainer)&&(i.isLine(h.previousElementSibling)||Pe.check.isListCell(h)))return t.push($o()),t.push(Oo(l.startContainer,h)),t.push(No(!0)),t.push(Qo(l)),!1;if(!c&&!d&&h&&i.isNormalLine(h)&&!Pe.check.isListCell(h)&&i.isEdgeLine(l.startContainer,l.startOffset,"front")){const e=function(t,e,s){const i=fo(t,e,s);return t.isLine(i)?i:null}(i,h,"front");if(e&&e.parentElement!==h.parentElement&&i.isNormalLine(e))return t.push($o()),t.push(Zo(e,h)),t.push(No(!0)),!1}if(!c&&!d&&!h.previousElementSibling&&0===l.startOffset&&!a.previousSibling&&!Pe.check.isListCell(h)&&i.isLine(h)&&(!i.isBrLine(h)||i.isClosureBrLine(h)||Pe.check.isWysiwygFrame(h.parentNode)))return i.isClosureBlock(h.parentNode)?(t.push($o()),!1):i.isBrLine(h)&&Pe.check.isWysiwygFrame(h.parentNode)?(t.push($o()),t.push(zo(h)),t.push(No(!0)),!1):(Pe.check.isWysiwygFrame(h.parentNode)&&h.childNodes.length<=1&&(!h.firstChild||Pe.check.isZeroWidth(h.textContent))&&(t.push($o()),t.push(Ro(h))),t.push(Mo()),t.push(Qo(l)),!1);const u=l.startContainer;if(h&&!d&&!h.previousElementSibling&&0===l.startOffset&&3===u.nodeType&&Pe.check.isZeroWidth(u)&&!0===function(t,e,s){let i=e.parentNode.previousSibling;const n=e.parentNode.nextSibling;i||(n?i=n:(i=Pe.utils.createElement("BR"),s.appendChild(i)));let o=e;for(;s.contains(o)&&!o.previousSibling;)o=o.parentNode;if(!s.contains(o))return e.textContent="",t.nodeTransform.removeAllParents(e,null,s),!0}(e,u,h))return!0;if(!c&&h&&(0===l.startOffset||a===h)){const s=a===h?uo(e,l,!0):Pe.check.isElement(a.previousSibling)?a.previousSibling:Pe.check.isEdgePoint(l.startContainer,l.startOffset)?Pe.query.getPreviousDeepestNode(l.startContainer):null;if(n.is(s)){const e=n.get(s);if(e)return t.push($o()),t.push(Po(a,l,e)),!0}}if(uo(e,l,!0))return t.push($o()),!0;c||d||!i.isEdgeLine(l.startContainer,l.startOffset,"front")||i.isLine(h.previousElementSibling)&&t.push(Eo(h.previousElementSibling.attributes)),h=i.getLine(l.startContainer,null);const p=i.getBlock(h,null),g=l.commonAncestorContainer;if(p&&h&&!Pe.check.isTableCell(p)&&!/^FIGCAPTION$/i.test(p.nodeName)){if(Pe.check.isListCell(h)&&Pe.check.isList(p)&&(Pe.check.isListCell(p.parentElement)||h.previousElementSibling)&&(a===h||mo(l,a,"front")||3===a.nodeType&&(!a.previousSibling||Pe.check.isList(a.previousSibling)))&&(i.getLine(l.startContainer,null)!==i.getLine(l.endContainer,null)?p.contains(l.startContainer):0===l.startOffset&&l.collapsed&&!d)){if(l.startContainer!==l.endContainer)t.push(xo()),t.push(Ho(l)),t.push(No(!0));else{let e=h.previousElementSibling||p.parentElement;if(Pe.check.isListCell(e)){t.push(xo());let s=e;if(!e.contains(h)&&Pe.check.isListCell(s)&&Pe.check.isList(s.lastElementChild)){for(s=s.lastElementChild.lastElementChild;Pe.check.isListCell(s)&&Pe.check.isList(s.lastElementChild);)s=s.lastElementChild&&s.lastElementChild.lastElementChild;e=s}t.push(Fo(e,h,p)),t.push(No(!0))}}return t.push(Qo(l)),!0}if(!c&&0===l.startOffset&&!d){let e=!0,s=g;for(;s&&s!==p&&!Pe.check.isWysiwygFrame(s);){if(s.previousSibling&&(1===s.previousSibling.nodeType||!Pe.check.isZeroWidth(s.previousSibling.textContent.trim()))){e=!1;break}s=s.parentNode}if(e&&p.parentNode)return t.push(xo()),t.push(Io(p,Pe.check.isListCell(h)?[h]:null,null,!1,!1)),t.push(No(!0)),t.push(Qo(l)),!0}}if(!c&&h&&Pe.check.isEmptyLine(h)&&n.is(h.previousElementSibling)){const e=n.get(h.previousElementSibling);if(e)return t.push($o()),t.push(Do(!1,h.firstChild,h,e)),t.push(Qo(l)),!0}if(!c&&h&&(0===l.startOffset||a===h&&h.childNodes[l.startOffset])){const e=Pe.check.isListCell(h),s=a===h?h.childNodes[l.startOffset]:a,i=(e?s:h).previousSibling,o=e||(3===g.nodeType||Pe.check.isBreak(g))&&!g.previousSibling&&0===l.startOffset;if(s&&(e||!s.previousSibling)&&(g&&n.is(g.previousSibling)||o&&n.is(i))){const o=n.get(i);return o?(t.push($o()),t.push(Do(e,s,h,o))):n.is(i)&&(t.push($o()),t.push(Lo(i))),t.push(Qo(l)),!0}if(s&&Pe.check.isNonEditable(s.previousSibling))return t.push($o()),t.push(Lo(s.previousSibling)),t.push(Qo(l)),!0}if(!c&&i.isBrLine(h)&&Pe.check.isBreak(l.startContainer)&&0===l.startOffset){let e=l.startContainer.previousSibling;if(3===e?.nodeType&&Pe.check.isZeroWidth(e)&&(e=e.previousSibling),Pe.check.isBreak(e))return t.push($o()),t.push(Wo(l.startContainer,e)),t.push(No(!0)),t.push(Qo(l)),!1}if(!c&&3===l.startContainer.nodeType&&Pe.check.isZeroWidth(l.startContainer)&&l.startOffset<=1&&Pe.check.isBreak(l.startContainer.previousSibling))return t.push($o()),t.push(Uo(l.startContainer)),t.push(No(!0)),t.push(Qo(l)),!1;const m=vo(i,h,"front");return!c&&m?(t.push($o()),t.push(qo(h,m)),t.push(No(!0)),t.push(Qo(l)),!1):(t.push(Qo(l)),!0)}function mr(t,e,s){const{format:i,char:n,selection:o}=e,{frameOptions:r,range:l,formatEl:a,selectionNode:h,shift:c,e:d}=s,u=!l.collapsed||l.startContainer!==l.endContainer;t.push(To());const p=i.getBrLine(h,null),g=i.getBlock(a,null);if("byte-html"===r.get("charCounter_type")){let e="";if(e=!c&&p||c?"
    ":"<"+a.nodeName+">
    ",!n.check(e))return t.push(xo()),!1}if(c)return e.enterPrevent(d),t.push(rr(l)),t.push(Qo(l)),!0;if(!c){let n=i.isEdgeLine(l.endContainer,l.endOffset,"end"),r=i.isEdgeLine(l.startContainer,l.startOffset,"front"),c=!1;if(s.options.get("_rtl")&&a&&l.collapsed&&r!==n){const t=s.fc.get("_wd");r&&go(l,a,"front",t)?(r=!1,n=!0,c=!0):n&&go(l,a,"end",t)&&(n=!1,r=!0,c=!0)}if(n&&(/^H[1-6]$/i.test(a.nodeName)||/^HR$/i.test(a.nodeName)))return e.enterPrevent(d),t.push(tr(a)),t.push(Qo(l)),!0;if(g&&a&&!Pe.check.isTableCell(g)&&!/^FIGCAPTION$/i.test(g.nodeName)){const s=o.getRange();if(Pe.check.isEdgePoint(s.endContainer,s.endOffset)&&Pe.check.isList(h.nextSibling))return e.enterPrevent(d),t.push(er(a,h)),t.push(Qo(l)),!0;if((3!==s.commonAncestorContainer.nodeType||!s.commonAncestorContainer.nextElementSibling)&&Pe.check.isZeroWidth(a.innerText.trim())&&!Pe.check.isListCell(a.nextElementSibling))return e.enterPrevent(d),t.push(sr(a,g)),!0}if(p||g===a&&i.isClosureBlock(g)&&i.isLine(a)){if(e.enterPrevent(d),p&&!i.isClosureBrLine(p))return!function(t,e){const s=Array.from(t.childNodes),i=[[]];for(const t of s)Pe.check.isBreak(t)?i.push([]):i[i.length-1].push(t);s.length&&Pe.check.isBreak(s[s.length-1])&&i.pop();const n=t=>!t||t.every((t=>Pe.check.isZeroWidth(t.textContent))),o=e.anchorNode;let r=0;if(o===t)for(let t=0;t=1&&n(i[a-1])}}(p,o.get()).shouldExit?t.push(or(l)):t.push(lr(p)),t.push(Qo(l)),!0;const s=o.get();return h===p?t.push(ir(p,l,s,s.focusOffset)):t.push(nr(s)),t.push(Qo(l)),!0}if(l.collapsed&&(r||n))return e.enterPrevent(d),t.push(ar(a,h,r,n,c)),t.push(Qo(l)),!0;if(a){if(t.push(xo()),u){if(s.options.get("_rtl")&&r&&!n){const t=s.fc.get("_wd"),e=t.createRange();e.setStart(l.startContainer,l.startOffset),e.collapse(!0),go(e,a,"front",t)&&(r=!1,n=!0,c=!0)}t.push(hr(a,l,r,n))}else t.push(cr(a,l));return t.push(Qo(l)),!0}}return u?(t.push(Qo(l)),!0):(g&&Pe.query.getParentElement(g,"FIGCAPTION")&&Pe.query.getParentElement(g,Pe.check.isList)&&(e.enterPrevent(d),t.push(dr(a)),t.push(Qo(l))),!0)}const{isOSX_IOS:fr}=Oe;function vr(t,e){return t.get("_canUseBeforeInput")&&!e?.repeat}async function br(t,e){const s=[];switch(e.keyCode){case"Backspace":if(!1===gr(s,t,e))return s;break;case"Delete":if(!1===function(t,e,s){const{format:i,component:n}=e,{fc:o,range:r,selectionNode:l}=s;let{formatEl:a}=s;const h=!r.collapsed||r.startContainer!==r.endContainer,c=s.options.get("_rtl")&&!h&&r.endOffset>=(r.endContainer.textContent?.length||0)&&go(r,a,"end",o.get("_wd"));if(t.push(To()),t.push(So()),h&&co(e))return t.push($o()),!0;if(!h&&!c&&a&&i.isEdgeLine(r.endContainer,r.endOffset,"end")){const e=fo(i,a,"end");if(!e)return t.push($o()),!1;if(i.isLine(e)&&e.parentElement!==a.parentElement&&i.isNormalLine(a)&&i.isNormalLine(e))return t.push($o()),t.push(Zo(a,e)),t.push(No(!0)),!1}if(i.isLine(a)&&h&&Pe.check.isEdgePoint(r.endContainer,r.endOffset,"end")&&(!r.endContainer.nextSibling||Pe.check.isZeroWidth(r.endContainer.nextSibling))&&i.getLine(r.startContainer)!==i.getLine(r.endContainer)&&(i.isLine(a.nextElementSibling)||Pe.check.isListCell(a)))return t.push($o()),t.push(Oo(r.endContainer,a)),t.push(No(!0)),!1;if(!h&&a&&(r.endOffset===r.endContainer.textContent.length||l===a)){const s=l===a?uo(e,r,!1):Pe.check.isElement(l.nextSibling)?l.nextSibling:Pe.check.isEdgePoint(r.endContainer,r.endOffset)?Pe.query.getNextDeepestNode(r.endContainer,null):null;if(n.is(s)){const e=n.get(s);if(e)return t.push($o()),t.push(Vo(a,e)),!0}}if(uo(e,r,!1))return t.push($o()),!0;if((i.isLine(l)||null===l.nextSibling||Pe.check.isZeroWidth(l.nextSibling)&&null===l.nextSibling.nextSibling)&&r.startOffset===l.textContent.length){const e=a.nextElementSibling;if(!e)return!0;if(n.is(e))return t.push(xo()),t.push(jo(a,e)),!0}if(!h&&(Pe.check.isEdgePoint(r.endContainer,r.endOffset)||l===a&&a.childNodes[r.startOffset])){const e=l===a&&a.childNodes[r.startOffset]||l;if(e&&Pe.check.isNonEditable(e.nextSibling))return t.push($o()),t.push(Lo(e.nextSibling)),!0;if(n.is(e))return t.push($o()),t.push(Lo(e)),!0}h||c||!i.isEdgeLine(r.endContainer,r.endOffset,"end")||i.isLine(a.nextElementSibling)&&t.push(Eo(a.attributes)),a=i.getLine(r.startContainer,null);const d=i.getBlock(a,null);if(Pe.check.isListCell(a)&&Pe.check.isList(d)&&(r.startContainer!==r.endContainer||bo(a,d))&&(l===a||mo(r,l,"end")||3===l.nodeType&&(!l.nextSibling||Pe.check.isList(l.nextSibling))&&(i.getLine(r.startContainer,null)!==i.getLine(r.endContainer,null)?d.contains(r.endContainer):r.endOffset===l.textContent.length&&r.collapsed&&!c)))return t.push(Go(r,a,d)),!0;if(!h&&i.isBrLine(a)&&Pe.check.isBreak(r.startContainer)&&0===r.startOffset){let e=r.startContainer.previousSibling;if(3===e?.nodeType&&Pe.check.isZeroWidth(e)&&(e=e.previousSibling),Pe.check.isBreak(e))return t.push($o()),t.push(Yo(r.startContainer)),t.push(No(!0)),!1}if(!h){const e=r.startContainer;let s=null;if(3===e.nodeType&&r.startOffset>=e.textContent.length&&Pe.check.isBreak(e.nextSibling)){const t=e.nextSibling;3===t.nextSibling?.nodeType&&Pe.check.isZeroWidth(t.nextSibling.textContent)&&(s=t)}else 3===e.nodeType&&Pe.check.isZeroWidth(e)&&0===r.startOffset&&Pe.check.isBreak(e.previousSibling)&&(s=e.previousSibling);if(s)return t.push($o()),t.push(Xo(s)),t.push(No(!0)),!1}const u=vo(i,a,"end");return!(!h&&u&&(t.push($o()),t.push(Ko(a,u)),t.push(No(!0)),1))}(s,t,e))return s;break;case"Tab":if(!1===function(t,e,s){const{options:i,selectionNode:n,range:o,formatEl:r,ctrl:l,alt:a,shift:h}=s;return!!i.get("tabDisable")||(t.push(xo()),l||a||Pe.check.isWysiwygFrame(n)||(t.push(Jo(o,r,h)),t.push(No(!1))),!0)}(s,0,e))return s;break;case"Enter":if(!vr(e.store,e.e)&&!1===mr(s,t,e))return s}const{fc:i,keyCode:n,shift:o,alt:r,ctrl:l,range:a}=e;if(o&&(fr?r:l)&&Fe.isSpace(n))return s.push($o()),s.push(ur()),s;const h=!a.collapsed||a.startContainer!==a.endContainer;return l||r||h||Fe.isNonTextKey(n)||!Pe.check.isBreak(a.commonAncestorContainer)?!i.has("documentType_use_header")||!h||l||r||o||Fe.isDirectionKey(n)?(function(t,e,s){const{component:i}=e,{formatEl:n,range:o,selectionNode:r,keyCode:l}=s,a=s.options.get("_rtl"),h="ArrowLeft"===l?a?"forward":"back":"ArrowRight"===l?a?"back":"forward":null;let c=null;switch(l){case"ArrowUp":i.is(n.previousElementSibling)&&(c=i.get(n.previousElementSibling));break;case"ArrowLeft":case"ArrowRight":if("forward"===h){if(Pe.check.isEdgePoint(r,o.endOffset,"end")){const t=r.nextElementSibling||Pe.query.getNextDeepestNode(r);t?i.is(t)&&(c=i.get(t)):i.is(n.nextElementSibling)&&(c=i.get(n.nextElementSibling))}}else if("back"===h&&Pe.check.isEdgePoint(r,o.startOffset,"front")){const t=r.previousElementSibling||Pe.query.getPreviousDeepestNode(r);t?i.is(t)&&(c=i.get(t)):i.is(n.previousElementSibling)&&(c=i.get(n.previousElementSibling))}break;case"ArrowDown":i.is(n.nextElementSibling)&&(c=i.get(n.nextElementSibling))}c&&!c.options?.isInputComponent&&(t.push(xo()),t.push(Ao(c)))}(s,t,e),s):(s.push(Bo()),s):(s.push(pr()),s)}function yr(t,{_styleNodes:e}){const{frameContext:s,ui:i,focusManager:n,selection:o,format:r,listFormat:l,component:a,html:h,nodeTransform:c,history:d,char:u,menu:p,store:g}=t.$;return{focusManager:{nativeFocus:()=>n.nativeFocus(),blur:()=>n.blur()},selection:{getRange:()=>o.getRange(),getNode:()=>o.getNode(),setRange:(t,e,s,i)=>o.setRange(t,e,s,i),get:()=>o.get()},format:{isLine:t=>r.isLine(t),getLine:(t,e)=>r.getLine(t,e),getLines:t=>r.getLines(t),getBrLine:(t,e)=>r.getBrLine(t,e),getBlock:(t,e)=>r.getBlock(t,e),isNormalLine:t=>r.isNormalLine(t),isBrLine:t=>r.isBrLine(t),isClosureBrLine:t=>r.isClosureBrLine(t),isBlock:t=>r.isBlock(t),isClosureBlock:t=>r.isClosureBlock(t),isEdgeLine:(t,e,s)=>r.isEdgeLine(t,e,s),removeBlock:(t,e)=>r.removeBlock(t,e),addLine:(t,e)=>r.addLine(t,e),addLineAfter:t=>r.addLineAfter(t)},listFormat:{applyNested:(t,e)=>l.applyNested(t,e)},component:{deselect:()=>a.deselect(),is:t=>a.is(t),get:t=>a.get(t),select:(t,e)=>a.select(t,e)},html:{remove:()=>h.remove(),insert:(t,e)=>h.insert(t,e),insertNode:(t,e)=>h.insertNode(t,e)},history:{push:t=>d.push(!!t)},nodeTransform:{removeAllParents:(t,e,s)=>c.removeAllParents(t,e,s),split:(t,e,s)=>c.split(t,e,s)},char:{check:t=>u.check(t)},menu:{dropdownOff:()=>p.dropdownOff()},setDefaultLine:e=>t._setDefaultLine(e),hideToolbar:()=>t._hideToolbar(),hideToolbar_sub:()=>t._hideToolbar_sub(),styleNodeCache:()=>e.value=t.__cacheStyleNodes,formatAttrsTempCache:e=>t._formatAttrsTemp=e,setOnShortcutKey:e=>t._onShortcutKey=e,caretScrollTo(t){i._iframeAutoHeight(s),o.scrollTo(o.getRange()||t,{behavior:"auto",block:"nearest",inline:"nearest"})},enterPrevent(e){e.preventDefault(),b&&!vr(g)&&(t.__focusTemp.focus({preventScroll:!0}),s.get("wysiwyg").focus({preventScroll:!0}))}}}const wr={value:[]};async function Cr(t,e){if(t.get("isReadOnly")||t.get("isDisabled"))return e.preventDefault(),e.stopPropagation(),!1;if(vr(this.$.store)&&("insertParagraph"===e.inputType||"insertLineBreak"===e.inputType))return void await _r.call(this,t,e);const s=(null===e.data?"":void 0===e.data?" ":e.data)||"";if(Fe.isComposing(e))this._handledInBefore=!1;else{if(!this.$.char.test(s,!1))return e.preventDefault(),e.stopPropagation(),!1;this._handledInBefore=!0}!1!==await this.$.eventManager.triggerEvent("onBeforeInput",{frameContext:t,event:e,data:s})&&await this._callPluginEventAsync("onBeforeInput",{frameContext:t,event:e,data:s})}async function _r(t,e){if(e.isComposing||this.isComposing)return;if(this.$.ui.selectMenuOn)return;let s=this.$.selection.getNode();if(Pe.check.isInputElement(s))return;if(this.$.menu.currentDropdownName)return;Pe.check.isWysiwygFrame(s)&&(this._setDefaultLine(this.$.options.get("defaultLine")),s=this.$.selection.getNode());const i=this._enterKeyShift||"insertLineBreak"===e.inputType;if(this._enterKeyShift=!1,!i){const t=this._normalizeEditRange();t&&(s=t)}const n=this.$.selection.getRange(),o=this.$.format.getLine(s,null)||s,r={e,fc:t,store:this.$.store,options:this.$.options,frameOptions:this.$.frameOptions,range:n,selectionNode:s,formatEl:o,keyCode:"Enter",ctrl:!1,alt:!1,shift:i},l=yr(this,{_styleNodes:wr}),a=[];mr(a,l,r),a.some((t=>"event.prevent"===t.t||"event.prevent.stop"===t.t))&&e.preventDefault(),await ko(a,{ports:l,ctx:r})}async function kr(t,e){if(t.get("isReadOnly")||t.get("isDisabled"))return e.preventDefault(),e.stopPropagation(),!1;const s=this.$.selection.getRange(),i=this.$.selection.getNode(),n=this.$.format.getLine(i,null);if(!this.$.format.isNormalLine(n)&&!this.$.format.isBrLine(n)&&s.collapsed&&!this.$.component.is(i)&&!Pe.check.isList(i)){const t=this.$.format.getBlock(i,null);this._setDefaultLine(this.$.format.isBlock(t)?"DIV":this.$.options.get("defaultLine"))}this.$.selection.init();const o=(null===e.data?"":void 0===e.data?" ":e.data)||"";if(!this._handledInBefore&&!this.$.char.test(o,!0))return e.preventDefault(),e.stopPropagation(),!1;this._handledInBefore=!1,!1!==await this.$.eventManager.triggerEvent("onInput",{frameContext:t,event:e,data:o})&&(await this._callPluginEventAsync("onInput",{frameContext:t,event:e,data:o}),this.$.history.push(!0))}const{_w:xr}=Oe,$r=new RegExp(Re.zeroWidthSpace+"+",""),Sr={ctrl:!1,alt:!1},Er=Object.preventExtensions({value:[]});async function Tr(t,e){if(this.$.ui.blockHandle?.hideOnKeyDown(),this.isComposing=Fe.isComposing(e))return!0;if(this.$.ui.selectMenuOn||!e.isTrusted)return;let s=this.$.selection.getNode();if(Pe.check.isInputElement(s))return;if(this.$.menu.currentDropdownName)return;const i=e.code,n=Fe.isShift(e),o=Sr.ctrl=Fe.isCtrl(e),r=Sr.alt=Fe.isAlt(e);if(Fe.isEnter(i)&&(this._enterKeyShift=n),!o&&t.get("isReadOnly")&&!Fe.isDirectionKey(i))return e.preventDefault(),!1;this.$.menu.dropdownOff(),this.$.store.mode.isBalloon?this.$.store.mode.isBalloonAlways||this._hideToolbar():this.$.store.mode.isSubBalloon&&(this.$.store.mode.isSubBalloonAlways||this._hideToolbar_sub());if(Fe.isEnter(i)&&!vr(this.$.store,e)||Fe.isRemoveKey(i)){const t=this._normalizeEditRange();t&&(s=t)}const l=this.$.selection.getRange(),a=this.$.format.getLine(s,null)||s;if(o&&!Fe.isNonTextKey(i)&&this.$.shortcuts.command(e,o,n,i,"",!1,null,null))return this._onShortcutKey=!0,e.preventDefault(),e.stopPropagation(),!1;if(!o&&!Fe.isNonTextKey(i)&&this.$.format.isLine(a)&&l.collapsed&&Pe.check.isEdgePoint(l.startContainer,0,"front")){const t=l.startContainer.substringData?.(0,l.startOffset);if(t&&this.$.shortcuts.command(e,!1,n,i,t,!0,a,l))return this._onShortcutKey=!0,e.preventDefault(),e.stopPropagation(),!1}else this._onShortcutKey&&(this._onShortcutKey=!1);const h={e,fc:t,store:this.$.store,options:this.$.options,frameOptions:this.$.frameOptions,range:l,selectionNode:s,formatEl:a,keyCode:i,ctrl:o,alt:r,shift:n},c=yr(this,{_styleNodes:Er}),d=await br(c,h);!1!==await this.$.eventManager.triggerEvent("onKeyDown",{frameContext:t,event:e})&&!1!==await this._callPluginEventAsync("onKeyDown",{frameContext:t,event:e,range:l,line:a})&&await ko(d,{ports:c,ctx:h})}async function Mr(t,e){if(this._onShortcutKey||this.$.menu.currentDropdownName)return;const s=e.code,i=Fe.isCtrl(e),n=Fe.isAlt(e);if(i&&(Sr.ctrl=!1),n&&(Sr.alt=!1),t.get("isReadOnly"))return;const o=this.$.selection.getRange();let r=this.$.selection.getNode();if((this.$.store.mode.isBalloon||this.$.store.mode.isSubBalloon)&&((this.$.store.mode.isBalloonAlways||this.$.store.mode.isSubBalloonAlways)&&!Fe.isEsc(s)||!o.collapsed)){if(!this.$.store.mode.isBalloonAlways&&!this.$.store.mode.isSubBalloonAlways)return void(this.$.store.mode.isSubBalloon?this.$.subToolbar._showBalloon():this.$.toolbar._showBalloon());Fe.isEsc(s)||this._showToolbarBalloonDelay()}if(Fe.isBackspace(s)&&Pe.check.isWysiwygFrame(r)&&""===r.textContent&&0===r.children.length){e.preventDefault(),e.stopPropagation(),r.innerHTML="";const i=this.$.store.get("currentNodes")[0],n=Pe.utils.createElement(this.$.format.isLine(i)&&!Pe.check.isListCell(i)?i:this.$.options.get("defaultLine"),null,"
    ");return r.appendChild(n),this.$.selection.setRange(n,0,n,0),this.applyTagEffect(),this.$.history.push(!1),void(t.has("documentType_use_header")&&Fe.isDocumentTypeObserverKey(s)&&t.get("documentType").reHeader())}const l=this.$.format.getLine(r,null),a=this.$.format.getBlock(r,null),h=this._formatAttrsTemp;if(l&&h){for(let t=0,e=h.length;t0?"repeat"===t?this.__retainTimer?(this.__retainTimer=xr.clearTimeout(this.__retainTimer),this._clearRetainStyleNodes(l)):(this.__retainTimer=xr.setTimeout((()=>{this.__retainTimer=null}),0),this._retainStyleNodes(l,Er.value)):(this.__retainTimer=null,this._retainStyleNodes(l,Er.value)):this._clearRetainStyleNodes(l)}if(t.has("documentType_use_header"))if(Fe.isDocumentTypeObserverKey(s)){t.get("documentType").reHeader();const e=Pe.query.getParentElement(this.$.selection.selectionNode,this.$.format.isLine.bind(this.$.format));t.get("documentType").on(e)}else{const e=Pe.query.getParentElement(r,(t=>1===t.nodeType));t.get("documentType").onChangeText(e)}!1!==await this.$.eventManager.triggerEvent("onKeyUp",{frameContext:t,event:e})&&!1!==await this._callPluginEventAsync("onKeyUp",{frameContext:t,event:e,range:o,line:l})&&Fe.isHistoryRelevantKey(s)&&this.$.history.push(!0)}const{_w:Nr}=Oe;function Br(t,e){const s=e.clipboardData;return!s||this._dataTransferAction("paste",e,s,t)}async function Ir(t,e){const s=e.clipboardData;if(!1===await this.$.eventManager.triggerEvent("onCopy",{frameContext:t,event:e,clipboardData:s}))return e.preventDefault(),e.stopPropagation(),!1;const i=t.get("_ww").getSelection();this.__secopy=i.toString()}async function Lr(t,e){const s=e.clipboardData;if(!1===await this.$.eventManager.triggerEvent("onCut",{frameContext:t,event:e,clipboardData:s}))return e.preventDefault(),e.stopPropagation(),!1;const i=t.get("_ww").getSelection();this.__secopy=i.toString(),Nr.setTimeout((()=>{this.$.history.push(!1)}),0)}const{_w:Ar}=Oe;function Or(t,e,s,i,n){if(n.dataTransfer&&Array.from(n.dataTransfer.types||[]).includes("application/x-suneditor-block-drag"))return;const{sc:o,so:r,ec:l,eo:a}=this.$.selection.getDragEventLocationRange(n);if(!o)return;n.preventDefault();const h=t.get("_wd").createRange();h.setStart(o,r),h.setEnd(l,a);const c={y:0,x:0};if(s){const t=this.$.offset.getGlobal(s),e=i?this.$.context.get("toolbar_main").offsetHeight:0;c.y=t.top+e-Ar.scrollY,c.x=t.left-Ar.scrollX}const d=h.getBoundingClientRect();if(d.height>0){const s=t.get("wysiwygFrame");let i=0,n=0;/^iframe$/i.test(s.nodeName)&&(i=s.offsetLeft,n=s.offsetTop),e.style.left=`${d.right+Ar.scrollX+c.x+i}px`,e.style.top=`${d.top+Ar.scrollY+c.y-5+n}px`,e.style.height=`${d.height+10}px`,e.style.display="block";try{e.showPopover?.()}catch{}}else{try{e.hidePopover?.()}catch{}e.style.display="none"}}function Rr(t){try{t.hidePopover?.()}catch{}t.style.display="none"}function zr(t,e,s){try{if(t.get("isReadOnly"))return s.preventDefault(),s.stopPropagation(),!1;const e=s.dataTransfer;if(!e)return!0;if(Array.from(e.types||[]).includes("application/x-suneditor-block-drag"))return;const{sc:i,so:n,ec:o,eo:r}=this.$.selection.getDragEventLocationRange(s);if(!i)return;if(Pe.query.getParentElement(i,".se-disable-pointer"))return void s.preventDefault();if(_i.get("__dragContainer")){if(s.preventDefault(),_i.get("__dragContainer").contains(s.target))return void this.$.component.deselect();const e=_i.get("__dragContainer");return this.$.component.deselect(),this.$.selection.setRange(i,n,o,r),this.$.html.insertNode(e,{afterNode:null,skipCharCount:!0}),void(t.has("documentType_use_page")&&(t.get("documentTypePageMirror").innerHTML=t.get("wysiwyg").innerHTML,t.get("documentType").rePage(!0)))}return this.$.html.remove(),this.$.selection.setRange(i,n,o,r),this._dataTransferAction("drop",s,e,t)}finally{try{e.hidePopover?.()}catch{}e.style.display="none"}}class Pr{#J;constructor({$:t}){this.#J=t}execute(t){if(!this.#J.options.get("__lineFormatFilter"))return null;if(this.#J.pluginManager.fileInfo.pluginRegExp.test(this.#J.ui.currentControllerName))return;const e=this.#J.selection.getRange(),s=e.commonAncestorContainer,i=e.startContainer,n=e.endOffset,o=this.#J.format.getBlock(s,null);let r,l,a;if(o)return a=Pe.utils.createElement(t||this.#J.options.get("defaultLine")),a.innerHTML=o.innerHTML,0===a.childNodes.length&&(a.innerHTML=Re.zeroWidthSpace),o.innerHTML=a.outerHTML,a=o.firstChild,r=a.childNodes[n]||Pe.query.getEdgeChildNodes(a,null).sc,r||(r=Pe.utils.createTextNode(Re.zeroWidthSpace),a.insertBefore(r,a.firstChild)),l=r.textContent.length,void this.#J.selection.setRange(r,l,r,l);if(3===s.nodeType&&this.#J.component.is(s.parentElement)){const t=this.#J.component.get(s.parentElement);if(!t)return;const e=t.container;if(s.parentElement===e){const t=s.nextElementSibling?e:e.nextElementSibling,i=Pe.utils.createElement(this.#J.options.get("defaultLine"),null,s);return e.parentElement.insertBefore(i,t),void this.#J.focusManager.focusEdge(i)}return this.#J.component.select(t.target,t.pluginName),null}if(1===s.nodeType&&"true"===s.getAttribute("data-se-embed")){let t=s.nextElementSibling;return this.#J.format.isLine(t)||(t=this.#J.format.addLine(s,this.#J.options.get("defaultLine"))),void this.#J.selection.setRange(t.firstChild,0,t.firstChild,0)}if(!this.#J.format.isBlock(i)&&!Pe.check.isWysiwygFrame(i)||!this.#J.component.is(i.children[e.startOffset])&&!this.#J.component.is(i.children[e.startOffset-1])){if(Pe.query.getParentElement(s,Pe.check.isExcludeFormat))return null;if(this.#J.format.isBlock(s)&&s.childNodes.length<=1){let t=null;return 1===s.childNodes.length&&Pe.check.isBreak(s.firstChild)?t=s.firstChild:(t=Pe.utils.createTextNode(Re.zeroWidthSpace),s.appendChild(t)),void this.#J.selection.setRange(t,1,t,1)}try{if(3===s.nodeType&&(a=Pe.utils.createElement(t||this.#J.options.get("defaultLine")),s.parentNode.insertBefore(a,s),a.appendChild(s)),Pe.check.isBreak(a.nextSibling)&&Pe.utils.removeItem(a.nextSibling),Pe.check.isBreak(a.previousSibling)&&Pe.utils.removeItem(a.previousSibling),Pe.check.isBreak(r)){const t=Pe.utils.createTextNode(Re.zeroWidthSpace);r.parentNode.insertBefore(t,r),r=t}}catch{return this.#J.frameContext.get("_wd").execCommand("formatBlock",!1,`<${t||this.#J.options.get("defaultLine")}>`),this.#J.store.set("_lastSelectionNode",null),void this.#J.selection.init()}if(a&&(Pe.check.isBreak(a.nextSibling)&&Pe.utils.removeItem(a.nextSibling),Pe.check.isBreak(a.previousSibling)&&Pe.utils.removeItem(a.previousSibling),Pe.check.isBreak(r))){const t=Pe.utils.createTextNode(Re.zeroWidthSpace);r.parentNode.insertBefore(t,r),r=t}this.#J.store.set("_lastSelectionNode",null),i?this.#J.selection.setRange(i,1,i,1):this.#J.focusManager.nativeFocus()}}}class Dr{#ta;#J;#ea;constructor(t){this.#ta=t,this.#J=t.$,this.#ea=new RegExp(`^(${Object.keys(this.#J.options.get("_defaultStyleTagMap")).join("|")})$`,"i")}update(t){if(t||=this.#J.selection.getNode(),t===this.#J.store.get("_lastSelectionNode"))return;this.#J.store.set("_lastSelectionNode",t);const e=this.#J.options.get("_rtl")?"marginRight":"marginLeft",s=this.#J.plugins,i=this.#J.commandDispatcher.targets,n=this.#ea,o=this.#J.options.get("_styleCommandMap"),r=[],l=[],a=this.#J.options.get("_textStyleTags"),h=[],c=[],d=this.#J.commandDispatcher.activeCommands,u=d.length;let p="";if(this.#J.component.is(t)&&!this.#J.component.__selectionSelected){const e=this.#J.component.get(t);if(!e)return;return this.#J.store.set("_lastSelectionNode",null),void this.#J.component.select(e.target,e.pluginName)}for(;t.firstChild;)t=t.firstChild;const g=this.#J.frameContext,m=!g.get("isReadOnly");for(let g=t;!Pe.check.isWysiwygFrame(g)&&g;g=g.parentElement)if(1===g.nodeType&&!Pe.check.isBreak(g)){if(this.#sa(g))return void this.#J.focusManager.blur();if(p=g.nodeName.toLowerCase(),l.push(p),a.includes(p)&&!this.#J.format.isLine(p)&&h.push(g),m)for(let t,e=0;e{const i=s[t]?.active(g,e);return void 0===i&&c.push(t),i})).length>0&&r.push(t);if(this.#J.format.isLine(g)){if(!r.includes("outdent")&&i.has("outdent")&&(Pe.check.isListCell(g)||g.style[e]&&De.get(g.style[e],0)>0)&&i.get("outdent").filter((t=>!Pe.check.isImportantDisabled(t)&&(t.disabled=!1,!0))).length>0&&r.push("outdent"),!r.includes("indent")&&i.has("indent")){const t=Pe.check.isListCell(g)&&!g.previousElementSibling;i.get("indent").filter((e=>!Pe.check.isImportantDisabled(e)&&(e.disabled=t,!0))).length>0&&r.push("indent")}}else n.test(p)&&(p=o[p]||p,r.push(p),Pe.utils.addClass(i.get(p),"active"))}return this.#ia(r),this.#ta.__cacheStyleNodes=h.reverse(),this.#J.store.set("currentNodes",l.reverse()),this.#J.store.set("currentNodesMap",r),this.#J.frameOptions.get("statusbar_showPathLabel")&&g.get("navigation")&&(g.get("navigation").textContent=this.#J.options.get("_rtl")?this.#J.store.get("currentNodes").reverse().join(" < "):this.#J.store.get("currentNodes").join(" > ")),t}reset(){this.#ia([])}#ia(t){const e=this.#J.commandDispatcher.activeCommands,s=this.#J.commandDispatcher.targets,i=this.#J.plugins;for(let n,o,r,l=0,a=e.length;l{Fr.clearTimeout(this.#ra),this.#ra=null,this.#t.mode.isSubBalloon?this.$.subToolbar._showBalloon():this.#o._showBalloon()}),250)}#ca(){this.#ra&&Fr.clearTimeout(this.#ra),this.#ra=Fr.setTimeout((()=>{Fr.clearTimeout(this.#ra),this.#ra=null,this._toggleToolbarBalloon()}),250)}_toggleToolbarBalloon(){this.$.selection.init();const t=this.$.selection.getRange(),e=this.#rt.has("_subMode");!(e?this.#t.mode.isSubBalloonAlways:this.#t.mode.isBalloonAlways)&&t.collapsed?e?this._hideToolbar_sub():this._hideToolbar():e?this.$.subToolbar._showBalloon(t):this.#o._showBalloon(t)}_hideToolbar(){this.#na.isPreventToolbarHide||this.$.frameContext.get("isFullScreen")||this.#o.hide()}_hideToolbar_sub(){this.$.subToolbar&&!this.#na.isPreventToolbarHide&&this.$.subToolbar.hide()}_setDefaultLine(t){return this.defaultLineManager.execute(t)}_normalizeEditRange(){if(!this.$.format.isLine(this.$.selection.getRange()?.startContainer))return null;this.$.selection.resetRangeToTextNode();const t=this.$.selection.getRange();if(t.startContainer===t.endContainer&&t.startOffset!==t.endOffset&&3===t.startContainer.nodeType&&Pe.check.isZeroWidth(t.startContainer)){const e=t.startContainer,s=e.nextSibling;s&&Pe.check.isBreak(s)?(Pe.utils.removeItem(e),this.$.selection.setRange(s,0,s,0)):this.$.selection.setRange(t.endContainer,t.endOffset,t.endContainer,t.endOffset)}return this.$.selection.getNode()}async _dataTransferAction(t,e,s,i){try{return this.#na.showLoading(),await this.#da(t,e,s,i),e.preventDefault(),e.stopPropagation(),!1}catch(t){console.warn("[SUNEDITOR.paste.error]",t)}finally{this.#na.hideLoading()}}async#da(t,e,s,i){e.preventDefault(),e.stopPropagation();let n=s.getData("text/plain"),o=s.getData("text/html");const r=!o,l=this.__secopy===n,a=/class=["']*Mso(Normal|List)/i.test(o)||/content=["']*Word.Document/i.test(o)||/content=["']*OneNote.File/i.test(o)||/content=["']*Excel.Sheet/i.test(o),h=!l&&!a&&Ue.isGoogleDocs(o),c=l?"SE":a?"MS":h?"GOOGLE":"";if(r?o=ze.htmlToEntity(n).replace(/\n/g,"
    "):(o=o.replace(/^\r?\n?\r?\n?\x3C!--StartFragment-->|\x3C!--EndFragment-->\r?\n?<\/body>\r?\n?<\/html>$/g,""),a?(o=o.replace(/\n/g," "),n=n.replace(/\n/g," "),o=We.cleanHTML(o)):h&&(o=Ue.cleanHTML(o))),!l){if(this.#rt.get("autoLinkify")){const t=(new DOMParser).parseFromString(o,"text/html");Pe.query.getListChildNodes(t.body,ze.textToAnchor,null),o=t.body.innerHTML}}r||(o=this.$.html.clean(o,{forceFormat:!1,whitelist:null,blacklist:null}));const d=this.$.char.test("byte-html"===this.$.frameOptions.get("charCounter_type")?o:n,!1);if("paste"===t){const t=await this.#_i.triggerEvent("onPaste",{frameContext:i,event:e,data:o,maxCharCount:d,from:c});if(!1===t)return!1;if("string"==typeof t){if(!t)return!1;o=t}}if("drop"===t){const t=await this.#_i.triggerEvent("onDrop",{frameContext:i,event:e,data:o,maxCharCount:d,from:c});if(!1===t)return!1;if("string"==typeof t){if(!t)return!1;o=t}}const u=s.files;if(u.length>0&&!a){for(let t=0,s=u.length;t{Fr.setTimeout((()=>{this.#o.resetResponsiveToolbar()}),0)})),this._wwFrameObserver=new ResizeObserver((t=>{Fr.setTimeout((()=>{t.forEach((t=>{this.#na._emitResizeEvent(this.$.frameRoots.get(t.target.getAttribute("data-root-key")),-1,t)})),this.#t.mode.isInline&&this.#t.mode.isBottom&&this.#o._resetSticky()}),0)}))),this.#rt.get("closeModalOutsideClick")&&this.#_i.addEvent(this.#Ci.carrierWrapper.querySelector(".se-modal .se-modal-inner"),"click",(t=>{t.target===this.#Ci.carrierWrapper.querySelector(".se-modal .se-modal-inner")&&this.#na.offCurrentModal()}),!1),this.#_i.addEvent(Fr,"resize",this.#ua.bind(this),!1),this.#_i.addEvent(Fr.visualViewport,"resize",this.#pa.bind(this),!1),this.#_i.addEvent(Fr,"scroll",this.#ga.bind(this),!1),qr&&this.#_i.addEvent(Fr.visualViewport,"scroll",this.#ma.bind(this),!1)}_addFrameEvents(t){const e=t.get("options").get("iframe"),s=e?t.get("_ww"):t.get("wysiwyg");t.set("eventWysiwyg",s);const i=t.get("code"),n=this.#Ci.carrierWrapper.querySelector(".se-drag-cursor"),o=lo.bind(this,t);this.#_i.addEvent(s,"mousemove",o,!1),this.#_i.addEvent(s,"mouseleave",ao.bind(this,t),!1),this.#_i.addEvent(s,"mousedown",io.bind(this,t),!1),this.#_i.addEvent(s,"mouseup",oo.bind(this,t),!1),this.#_i.addEvent(s,"click",ro.bind(this,t),!1),this.#_i.addEvent(s,"beforeinput",Cr.bind(this,t),!1),this.#_i.addEvent(s,"input",kr.bind(this,t),!1),this.#_i.addEvent(s,"keydown",Tr.bind(this,t),!1),this.#_i.addEvent(s,"keyup",Mr.bind(this,t),!1),this.#_i.addEvent(s,"paste",Br.bind(this,t),!1),this.#_i.addEvent(s,"copy",Ir.bind(this,t),!1),this.#_i.addEvent(s,"cut",Lr.bind(this,t),!1),this.#_i.addEvent(s,"dragover",Or.bind(this,t,n,e?this.$.frameContext.get("topArea"):null,!this.#rt.get("toolbar_container")&&!this.#t.mode.isBalloon&&!this.#t.mode.isInline),!1),this.#_i.addEvent(s,"dragend",Rr.bind(this,n),!1),this.#_i.addEvent(s,"drop",zr.bind(this,t,n),!1),this.#_i.addEvent(s,"scroll",this.#fa.bind(this,t,s),{passive:!0,capture:!1}),this.#_i.addEvent(s,"focus",this.#va.bind(this,t),!1),this.#_i.addEvent(s,"blur",this.#ba.bind(this,t),!1),this.#_i.addEvent(i,"mousedown",this.#ya.bind(this,t),!1);const r=t.get("wrapper").querySelector(".se-drag-handle");if(this.#_i.addEvent(r,"wheel",(t=>{t.preventDefault(),this.$.component.deselect()}),!1),this.#_i.addEvent(t.get("lineBreaker_t"),"pointerdown",this.#wa.bind(this,"t"),!1),this.#_i.addEvent(t.get("lineBreaker_b"),"pointerdown",this.#wa.bind(this,"b"),!1),qr&&this.#_i.addEvent(s,"touchstart",o,{passive:!0,capture:!1}),!this.#rt.get("hasCodeMirror")){const e=t.get("codeNumbers"),s=this.$.viewer._codeViewAutoHeight.bind(this.$.viewer,t.get("code"),e,"auto"===this.$.frameOptions.get("height"));this.#_i.addEvent(i,"keydown",s,!1),this.#_i.addEvent(i,"keyup",s,!1),this.#_i.addEvent(i,"paste",s,!1),this.#rt.get("tabDisable")||this.#_i.addEvent(i,"keydown",Wr,!1),e&&this.#_i.addEvent(i,"scroll",this.$.viewer._scrollLineNumbers.bind(i,e),!1)}const l=t.get("markdown");if(l){this.#_i.addEvent(l,"mousedown",this.#Ca.bind(this,t),!1);const e=t.get("markdownNumbers"),s=this.$.viewer._markdownViewAutoHeight.bind(this.$.viewer,l,e,"auto"===this.$.frameOptions.get("height"));this.#_i.addEvent(l,"keydown",s,!1),this.#_i.addEvent(l,"keyup",s,!1),this.#_i.addEvent(l,"paste",s,!1),this.#rt.get("tabDisable")||this.#_i.addEvent(l,"keydown",Wr,!1),e&&this.#_i.addEvent(l,"scroll",this.$.viewer._scrollMarkdownLineNumbers.bind(l,e),!1)}t.has("statusbar")&&this.__addStatusbarEvent(t,t.get("options"));const a=this.#_a.bind(this),h=Pe.query.getScrollParents(t.get("originElement"));for(const t of h)this.scrollparents.push(t),this.#_i.addEvent(t,"scroll",a,!1);this.#_i.addEvent(this.__focusTemp,"focus",(t=>t.preventDefault()),!1),this.__eventDoc!==t.get("_wd")&&(this.__eventDoc=t.get("_wd"),this.#_i.addEvent(this.__eventDoc,"selectionchange",this.#ka.bind(this,this.__eventDoc),!1))}__addStatusbarEvent(t,e){/\d+/.test(e.get("height"))&&e.get("statusbar_resizeEnable")?e.set("__statusbarEvent",this.#_i.addEvent(t.get("statusbar"),"mousedown",this.#xa.bind(this),!1)):Pe.utils.addClass(t.get("statusbar"),"se-resizing-none")}_removeAllEvents(){this.#_i._init(),this._wwFrameObserver&&(this._wwFrameObserver.disconnect(),this._wwFrameObserver=null),this._toolbarObserver&&(this._toolbarObserver.disconnect(),this._toolbarObserver=null),this.#ra&&(Fr.clearTimeout(this.#ra),this.#ra=null),this.__retainTimer&&(Fr.clearTimeout(this.__retainTimer),this.__retainTimer=null),this.#aa&&=this.#_i.removeGlobalEvent(this.#aa),this.#ha&&=this.#_i.removeGlobalEvent(this.#ha),this.#la&&=this.#_i.removeGlobalEvent(this.#la),this._formatAttrsTemp=null,this.__cacheStyleNodes=null,this.__inputPlugin=null,this.__inputBlurEvent=null,this.__inputKeyEvent=null,this.__focusTemp=null,this.__eventDoc=null,this.__secopy=null,this._lineBreakComp=null,this.scrollparents=null}_setSelectionSync(){this.#_i.removeGlobalEvent(this.#aa),this.#aa=this.#_i.addGlobalEvent("mouseup",(()=>{this.$.selection.init(),this.#_i.removeGlobalEvent(this.#aa)}))}_retainStyleNodes(t,e){let s=e[0].cloneNode(!1);for(let t,i=1,n=e.length;i",this.$.selection.setRange(t,0,t,0)}_callPluginEvent(t,e){return this.$.pluginManager.emitEvent(t,e)}async _callPluginEventAsync(t,e){return await this.$.pluginManager.emitEventAsync(t,e)}__removeInput(){this.#t.set("_preventBlur",!1),this._inputFocus=!1,this.__inputBlurEvent=this.#_i.removeEvent(this.__inputBlurEvent),this.__inputKeyEvent=this.#_i.removeEvent(this.__inputKeyEvent),this.__inputPlugin=null}__postFocusEvent(t,e){(this.#t.mode.isInline||this.#t.mode.isBalloonAlways)&&this.#o.show(),this.#t.mode.isSubBalloonAlways&&this.$.subToolbar.show(),this.#o._resetSticky(),this.#na._updatePlaceholder(t),this.#_i.triggerEvent("onFocus",{frameContext:t,event:e}),this._callPluginEvent("onFocus",{frameContext:t,event:e})}__postBlurEvent(t,e){this.#t.mode.isInline?Fr.setTimeout((()=>{this.#t.get("hasFocus")||this._hideToolbar()}),0):this.#t.mode.isBalloon&&this._hideToolbar(),this.#t.mode.isSubBalloon&&this._hideToolbar_sub(),this.#_i.triggerEvent("onBlur",{frameContext:t,event:e}),this._callPluginEvent("onBlur",{frameContext:t,event:e})}__setViewportSize(){this.#t.set("currentViewportHeight",De.get(Fr.visualViewport.height,0))}#$a(){this.#oa.currentDropdownActiveButton&&this.#oa.currentDropdown&&this.#oa.__resetMenuPosition(this.#oa.currentDropdownActiveButton,this.#oa.currentDropdown),this.#na._repositionControllers()}#Sa(){Oe.isResizeObserverSupported||(this.#o.resetResponsiveToolbar(),this.#rt.get("_subMode")&&this.$.subToolbar.resetResponsiveToolbar());const t=this.#e.get("toolbar_main"),e="none"===t.style.display||this.#t.mode.isInline&&!this.#o.inlineToolbarAttr.isShow;if(0===t.offsetWidth&&!e)return;const s=this.#na.opendBrowser;if(s&&"block"===s.area.style.display&&(s.body.style.maxHeight=Pe.utils.getClientSize().h-s.header.offsetHeight-50+"px"),this.#oa.currentDropdownActiveButton&&this.#oa.currentDropdown&&this.#oa.__resetMenuPosition(this.#oa.currentDropdownActiveButton,this.#oa.currentDropdown),this.$.viewer._resetFullScreenHeight())return;const i=this.$.frameContext;i.get("isCodeView")&&this.#t.mode.isInline?this.#o._showInline():(this.#na._iframeAutoHeight(i),this.#o.isSticky&&(this.#o.isCSSSticky||(this.#e.get("toolbar_main").style.width=i.get("topArea").offsetWidth-2+"px"),this.#o._resetSticky()))}#fa(t,e,s){this.#na._syncScrollPosition(e),this.#$a(),this._callPluginEvent("onScroll",{frameContext:t,event:s}),t.has("documentType_use_page")&&t.get("documentType").scrollPage(),this.#_i.triggerEvent("onScroll",{frameContext:t,event:s})}#va(t,e){if(this.$.selection.__iframeFocus||t.get("isReadOnly")||t.get("isDisabled"))return e.preventDefault(),!1;this.#t.set("hasFocus",!0),this.$.component.__prevent=!1,this.#_i.triggerEvent("onNativeFocus",{frameContext:t,event:e});const s=t.get("key");this._inputFocus?this.#t.mode.isInline&&Fr.setTimeout((()=>{this.#o._showInline()}),0):this.#t.get("rootKey")===s&&this.#t.get("_preventBlur")||this.#t.get("_preventFocus")||(this.#t.set("_preventFocus",!0),Pe.utils.removeClass(this.$.commandDispatcher.targets.get("codeView"),"active"),this.#na._toggleCodeViewButtons(!1),this.$.facade.changeFrameContext(s),this.$.history.resetButtons(s,null),Fr.setTimeout((()=>{this.__postFocusEvent(t,e)}),0))}#ba(t,e){t.get("isCodeView")||t.get("isReadOnly")||t.get("isDisabled")||(this.#t.set("hasFocus",!1),this.#t.set("_lastSelectionNode",null),this.#_i.triggerEvent("onNativeBlur",{frameContext:t,event:e}),this.#na._updatePlaceholder(t),this._inputFocus||this.#t.get("_preventBlur")||(this.#t.set("_preventFocus",!1),this.selectionState.reset(),this.#t.set("currentNodes",[]),this.#t.set("currentNodesMap",[]),this.#na.offCurrentController(),this.#Ci.applyToRoots((t=>{t.get("navigation")&&(t.get("navigation").textContent="")})),this.$.history.check(t.get("key"),this.#t.get("_range")),this.__postBlurEvent(t,e)))}#xa(t){t.stopPropagation(),this._resizeClientY=t.clientY,this.#na.enableBackWrapper("ns-resize"),this.#ha=this.#_i.addGlobalEvent("mousemove",this.#Ea.bind(this)),this.#la=this.#_i.addGlobalEvent("mouseup",this.#Ta.bind(this))}#Ea(t){const e=this.$.frameContext,s=e.get("wrapper").offsetHeight+(t.clientY-this._resizeClientY),i=s"),"byte-html"!==this.$.frameOptions.get("charCounter_type")||this.$.char.check(n.outerHTML)){s.parentNode.insertBefore(n,"t"===t?s:s.nextSibling),this.$.component.deselect();try{const t=i?n:n.firstChild;this.$.selection.setRange(t,1,t,1),this.$.history.push(!1)}catch(t){console.warn("[SUNEDITOR.lineBreaker.error]",t)}}}#ua(){this.#t.set("initViewportHeight",Fr.visualViewport.height),Hr||this.#na.offCurrentController(),this.#t.mode.isBalloon?this.#o.hide():this.#t.mode.isSubBalloon&&this.$.subToolbar.hide(),this.#Sa()}#pa(){Hr&&this.#rt.get("_toolbar_sticky")>-1&&(this.#o._resetSticky(),this.#oa.__restoreMenuPosition()),this.#$a();const t=this.#t.get("currentViewportHeight");this.__setViewportSize(),Hr&&t>0&&t-Fr.visualViewport.height>100&&this.#t.get("hasFocus")&&this.$.selection.scrollTo(this.$.selection.getRange(),{behavior:"auto",block:"nearest",inline:"nearest"})}#ga(){this.#rt.get("_toolbar_sticky")>-1&&this.#o._resetSticky(),this.#t.mode.isBalloon&&"block"===this.#e.get("toolbar_main").style.display?this.#o._setBalloonOffset("top"===this.#o.balloonOffset.position):this.#t.mode.isSubBalloon&&"block"===this.#e.get("toolbar_sub_main").style.display&&this.$.subToolbar._setBalloonOffset("top"===this.$.subToolbar.balloonOffset.position),this.#$a(),this.#na.blockHandle?.syncScroll(),this.$.frameContext.has("documentType_use_page")&&this.$.frameContext.get("documentType").scrollWindow()}#ma(){this.#rt.get("_toolbar_sticky")>-1&&(this.#o._resetSticky(),this.#oa.__restoreMenuPosition())}#ka(t){let e=t.getSelection().anchorNode;this.#Ci.applyToRoots((t=>{if(e&&t.get("wysiwyg").contains(e)){if(t.get("isReadOnly")||t.get("isDisabled"))return;if(e=null,this.$.selection.init(),this.applyTagEffect(),this.#na._updatePlaceholder(t),qr&&(this.#t.mode.isBalloon||this.#t.mode.isSubBalloon)&&this.#ca(),t.has("documentType_use_header")){const e=Pe.query.getParentElement(this.$.selection.selectionNode,this.$.format.isLine.bind(this.$.format));t.get("documentType").on(e)}}}))}#_a(){this.#oa.dropdownOff(),this.#$a(),this.#na.blockHandle?.syncScroll()}#ya(t){this.$.facade.changeFrameContext(t.get("key")),Pe.utils.addClass(this.$.commandDispatcher.targets.get("codeView"),"active"),this.#na._toggleCodeViewButtons(!0)}#Ca(t){this.$.facade.changeFrameContext(t.get("key")),Pe.utils.addClass(this.$.commandDispatcher.targets.get("markdownView"),"active"),this.#na._toggleCodeViewButtons(!0)}};const Vr=class{#Ma=new Map;#Na=new Map;$=null;constructor(t,e){const{product:s,options:i}=e;this.store=new _s(s),this.$={facade:t,store:this.store},this.#Ba(s,i),this.#Ia(),this.#La(s),this.#Aa(),this.#Oa(),this._eventOrchestrator=new Ur(this),this.#Ma.get("eventManager")._bindOrchestrator(this._eventOrchestrator)}#Ba(t,e){const s=new $s(t),i=new Ss(this,t,e);this.#Ma.set("contextProvider",s),this.#Ma.set("optionProvider",i),this.#Ma.set("instanceCheck",new Es(s.frameContext)),this.#Ma.set("eventManager",new Bs(s,i,this.$))}#Ia(){const t=this.#Ma.get("contextProvider"),e=this.#Ma.get("optionProvider");Object.assign(this.$,{contextProvider:t,optionProvider:e,instanceCheck:this.#Ma.get("instanceCheck"),eventManager:this.#Ma.get("eventManager"),frameRoots:t.frameRoots,context:t.context,options:e.options,icons:t.icons,lang:t.lang,frameContext:t.frameContext,frameOptions:e.frameOptions})}#La(t){this.#Na.set("offset",new Is(this)),this.#Na.set("selection",new As(this)),this.#Na.set("html",new fi(this)),this.#Na.set("nodeTransform",new vi(this)),this.#Na.set("format",new Rs(this)),this.#Na.set("inline",new Ps(this)),this.#Na.set("listFormat",new Fs(this)),this.#Na.set("char",new yi(this)),this.#Na.set("shortcuts",new wi(this)),this.#Na.set("component",new tn(this)),this.#Na.set("pluginManager",new en(this,t)),this.#Na.set("focusManager",new sn(this)),this.#Na.set("ui",new Mn(this)),this.#Na.set("commandDispatcher",new $n(this)),this.#Na.set("toolbar",new Rn(this,{keyName:"toolbar",balloon:this.store.mode.isBalloon,balloonAlways:this.store.mode.isBalloonAlways,inline:this.store.mode.isInline,res:t.responsiveButtons})),this.$.options.has("_subMode")&&this.#Na.set("subToolbar",new Rn(this,{keyName:"toolbar_sub",balloon:this.store.mode.isSubBalloon,balloonAlways:this.store.mode.isSubBalloonAlways,inline:!1,res:t.responsiveButtons_sub})),this.#Na.set("menu",new Fn(this)),this.#Na.set("viewer",new Un(this)),this.#Na.set("finder",new Kn(this)),this.#Na.set("history",An(this))}#Oa(){for(const[,t]of this.#Na)"function"==typeof t?._init&&t._init()}#Aa(){const t=this.#Na.get("pluginManager");Object.assign(this.$,{offset:this.#Na.get("offset"),selection:this.#Na.get("selection"),format:this.#Na.get("format"),inline:this.#Na.get("inline"),listFormat:this.#Na.get("listFormat"),html:this.#Na.get("html"),nodeTransform:this.#Na.get("nodeTransform"),char:this.#Na.get("char"),component:this.#Na.get("component"),focusManager:this.#Na.get("focusManager"),pluginManager:t,plugins:t.plugins,ui:this.#Na.get("ui"),commandDispatcher:this.#Na.get("commandDispatcher"),history:this.#Na.get("history"),shortcuts:this.#Na.get("shortcuts"),toolbar:this.#Na.get("toolbar"),subToolbar:this.#Na.get("subToolbar"),menu:this.#Na.get("menu"),viewer:this.#Na.get("viewer"),finder:this.#Na.get("finder")})}_destroy(){if(null===this.$)return;const t=[];for(const[e,s]of this.#Na)try{s?._destroy?.()}catch(s){t.push(`[Logic:${e}] ${s.message}`)}this.#Na.clear();try{this._eventOrchestrator?._removeAllEvents()}catch(e){t.push(`[EventOrchestrator] ${e.message}`)}this._eventOrchestrator=null;for(const[e,s]of this.#Ma)try{s?._destroy?.()}catch(s){t.push(`[Config:${e}] ${s.message}`)}this.#Ma.clear(),t.length>0&&console.warn("[CoreKernel._destroy] Cleanup completed with errors:",t),this.$=null,this.store._destroy(),this.store=null,this.facade=null}};const jr=class{#H;$;constructor(t,e){const s=bs(t,e),i=new Vr(this,{product:s,options:e});this.#H=i,this.$=i.$,this.#Ra(e).catch((t=>{console.error("[SUNEDITOR:E_CREATE_FAIL] Failed to create editor instance.",t)}))}isEmpty(t){const e=(t||this.$.frameContext).get("wysiwyg");return Pe.check.isZeroWidth(e.textContent)&&!e.querySelector(this.$.options.get("allowedEmptyTags"))&&(e.innerText.match(/\n/g)||"").length<=1}resetOptions(t){this.$.optionProvider.reset(t),this.$.store.set("_lastSelectionNode",null),this.#za(this.$.frameRoots.get(this.$.store.get("rootKey")));for(const t of Object.values(this.$.plugins))t.init?.()}changeFrameContext(t){t!==this.$.store.get("rootKey")&&(this.$.store.set("rootKey",t),this.#za(this.$.frameRoots.get(t)),this.$.toolbar._resetSticky())}destroy(){this.$.options.get("hasCodeMirror")&&this.$.contextProvider.applyToRoots((t=>{const e=t.get("options").get("codeMirrorEditor");e&&e.toTextArea()})),Pe.utils.removeItem(this.$.context.get("toolbar_wrapper")),Pe.utils.removeItem(this.$.context.get("toolbar_sub_wrapper")),Pe.utils.removeItem(this.$.context.get("statusbar_wrapper"));for(const t in this.events)this.events[t]=null;return this.events=null,this.#H._destroy(),null}#za(t){this.$.contextProvider.reset(t),this.$.optionProvider.resetFrame(t.get("options")),this.$.ui.reset(t)}#Pa(t){this.$.store.set("initViewportHeight",Oe._w.visualViewport.height),this.#H._eventOrchestrator.__setViewportSize(),this.$.store.set("_canUseBeforeInput",Oe.canUseBeforeInput()),this.$.contextProvider.init(),this.#za(this.$.frameRoots.get(this.$.store.get("rootKey"))),this.#Ts(t),this.$.contextProvider.applyToRoots((t=>{this.#H._eventOrchestrator._addFrameEvents(t),this.#Da(t,t.get("options").get("value")),t.get("options").get("iframe")&&"auto"===t.get("options").get("height")&&this.$.ui._emitResizeEvent(t,t.get("wysiwygFrame").offsetHeight,null)})),this.#H._eventOrchestrator.__eventDoc=null,this.$.store._editorInitFinished=!0,this.$.pluginManager.checkFileInfo(!0),this.$.history.reset(),Oe._w.setTimeout((()=>{if(this.$.context?.size){this.$.context.get("toolbar_main").style.visibility="",this.$.contextProvider.applyToRoots((t=>{this.#H._eventOrchestrator._wwFrameObserver&&this.#H._eventOrchestrator._wwFrameObserver.observe(t.get("wysiwygFrame")),this.#H._eventOrchestrator._toolbarObserver&&this.#H._eventOrchestrator._toolbarObserver.observe(t.get("_toolbarShadow")),this.$.ui._syncFrameState(t)}));for(const t of Object.values(this.$.plugins))t.init?.();this.$.selection.__init(),this.$.eventManager.triggerEvent("onload",{})}else console.warn("[SUNEDITOR:E_INIT_FAIL] Editor instance was destroyed before initialization completed. Check if destroy() was called.")}),0)}#Da(t,e){if(t.get("wysiwyg").innerHTML=this.$.html.clean("string"==typeof e?e:(/^TEXTAREA$/i.test(t.get("originElement").nodeName)?t.get("originElement").value:t.get("originElement").innerHTML)||"",{forceFormat:!0,whitelist:null,blacklist:null,_freeCodeViewMode:this.$.options.get("freeCodeViewMode")})||"<"+this.$.options.get("defaultLine")+">
    ",t.has("charCounter")&&(t.get("charCounter").textContent=String(this.$.char.getLength())),t.has("wordCounter")&&(t.get("wordCounter").textContent=String(this.$.char.getWordCount())),"document"===this.$.options.get("type")&&(t.set("documentType",new Cs(this.#H,t)),t.get("documentType").useHeader&&t.set("documentType_use_header",!0),t.get("documentType").usePage)){t.set("documentType_use_page",!0);const e=t.get("documentTypePageMirror"),s=e.ownerDocument.createDocumentFragment();for(let e=t.get("wysiwyg").firstChild;e;e=e.nextSibling)s.appendChild(e.cloneNode(!0));e.replaceChildren(s)}}#Ts(t){this.$.pluginManager.init(t),this.$.shortcuts._registerShortcuts(),this.$.commandDispatcher._initCommandButtons(),this.$.ui.init()}#Fa(t,e,s){t.contentDocument.documentElement.className="sun-editor",t.contentDocument.head.innerHTML=''+ze._setIframeStyleLinks(s.get("iframe_cssFileName"))+ze._setAutoHeightStyle(s.get("height")),t.contentDocument.body.className=e.get("_editableClass"),t.contentDocument.body.setAttribute("contenteditable","true"),e.get("_rtl")&&(t.contentDocument.body.dir="rtl")}async#Ra(t){this.#H._eventOrchestrator._addCommonEvents();const e=[];this.$.contextProvider.applyToRoots((t=>{const s=t.get("originElement"),i=t.get("topArea");if(s.style.display="none",i.style.display="block",s.parentNode.insertBefore(i,s.nextElementSibling),t.get("options").get("iframe")){const s=new Promise((e=>{const s=s=>{this.#Fa(s,this.$.optionProvider.options,t.get("options")),e()};if(Oe.isGecko){let e=null;this.$.eventManager.addEvent(t.get("wysiwygFrame"),"load",(({target:t})=>{clearTimeout(e),e=setTimeout((()=>{this.$&&s(t)}),60)}))}else this.$.eventManager.addEvent(t.get("wysiwygFrame"),"load",(({target:t})=>{s(t)}))}));e.push(s)}})),this.$.contextProvider.applyToRoots((t=>{t.get("wrapper").appendChild(t.get("wysiwygFrame")),t.get("documentTypeInner")&&t.get("wrapper").insertBefore(t.get("documentTypeInner"),t.get("wysiwygFrame")),t.get("documentTypePage")&&(t.get("wrapper").appendChild(t.get("documentTypePage")),t.get("wrapper").appendChild(t.get("documentTypePageMirror"))),t.get("blockHandleArea")&&t.get("wrapper").insertBefore(t.get("blockHandleArea"),t.get("wysiwygFrame"))})),e.length>0&&await Promise.all(e),this.#Pa(t)}};function Gr(t){let e;try{e=t.responseText}catch{return`status ${t.status}`}if(!e)return`status ${t.status}`;try{return JSON.parse(e)}catch{return e}}const Kr=class{#J;#Ha;constructor(t,e,s){this.#J=e,this.kind=t.constructor.key||t.constructor.name,this.#Ha=Oe.getXMLHttpRequest(),this.method=s?.method,this.url=s?.url,this.headers=s?.headers,this.data=s?.data,this.callBack=s?.callBack,this.errorCallBack=s?.errorCallBack,this.responseType=s?.responseType}call({method:t,url:e,headers:s,data:i,callBack:n,errorCallBack:o,responseType:r}){if(this.cancel(),t||=this.method,e=this.#qa(e||this.url),s||=this.headers,i||=this.data,n||=this.callBack,o||=this.errorCallBack,r||=this.responseType,"function"!=typeof n)throw new Error(`[SUNEDITOR.ApiManager[${this.kind}].upload.callBack.fail] callBack is not a function`);const l=this.#Ha;if(r&&(l.responseType=r),l.onreadystatechange=this.#Wa.bind(this,l,n,o),l.open(t,e,!0),null!==s&&"object"==typeof s&&Object.keys(s).length>0)for(const t in s)l.setRequestHeader(t,s[t]);l.send(i)}asyncCall({method:t,url:e,headers:s,data:i,responseType:n}){this.cancel(),t||=this.method,e=this.#qa(e||this.url),s||=this.headers,i||=this.data,n||=this.responseType;const o=this.#Ha;return n&&(o.responseType=n),new Promise(((n,r)=>{if(o.open(t,e,!0),null!==s&&"object"==typeof s&&Object.keys(s).length>0)for(const t in s)o.setRequestHeader(t,s[t]);o.onload=()=>{if(200===o.status)try{n(o)}finally{this.#J.ui.hideLoading()}else{console.error(`[SUNEDITOR.ApiManager[${this.kind}].upload.serverException]`,o);try{r(Gr(o))}finally{this.#J.ui.hideLoading()}}},o.onerror=()=>{this.#J.ui.hideLoading(),r(new Error("Network error"))},o.send(i)}))}cancel(){this.#Ha&&(this.#Ha.onreadystatechange=null,this.#Ha.onload=null,this.#Ha.onerror=null,this.#Ha.abort())}#qa(t){return t?t.replace(/([^:])\/+/g,"$1/").replace(/\/(\?|#|$)/,"$1"):""}async#Wa(t,e,s){if(4===t.readyState)if(200===t.status)try{await e(t)}catch(t){throw Error(`[SUNEDITOR.ApiManager[${this.kind}].upload.callBack.fail] ${t.message}`)}finally{this.#J.ui.hideLoading()}else{console.error(`[SUNEDITOR.ApiManager[${this.kind}].upload.serverException]`,t);try{const e=Gr(t);let i="";"function"==typeof s&&(i=await s(e,t));const n=`[SUNEDITOR.ApiManager[${this.kind}].upload.serverException] status: ${t.status}, response: ${i||e.errorMessage||("string"==typeof e?e:JSON.stringify(e))}`;this.#J.ui.alertOpen(n,"error")}catch(t){throw Error(`[SUNEDITOR.ApiManager[${this.kind}].upload.errorCallBack.fail] ${t.message}`)}finally{this.#J.ui.hideLoading()}}}};function Yr(t){const e=t.src.split("/").pop(),s=t.thumbnail||"",i=s||t.src,n=this.props?.map((e=>`data-${e}="${t[e]}"`)).join(" ")||"",o=`data-type="${t.type}" data-command="${t.src}" data-name="${t.name||e}" data-thumbnail="${s}" data-extension="${t.src.split(".").pop()}" ${n}`,r=`class="${s||"se-browser-empty-image"}" src="${i}" alt="${t.alt||e}" ${o}`;return`\n\t\t
    \n\t\t\t${this.thumbnail&&!s&&"image"!==t.type?`
    ${this.thumbnail(t)}
    `:``}\n\t\t\t
    \n\t\t\t
    ${t.name||e}
    \n\t\t
    `}const Xr=class{#J;#Ua;#rr;#Va=[];#ja;#Ga;#So=!1;#No=null;constructor(t,e,s){this.#J=e,this.useSearch=s.useSearch??!0;const i=Pe.utils.createElement("DIV",{class:"se-browser sun-editor-common"+(s.className?` ${s.className}`:"")}),n=function(t,e){const s=t.lang,i=t.icons,n=`\n\t\t
    \n\t\t\t
    \n\t\t\t\t\n\t\t\t\t\n\t\t\t
    \n\t\t\t
    \n\t\t\t\t
    \n\t\t\t\t
    \n\t\t\t\t\t
    \n\t\t\t\t\t\t\n\t\t\t\t\t
    \n\t\t\t\t\t
    \n\t\t\t\t\t\t
    \n\t\t\t\t\t\t
    \n\t\t\t\t\t\t
    \n\t\t\t\t\t\t
    \n\t\t\t\t\t
    \n\t\t\t\t
    \n\t\t\t
    \n\t\t
    `,o=Pe.utils.createElement("DIV",{class:"se-browser-inner"},n);return{html:o,header:o.querySelector(".se-browser-header"),titleArea:o.querySelector(".se-browser-title"),tagArea:o.querySelector(".se-browser-tags"),body:o.querySelector(".se-browser-body"),list:o.querySelector(".se-browser-list"),side:o.querySelector(".se-browser-side"),wrapper:o.querySelector(".se-browser-wrapper"),_loading:o.querySelector(".se-loading-box")}}(this.#J,this.useSearch),o=n.html;this.kind=t.constructor.key||t.constructor.name,this.host=t,this.area=i,this.header=n.header,this.titleArea=n.titleArea,this.tagArea=n.tagArea,this.body=n.body,this.list=n.list,this.side=n.side,this.wrapper=n.wrapper,this.#Ua=n._loading,this.title=s.title,this.listClass=s.listClass||"se-preview-list",this.directData=s.data,this.url=s.url,this.headers=s.headers,this.searchUrl=s.searchUrl,this.searchHeaders=s.searchHeaders,this.drawItemHandler=(s.drawItemHandler||Yr).bind({thumbnail:s.thumbnail,props:s.props||[]}),this.selectorHandler=s.selectorHandler,this.columnSize=s.columnSize||4,this.expand=s.expand??1,this.folderDefaultPath="",this.closeArrow=this.#J.icons.menu_arrow_right,this.openArrow=this.#J.icons.menu_arrow_down,this.icon_folder=this.#J.icons.side_menu_folder_item,this.icon_folder_item=this.#J.icons.side_menu_folder,this.icon_item=this.#J.icons.side_menu_item,this.items=[],this.folders={},this.tree={},this.data={},this.selectedTags=[],this.keyword="",this.sideInner=null,this.apiManager=new Kr(this,e,{method:"GET"}),this.#rr=t=>{Fe.isEsc(t.code)&&this.close()},i.appendChild(Pe.utils.createElement("DIV",{class:"se-browser-back"})),i.appendChild(o),i.setAttribute("popover","manual"),this.#J.contextProvider.carrierWrapper.appendChild(i),this.#J.eventManager.addEvent(this.tagArea,"click",this.#Ka.bind(this)),this.#J.eventManager.addEvent(this.list,"click",this.#Ya.bind(this)),this.#J.eventManager.addEvent(this.side,"click",this.#Xa.bind(this)),this.#J.eventManager.addEvent(o,"mousedown",this.#Za.bind(this)),this.#J.eventManager.addEvent(o,"click",this.#Ja.bind(this)),this.#J.eventManager.addEvent(this.sideOpenBtn=i.querySelector(".se-side-open-btn"),"click",this.#Qa.bind(this)),this.#J.eventManager.addEvent([this.header,i.querySelector(".se-browser-main")],"mousedown",this.#th.bind(this));const r=i.querySelector("form.se-browser-search-form");this.#ja=r?.querySelector('input[type="text"]'),this.#Ga=i.querySelector(".se-browser-search-clear"),this.#J.eventManager.addEvent(r,"submit",this.#eh.bind(this)),this.#J.eventManager.addEvent(this.#Ga,"click",this.#sh.bind(this))}open(t={}){this.#qe();const e=t.listClass||this.listClass;Pe.utils.hasClass(this.list,e)||(this.list.className="se-browser-list "+e),this.titleArea.textContent=t.title||this.title,this.area.style.display="block",this.area.showPopover?.(),this.#J.ui.opendBrowser=this,this.closeArrow=this.#J.options.get("_rtl")?this.#J.icons.menu_arrow_left:this.#J.icons.menu_arrow_right,this.directData?this.#ih(this.directData):this.#nh(t.url||this.url,t.headers||this.headers,!1),this.body.style.maxHeight=Pe.utils.getClientSize().h-(this.#J.offset.getGlobal(this.body).top-o.scrollY)-20+"px"}close(){this.#je(),this.apiManager.cancel(),this.area.hidePopover?.(),this.area.style.display="none",this.selectedTags=[],this.items=[],this.#Va=[],this.folders={},this.tree={},this.data={},this.keyword="",this.list.innerHTML=this.tagArea.innerHTML=this.titleArea.textContent="",this.#ja&&(this.#ja.value=""),this.#Ga&&(this.#Ga.style.display="none"),this.#J.ui.opendBrowser=null,this.sideInner=null,this.host.browserInit?.()}search(t){if(this.searchUrl){this.keyword=t;const e=this.searchUrl.includes("?")?"&":"?";this.#nh(this.searchUrl+e+"keyword="+o.encodeURIComponent(t),this.searchHeaders,!1)}else this.keyword=t.toLowerCase(),this.#oh(this.#Va.length>0?this.#Va:this.items,!1)}#rh(){const t=[];for(const e in this.data){const s=this.data[e];if(Array.isArray(s))for(let e=0;e!Array.isArray(t.tag)||t.tag.some((t=>e.includes(t)))))}showBrowserLoading(){this.#Ua.style.display="block"}closeBrowserLoading(){this.#Ua.style.display="none"}#nh(t,e,s){this.apiManager.call({method:"GET",url:t,headers:e,callBack:this.#lh.bind(this),errorCallBack:this.#ah.bind(this)}),s||(this.sideOpenBtn.style.display="none",this.showBrowserLoading())}#oh(t,e){const s=this.keyword,i=[],n=(t=this.tagfilter(t).filter((t=>t.name.toLowerCase().indexOf(s)>-1))).length,o=this.columnSize,r=o<=1?1:Math.round(n/o)||1,l=this.drawItemHandler;let a="",h='
    ',c=1;for(let s,d,u=0;ut.trim())),h+=l(s),(u+1)%r==0&&c
    '),e&&d.length>0)for(let t,e=0,s=d.length;e${t}`);h+="
    ",this.list.innerHTML=h,s&&this.#hh(s),e&&(this.items=t,this.tagArea.innerHTML=a)}#qe(){this.#je(),this.#No=this.#J.eventManager.addGlobalEvent("keydown",this.#rr,!0)}#je(){this.#No&&=this.#J.eventManager.removeGlobalEvent(this.#No)}#ih(t){if(Array.isArray(t))return t.length>0&&this.#oh(t,!0),!0;if("object"==typeof t){this.sideOpenBtn.style.display="",this.#ch(t),this.#Va=this.#rh(),this.side.innerHTML="";const e=this.sideInner=Pe.utils.createElement("div",null);if(this.#dh(this.tree,e),this.side.appendChild(e),this.folderDefaultPath){const t=e.querySelector(`[data-command="${this.folderDefaultPath}"]`);t.click(),this.folderDefaultPath.includes("/")&&(Pe.utils.removeClass(t.parentElement,"se-menu-hidden"),t.parentElement.previousElementSibling.querySelector("button").innerHTML=this.openArrow)}return!0}return!1}#ch(t,e){let s=this.tree;if(t._data){this.data[e]=t._data,this.folderDefaultPath&&!t.default||(this.folderDefaultPath=e);const i=e.split("/"),n=i.length-1;i.forEach(((t,i)=>{s[t]||={children:{}},i===n?(s[t].key=e,s[t].name=this.folders[e].name):s=s[t].children}))}else e&&(s[e]={name:this.folders[e].name,children:{}});Object.entries(t).forEach((([t,s])=>{if("_data"===t||!s||"object"!=typeof s)return;const i=s,n=e?`${e}/${t}`:t;this.folders[n]={name:i.name||t,meta:i.meta||{}},this.#ch(i,n)}))}#dh(t,e,s=0){const i=s0){const t=Pe.utils.createElement("div",o.key?{"data-command":o.key,"aria-label":o.name}:null,`${o.key?this.icon_folder:this.icon_folder_item}${o.name}`),n=Pe.utils.createElement("div",{class:"se-menu-folder"},t);t.insertBefore(Pe.utils.createElement("button",{type:"button"},i?this.openArrow:this.closeArrow),t.firstElementChild);const r=document.createElement("div");Pe.utils.addClass(r,i?"se-menu-child":"se-menu-child|se-menu-hidden"),this.#dh(o.children,r,s+1),n.appendChild(r),e.appendChild(n)}else{const t=Pe.utils.createElement("div",{"data-command":o.key,"aria-label":o.name,class:"se-menu-folder-item"},`${this.icon_item}${o.name}`);if(e===this.sideInner){const s=Pe.utils.createElement("div",{class:"se-menu-folder"},t);e.appendChild(s)}else e.appendChild(t)}}}#lh(t){try{const e=JSON.parse(t.responseText),s=e.result;if(this.#ih(s))return;e.nullMessage&&(this.list.innerHTML=e.nullMessage)}catch(t){throw Error(`[SUNEDITOR.browser.drawList.fail] cause: "${t.message}"`)}finally{this.closeBrowserLoading()}}#ah(t,e){throw this.closeBrowserLoading(),Error(`[SUNEDITOR.browser.get.serverException] status: ${e.status}, response: ${t.errorMessage||e.responseText}`)}#Ka(t){const e=Pe.query.getEventTarget(t);if(!Pe.check.isAnchor(e))return;const s=e.textContent,i=this.tagArea.querySelector('a[title="'+s+'"]'),n=this.selectedTags.indexOf(s);n>-1?(this.selectedTags.splice(n,1),Pe.utils.removeClass(i,"on")):(this.selectedTags.push(s),Pe.utils.addClass(i,"on")),this.#oh(this.items,!1)}#Ya(t){const e=Pe.query.getEventTarget(t);if(t.preventDefault(),t.stopPropagation(),e===this.list)return;const s=Pe.query.getCommandTarget(e);s&&(this.close(),this.selectorHandler(s))}#Xa(t){const e=Pe.query.getEventTarget(t);if(t.stopPropagation(),/^button$/i.test(e.nodeName)){const t=e.parentElement.parentElement.querySelector(".se-menu-child");return void(Pe.utils.hasClass(t,"se-menu-hidden")?(Pe.utils.removeClass(t,"se-menu-hidden"),e.innerHTML=this.openArrow):(Pe.utils.addClass(t,"se-menu-hidden"),e.innerHTML=this.closeArrow))}const s=Pe.query.getCommandTarget(e);if(!s||Pe.utils.hasClass(s,"active"))return;const i=this.data[s.getAttribute("data-command")];Pe.utils.removeClass(this.side.querySelectorAll(".active"),"active"),Pe.utils.addClass([s,Pe.query.getParentElement(s,".se-menu-folder")],"active"),this.tagArea.innerHTML="",this.selectedTags=[],"string"==typeof i?this.#nh(i,this.headers,!0):this.#oh(i,!0)}#Za(t){const e=Pe.query.getEventTarget(t);/se-browser-inner/.test(e.className)?this.#So=!0:this.#So=!1}#Ja(t){const e=Pe.query.getEventTarget(t);t.stopPropagation(),(/close/.test(e.getAttribute("data-command"))||this.#So)&&this.close()}#eh(t){t.preventDefault();const e=this.#ja.value;this.search(e),this.#Ga&&(this.#Ga.style.display=e?"":"none")}#sh(){this.#ja&&(this.#ja.value=""),this.#Ga&&(this.#Ga.style.display="none"),this.keyword="",this.#oh(this.items,!1)}#hh(t){const e=this.list.querySelectorAll(".se-file-name-image:not(.se-file-name-back)");for(let s=0;s-1&&(i.innerHTML=n.substring(0,o)+""+n.substring(o,o+t.length)+""+n.substring(o+t.length))}}#Qa(t){const e=Pe.query.getEventTarget(t);Pe.utils.hasClass(e,"active")?(Pe.utils.removeClass(this.side,"se-side-show"),Pe.utils.removeClass(e,"active")):(Pe.utils.addClass(this.side,"se-side-show"),Pe.utils.addClass(e,"active"))}#th({target:t}){t!==this.sideOpenBtn&&Pe.utils.hasClass(this.sideOpenBtn,"active")&&(Pe.utils.removeClass(this.side,"se-side-show"),Pe.utils.removeClass(this.sideOpenBtn,"active"))}},{isTouchDevice:Zr}=Oe,Jr=240,Qr=120,tl={hex:"#FFFFFF",r:255,g:255,b:255,h:0,s:1,l:1};let el,sl=0,il=!1,nl=!1,ol=120,rl=120,ll=tl,al=!1;const{slider:hl,offscreenCanvas:cl,offscreenCtx:dl,wheel:ul,wheelCtx:pl,wheelPointer:gl,gradientBar:ml,gradientPointer:fl,fanalColorHex:vl,fanalColorBackground:bl}=function(){const t=document.createElement("canvas");t.width=Jr,t.height=Jr;const e=`\n\t
    \n \n
    \n
    \n
    \n \n
    \n
    \n
    \n\t\t
    ${tl.hex}
    \n\t\t
    \n\t
    \n\t`,s=Pe.utils.createElement("DIV",{class:"se-hue-slider"},e),i=s.querySelector(".se-hue-wheel"),n=s.querySelector(".se-hue-gradient"),o=s.querySelector(".se-hue-final-hex").children;return{slider:s,offscreenCanvas:t,offscreenCtx:t.getContext("2d"),wheel:i,wheelCtx:i.getContext("2d"),wheelPointer:s.querySelector(".se-hue-wheel-pointer"),gradientBar:n,gradientPointer:s.querySelector(".se-hue-gradient-pointer"),fanalColorHex:o[0],fanalColorBackground:o[1]}}();function yl(t){const{target:e,touches:s}=t,i=s[0].clientX,n=s[0].clientY;e===ul?(t.preventDefault(),nl=!1,il=!0,kl(i,n)):e===ml&&(t.preventDefault(),nl=!0,il=!1,xl(i))}function wl(t){t.preventDefault();const{touches:e}=t,s=e[0].clientX,i=e[0].clientY;il?kl(s,i):nl&&xl(s)}function Cl({target:t,clientX:e,clientY:s}){t===ul?(nl=!1,il=!0,kl(e,s)):t===ml&&(nl=!0,il=!1,xl(e))}function _l({clientX:t,clientY:e}){il?kl(t,e):nl&&xl(t)}function kl(t,e){const s=ul.getBoundingClientRect();t=t-s.left-Qr,e=e-s.top-Qr;const i=180*Math.atan2(e,t)/Math.PI,n=Math.min(Math.sqrt(t*t+e*e),Qr),o=Qr+n*Math.cos(i*Math.PI/180),r=Qr+n*Math.sin(i*Math.PI/180);gl.style.left=`${o}px`,gl.style.top=`${r}px`,function(t,e){ol=t,rl=e,$l(Sl())}(o,r),El()}function xl(t){const e=ml.getBoundingClientRect();let s=t-e.left;s=Math.max(14,Math.min(s,e.width-14)),fl.style.left=`${s}px`,function(t){const e=ml.getBoundingClientRect();let s=t-e.left;s<0&&(s=0);s>e.width&&(s=e.width);const i=14;s>=ml.width-i?s=ml.width:s<=i&&(s=0);const n=1-s/e.width;sl=n,Nl()}(t),El()}function $l(t){const e=ml.getContext("2d"),s=e.createLinearGradient(0,0,ml.width,0);s.addColorStop(0,"black"),s.addColorStop(1,t.hex),e.fillStyle=s,e.fillRect(0,0,ml.width,ml.height)}function Sl(){return Ml(dl)}function El(){el.color=ll=Ml(pl),Tl(ll.hex)}function Tl(t){bl.style.backgroundColor=vl.textContent=t}function Ml(t){const e=t.getImageData(ol,rl,1,1).data;let[s,i,n]=function([t,e,s]){t/=255,e/=255,s/=255;const i=Math.max(t,e,s),n=Math.min(t,e,s);let o,r;const l=(i+n)/2;if(i===n)o=r=0;else{const a=i-n;switch(r=l>.5?a/(2-i-n):a/(i+n),i){case t:o=(e-s)/a+(e1&&(n=1),n<0&&(n=0);const{r:l,g:a,b:h}=function([t,e,s]){let i,n,o;if(0===e)i=n=o=s;else{const r=function(t,e,s){return s<0&&(s+=1),s>1&&(s-=1),s<1/6?t+6*(e-t)*s:s<.5?e:s<2/3?t+(e-t)*(2/3-s)*6:t},l=s<.5?s*(1+e):s+e-s*e,a=2*s-l;i=r(a,l,t+1/3),n=r(a,l,t),o=r(a,l,t-1/3)}return{r:Math.round(255*i),g:Math.round(255*n),b:Math.round(255*o)}}([s,i,n]),c=`#${function({r:t,g:e,b:s}){let i=Math.floor(t).toString(16);t<16&&(i=`0${i}`);let n=Math.floor(e).toString(16);e<16&&(n=`0${n}`);let o=Math.floor(s).toString(16);s<16&&(o=`0${o}`);return`${i}${n}${o}`.toUpperCase()}({r:l,g:a,b:h})}`;return{hex:c,r:l,g:a,b:h,h:s,s:i,l:Il(n)}}function Nl(){pl.clearRect(0,0,Jr,Jr),pl.drawImage(cl,0,0),pl.globalAlpha=sl,pl.fillStyle="black",pl.beginPath(),pl.arc(Qr,Qr,Qr,0,2*Math.PI),pl.fill(),pl.globalAlpha=1}function Bl(t){return t*Math.PI/180}function Il(t){const e=Math.pow(10,10);return Math.round(t*e)/e}function Ll(){!function(t){if(!t)return void console.warn("[HueSlider.fail] Context not found.");for(let e=0;e<=360;e+=.5)for(let s=0;s<=Qr;s+=1){t.beginPath();const i=50+(Qr-s)/Qr*50;t.fillStyle=`hsl(${e}, 100%, ${i}%)`;const n=Qr+Math.cos(Bl(e))*s,o=Qr-Math.sin(Bl(e))*s;t.arc(n,o,1.5,0,2*Math.PI),t.fill()}al=!0}(dl),al&&Nl()}Ll();const Al=class{#J;#uh;#ph;#gh;#mh;#fh;#vh;constructor(t,e,s={},i=""){if(this.#J=e,this.inst=t,this.ctx={wheelX:ol,wheelY:rl,lightness:sl,wheelPointerX:"50%",wheelPointerY:"50%",gradientPointerX:"calc(100% - 14px)",color:tl},this.isOpen=!1,this.controlle=null,this.#uh=null,this.#ph=null,this.#gh=null,this.#mh=null,this.#fh=null,this.#vh=null,!s.isNewForm){const n=function({lang:t,icons:e},s){const i=Pe.utils.createElement("DIV",{class:`se-controller ${s}`},`\n\t\t
    \n\t\t
    \n\t\t\t\n\t\t\t\n\t\t
    \n\t`);return i}(e,i);this.circle=n.querySelector(".se-hue"),this.controller=new Ii(this,e,n,{position:"bottom",isWWTarget:!1,parents:[t.form],parentsHide:!0,...s.controllerOptions})}}controllerAction(t){const e=t.getAttribute("data-command");"submit"===e?(this.inst.hueSliderAction?.(this.get()),this.close()):"close"===e&&this.close()}controllerClose(){this.init(),this.inst.hueSliderCancelAction?.()}get(){return ll}open(t){this.attach(),this.controller.open(t,null,{isWWTarget:!1,initMethod:null,addOffset:null})}close(){this.ctx={gradientPointerX:fl.style.left,wheelPointerX:gl.style.left,wheelPointerY:gl.style.top,wheelX:ol,wheelY:rl,lightness:sl,color:el?.color||""},this.controller.close()}attach(t){al||Ll(),this.init(),(t||this.circle).appendChild(hl),el=this.ctx,el&&(ol=el.wheelX,rl=el.wheelY,sl=el.lightness,gl.style.left=el.wheelPointerX,gl.style.top=el.wheelPointerY,fl.style.left=el.gradientPointerX,Tl(el.color.hex),Nl(),$l(Sl())),Zr&&(this.#fh=this.#J.eventManager.addGlobalEvent("touchstart",yl,{passive:!1,capture:!0}),this.#ph=this.#J.eventManager.addGlobalEvent("touchmove",wl,!0),this.#vh=this.#J.eventManager.addGlobalEvent("touchend",(()=>{il=!1,nl=!1}),!0)),this.#uh=this.#J.eventManager.addGlobalEvent("mousedown",Cl,{passive:!1,capture:!0}),this.#mh=this.#J.eventManager.addGlobalEvent("mousemove",_l,!0),this.#gh=this.#J.eventManager.addGlobalEvent("mouseup",(()=>{il=!1,nl=!1}),!0),this.isOpen=!0}init(){this.isOpen=!1,il=!1,nl=!1,this.#uh&&=this.#J.eventManager.removeGlobalEvent(this.#uh),this.#mh&&=this.#J.eventManager.removeGlobalEvent(this.#mh),this.#gh&&=this.#J.eventManager.removeGlobalEvent(this.#gh),this.#fh&&=this.#J.eventManager.removeGlobalEvent(this.#fh),this.#ph&&=this.#J.eventManager.removeGlobalEvent(this.#ph),this.#vh&&=this.#J.eventManager.removeGlobalEvent(this.#vh)}},Ol=["#ef4444","#f97316","#eab308","#22c55e","#06b6d4","#3b82f6","#8b5cf6","#ec4899","#000000","#fca5a5","#fdba74","#fcd34d","#6ee7b7","#5eead4","#7dd3fc","#c4b5fd","#f9a8d4","#e5e7eb","#fee2e2","#ffedd5","#fef9c3","#dcfce7","#cffafe","#dbeafe","#ede9fe","#fce7f3","#f3f4f6","#f87171","#fb923c","#facc15","#4ade80","#22d3ee","#60a5fa","#a78bfa","#f472b6","#9ca3af","#b91c1c","#c2410c","#a16207","#15803d","#0e7490","#1d4ed8","#6d28d9","#be185d","#4b5563","#7f1d1d","#7c2d12","#713f12","#14532d","#164e63","#1e3a8a","#4c1d95","#831843","#1f2937"];function Rl(t,e){const s=`
      `;let i=s;for(let n,o,r,l=0,a=t.length;l0&&l%e==0&&(i+=`
    ${s}`),i+=`
  • `;return i+="",i}const zl=class{#J;constructor(t,e,s,i){this.#J=e,this.kind=t.constructor.key||t.constructor.name,this.host=t,this.form=i.form,this.target=function({lang:t,icons:e},{colorList:s,disableHEXInput:i,disableRemove:n,splitNum:o}){s||=Ol,o=s===Ol?9:o;let r="";for(let t,e=0,i=s.length,n=[];e0&&(r+=`
    ${Rl(n,o)}
    `,n=[]),"object"==typeof t&&(r+=`
    ${Rl(t,o)}
    `)));return r+=`\n\t\t
    \n\t\t\t${i?"":``}\n\t\t\t\n\t\t\t${i?"":``}\n\t\t\t${n?"":``}\n\t\t
    `,Pe.utils.createElement("DIV",{class:"se-list-inner"},r)}(this.#J,i),this.targetButton=null,this.inputElement=this.target.querySelector(".se-color-input"),this.styleProperties=s,this.splitNum=i.splitNum||0,this.defaultColor=i.defaultColor||"",this.hueSliderOptions=i.hueSliderOptions,this.currentColor="",this.colorList=this.target.querySelectorAll("li button")||[],this.hueSlider=null;const n=(new DOMParser).parseFromString(this.#J.icons.color_checked,"image/svg+xml");this.checkedIcon=n.documentElement,i.disableHEXInput||(this.hueSlider=new Al(this,e,i.hueSliderOptions,"se-dropdown"),this.#J.eventManager.addEvent(this.target.querySelector(".__se_hue"),"click",this.#bh.bind(this)),this.#J.eventManager.addEvent(this.inputElement,"input",this.#yh.bind(this)),this.#J.eventManager.addEvent(this.target.querySelector("form"),"submit",this.#wh.bind(this))),i.disableRemove||this.#J.eventManager.addEvent(this.target.querySelector(".__se_remove"),"click",this.#Ch.bind(this)),this.#J.eventManager.addEvent(this.target,"click",this.#_h.bind(this)),this.form.appendChild(this.target)}init(t,e,s){this.targetButton=e,"function"!=typeof s&&(s=()=>!1);let i=("string"==typeof t?t:this.#kh(t,s))||this.defaultColor;i=ze.isHexColor(i)?i:ze.rgb2hex(i)||i||"";const n=this.colorList;for(let t,e=0,s=n.length;e=3?"#"+((1<<24)+(s[0]<<16)+(s[1]<<8)+s[2]).toString(16).substring(1):""}#bh(){this.hueSlider.open(this.targetButton),this.host.colorPickerHueSliderOpen?.()}#wh(t){t.preventDefault(),this.host.colorPickerAction?.(this.currentColor)}#_h(t){const e=Pe.query.getEventTarget(t).getAttribute("data-value");e&&this.host.colorPickerAction?.(e)}#Ch(){this.host.colorPickerAction?.(null)}#yh(t){const e=Pe.query.getEventTarget(t);this.setHexColor(e.value)}},{_w:Pl}=Oe,Dl={w:"ns-resize",h:"ew-resize",c:"nwse-resize",wRTL:"ns-resize",hRTL:"ew-resize",cRTL:"nesw-resize"};const Fl=class{#J;#Sh;#Eh;#Th;#Mh;#$o;#Te;#No=null;#Nh=!1;#Bh=null;#Ih=null;#Lh="";#Ah=0;#Oh=0;#Rh=null;#zh=null;constructor(t,e,s){this.#J=e,this.inst=t,this.kind=t.constructor.key||t.constructor.name,this.form=s,this.isUpdate=!1,this.focusElement=s.querySelector("[data-focus]"),this.#Eh=this.#J.contextProvider.carrierWrapper.querySelector(".se-modal"),this.#Th=this.#J.contextProvider.carrierWrapper.querySelector(".se-modal .se-modal-inner"),this.#$o=[this.#Ph.bind(this),this.#Dh.bind(this)],this.#Th.appendChild(s),this.#J.eventManager.addEvent(s.querySelector("form"),"submit",this.#De.bind(this)),this.#Nh=!this.#J.eventManager.addEvent(s.querySelector('[data-command="close"]'),"click",this.close.bind(this)),(s.querySelector(".se-modal-resize-handle-w")||s.querySelector(".se-modal-resize-handle-h")||s.querySelector(".se-modal-resize-handle-c")||s.querySelector(".se-modal-resize-form"))&&!(this.#Mh=s.querySelector(".se-modal-resize-form"))&&(this.#Mh=s.querySelector(".se-modal-body"))&&(this.#J.eventManager.addEvent(s.querySelector(".se-modal-resize-handle-w"),"mousedown",this.#Fh.bind(this,"w")),this.#J.eventManager.addEvent(s.querySelector(".se-modal-resize-handle-h"),"mousedown",this.#Fh.bind(this,"h")),this.#J.eventManager.addEvent(s.querySelector(".se-modal-resize-handle-c"),"mousedown",this.#Fh.bind(this,"c")),this.#Te={mousemove:this.#Hh.bind(this),mouseup:this.#qh.bind(this)})}static CreateFileInput({icons:t,lang:e},{acceptedFormats:s,allowMultiple:i}){return`\n\t\t
    \n\t\t\t
    \n\t\t\t\t
    \n\t\t\t\t\t
    \n\t\t\t\t\t\t
    \n\t\t\t\t\t\t\t
    ${t.upload_tray}
    \n\t\t\t\t\t\t\t
    ${t.file_plus}
    \n\t\t\t\t\t\t\t\n\t\t\t\t\t\t
    \n\t\t\t\t\t
    \n\t\t\t\t
    \n\t\t\t\t\n\t\t\t
    \n\t\t\t\n\t\t
    `}static OnChangeFile(t,e){if(!t||!e)return;const s=t.querySelector(".se-input-file-cnt"),i=t.querySelector(".se-input-file-icon-up"),n=t.querySelector(".se-input-file-icon-files");e.length>1?(i.style.display="none",n.style.display="inline-block",s.style.display="",s.textContent=` ..${e.length}`):e.length>0?(i.style.display="none",n.style.display="none",s.style.display="block",s.textContent=e[0].name):(i.style.display="inline-block",n.style.display="none",s.style.display="",s.textContent="")}open(){if(this.#J.ui.offCurrentModal(),this.#Wh(!0),this.#Nh&&(this.#Bh&&this.#J.eventManager.removeEvent(this.#Bh),this.#Bh=this.#J.eventManager.addEvent(this.#Th,"click",this.#$o[1])),this.#No&&=this.#J.eventManager.removeGlobalEvent(this.#No),this.#No=this.#J.eventManager.addGlobalEvent("keydown",this.#$o[0]),this.isUpdate=this.kind===this.#J.ui.currentControllerName,this.#J.ui.opendModal=this,this.isUpdate||this.inst.modalInit?.(),this.inst.modalOn?.(this.isUpdate),Pe.utils.addClass(this.#Eh,"se-backdrop-show"),Pe.utils.addClass(this.form,"se-modal-show"),this.#Eh.showPopover?.(),this.#Mh){const t=this.#Uh(),{maxWidth:e,maxHeight:s}=Pl.getComputedStyle(this.form),i=this.form.offsetWidth-t.width+"px",n=`${this.form.offsetTop+(this.form.offsetHeight-this.#Mh.offsetHeight)}px`;e&&"string"==typeof this.#Lh&&Pe.utils.setStyle(this.#Mh,"max-width",`calc(${e} - ${i})`),s&&Pe.utils.setStyle(this.#Mh,"max-height",`calc(${s} - ${n})`)}this.focusElement&&this.focusElement.focus(),this.#Sh=this.#J.component.currentTarget}close(){this.#je(),this.#Wh(!1),Pl.setTimeout((()=>{this.#J.ui.opendModal=null}),0),this.#Nh&&this.#Bh&&(this.#J.eventManager.removeEvent(this.#Bh),this.#Bh=null),this.#No&&=this.#J.eventManager.removeGlobalEvent(this.#No),this.#Eh.hidePopover?.(),Pe.utils.removeClass(this.#Eh,"se-backdrop-show"),Pe.utils.removeClass(this.form,"se-modal-show"),this.inst.modalInit?.(),this.inst.modalOff?.(this.isUpdate),this.isUpdate?this.#Sh&&this.inst.componentSelect?.(this.#Sh):this.#J.focusManager.focus(),this.#Sh=null,this.isUpdate=!1}#Wh(t){const e=this.#J.ui.opendControllers;for(let s=0;s0;){const t=e.shift();Hl(t,"index")&&n.includes(Number(Hl(t,"index")))?i.push(Number(Hl(t,"index"))):(i.push(this.infoIndex),t.removeAttribute("data-se-index"),this.#Vh(t,null))}if(t&&this.loadEventName)this.#J.eventManager.triggerEvent(this.loadEventName,{infoList:s});else for(let t,e=0;e=0)for(let e=0,s=this.infoList.length;e\n\t\t\t
    \n\t\t\t\t\n\t\t\t\t
    \n\t\t\t\t\t\n\t\t\t\t\t${e.enableFileUpload?``:""}\n\t\t\t\t\t\n\t\t\t\t
    \n\t\t\t\t
    \n\t\t\t\t\t${n.bookmark}\n\t\t\t\t\t${n.download}\n\t\t\t\t\t\n\t\t\t\t
    \n\t\t\t\t\n\t\t\t\t\n\t\t\t\t\n\t\t\t\t\n\t\t\t
    \n\t\t\t`);return l+="
    ",Pe.utils.createElement("DIV",null,l)}(t,s,this.relList);if(this.host=(Wl.location.origin+Wl.location.pathname).replace(/\/$/,""),this.urlInput=i.querySelector(".se-input-url"),this.displayInput=i.querySelector("._se_display_text"),this.titleInput=i.querySelector("._se_title"),this.newWindowCheck=i.querySelector("._se_anchor_check"),this.downloadCheck=i.querySelector("._se_anchor_download"),this.download=i.querySelector("._se_anchor_download_icon"),this.preview=i.querySelector(".se-link-preview"),this.bookmark=i.querySelector("._se_anchor_bookmark_icon"),this.bookmarkButton=i.querySelector("._se_bookmark_button"),this.currentRel=[],this.currentTarget=null,this.linkValue="",this.#Kh=this.relList.length>0,this.#Kh){this.relButton=i.querySelector(".se-anchor-rel-btn"),this.relPreview=i.querySelector(".se-anchor-rel-preview");const e=this.relList,s=(this.defaultRel.default||"").split(" "),n=[];for(let t,i=0,o=e.length;i'+this.#J.icons.checked+"
    "));this.#Yh=new Ai(t,{checkList:!0,position:"right-middle",dir:"ltr"}),this.#Yh.on(this.relButton,this.#Jh.bind(this)),this.#Yh.create(n),this.#J.eventManager.addEvent(this.relButton,"click",this.#Qh.bind(this))}this.#Gh=e,this.#Gh.querySelector(".se-anchor-editor").appendChild(i),this.#Xh=new Ai(t,{checkList:!1,position:"bottom-left",dir:"ltr"}),this.#Xh.on(this.urlInput,this.#tc.bind(this)),this.#J.eventManager.addEvent(this.newWindowCheck,"change",this.#ec.bind(this)),this.#J.eventManager.addEvent(this.downloadCheck,"change",this.#sc.bind(this)),this.#J.eventManager.addEvent(this.urlInput,"input",this.#ic.bind(this)),this.#J.eventManager.addEvent(this.urlInput,"focus",this.#nc.bind(this)),this.#J.eventManager.addEvent(this.bookmarkButton,"click",this.#oc.bind(this)),this.#J.eventManager.addEvent(i.querySelector("._se_upload_button"),"click",(()=>this.input.click()))}set(t){this.currentTarget=t}on(t){if(t){if(this.currentTarget){const t=this.currentTarget.href;this.linkValue=this.preview.textContent=this.urlInput.value=this.#rc(t)?t.substring(t.lastIndexOf("#")):t,this.displayInput.value=this.currentTarget.textContent,this.titleInput.value=this.currentTarget.title,this.newWindowCheck.checked=!!/_blank/i.test(this.currentTarget.target),this.downloadCheck.checked=!!this.currentTarget.download}}else this.init(),this.displayInput.value=this.#J.selection.get().toString().trim(),this.newWindowCheck.checked=this.openNewWindow,this.titleInput.value="";this.#lc(t&&this.currentTarget?this.currentTarget.rel:this.defaultRel.default||""),this.#ac(this.linkValue)}create(t,e){const s=this.linkValue||e||"";if(0===s.length)return null;const i=0===this.displayInput.value.length?s:this.displayInput.value,n=this.currentTarget||Pe.utils.createElement("A");return this.#hc(n,s,i,this.titleInput.value,t),this.linkValue=this.preview.textContent=this.urlInput.value=this.displayInput.value="",n}init(){this.currentTarget=null,this.linkValue=this.preview.textContent=this.urlInput.value="",this.displayInput.value="",this.newWindowCheck.checked=!1,this.downloadCheck.checked=!1,this.#lc(this.defaultRel.default||"")}#hc(t,e,s,i,n){!this.#rc(e)&&this.downloadCheck.checked?t.setAttribute("download",s||e):t.removeAttribute("download"),this.newWindowCheck.checked?t.target="_blank":t.removeAttribute("target");const o=this.currentRel.join(" ");o?t.rel=o:t.removeAttribute("rel"),t.href=e,i?t.title=i:t.removeAttribute("title"),n?0===t.children.length&&(t.textContent=""):t.textContent=s}#rc(t){const e=Wl.location.href.replace(/\/$/,"");return 0===t.indexOf("#")||0===t.indexOf(e)&&t.indexOf("#")===(e.includes("#")?e.substring(0,e.indexOf("#")).length:e.length)}#lc(t){if(!this.#Kh)return;const e=this.currentRel=t?t.split(" "):[],s=this.#Yh.form.querySelectorAll("button");for(let t,i=0,n=s.length;i0?Pe.utils.addClass(this.relButton,"on"):Pe.utils.removeClass(this.relButton,"on")}#cc(t){const e=Pe.query.getListChildren(this.#J.frameContext.get("wysiwyg"),(t=>/h[1-6]/i.test(t.nodeName)||Pe.check.isAnchor(t)&&!!t.id),null);if(0===e.length)return;const s=new RegExp(`^${t.replace(/^#/,"")}`,"i"),i=[],n=[];for(let t,o=0,r=e.length;o${this.#J.icons.bookmark_anchor}${t.id}`:`
    ${t.textContent}
    `));0===i.length?this.#Xh.close():(this.#Xh.create(i,n),this.#Xh.open(this.#J.options.get("_rtl")?"bottom-right":""))}#ac(t){const e=this.preview,s=this.#J.options.get("defaultUrlProtocol"),i=this.noAutoPrefix,n=/^(mailto:|tel:|sms:|https*:\/\/|#)/.test(t)||0===t.indexOf(s),o=!!s&&RegExp("^"+Re.escapeStringRegexp(t.substring(0,s.length))).test(s);t=this.linkValue=e.textContent=t?i?t:!s||n||o?n?t:/^www\./.test(t)?"http://"+t:this.host+(/^\//.test(t)?"":"/")+t:s+t:"",this.#rc(t)?(this.bookmark.style.display="block",Pe.utils.addClass(this.bookmarkButton,"active")):(this.bookmark.style.display="none",Pe.utils.removeClass(this.bookmarkButton,"active")),!this.#rc(t)&&this.downloadCheck.checked?this.download.style.display="block":this.download.style.display="none"}#dc(t){const e=this.currentRel;if(!t)return e.join(" ");if(/^only:/.test(t))return t=t.replace(/^only:/,"").trim(),this.currentRel=t.split(" "),t;const s=t.split(" ");for(let t=0,i=s.length;tthis.create(e,s,t)}},create(t,e,s){if("object"!=typeof e&&(e={}),s&&(e=[s,e].reduce(((t,e)=>(Object.entries(e).forEach((([e,s])=>{if("plugins"===e&&s&&t[e]){const i=Array.isArray(t[e])?t[e]:Object.values(t[e]),n=Array.isArray(s)?s:Object.values(s);t[e]=[...n.filter((t=>!i.includes(t))),...i]}else t[e]=s})),t)),{})),!t)throw Error('[SUNEDITOR.create.fail] The first parameter "target" is missing.');const i=[];if("string"==typeof t){const e=document.querySelector(t);if(!e)throw Error(`[SUNEDITOR.create.fail]-[document.querySelector(${t})] Cannot find target element. Make sure "${t}" is a valid selector and exists in the document.`);i.push({key:null,target:e})}else if(1===t.nodeType)i.push({key:null,target:t});else{let e;for(const s in t){if(e=t[s],!e.target||1!==e.target.nodeType)throw Error('[SUNEDITOR.create.fail] suneditor multi root requires textarea\'s element at the "target" property.');e.key=s,i.push(e)}}return new jr(i,e)}};class Gl extends Yn{static type="";static key="";static className="";static options={};constructor(t){super(t),this.title="",this.icon="",this.inner=null,this.beforeItem=null,this.afterItem=null,this.replaceButton=null}}class Kl extends Gl{static type="browser";open(t){throw new Error(`[${this.constructor.name}] Abstract method 'open()' must be implemented`)}close(){throw new Error(`[${this.constructor.name}] Abstract method 'close()' must be implemented`)}}class Yl extends Gl{static type="command";action(t){throw new Error(`[${this.constructor.name}] Abstract method 'action()' must be implemented`)}}class Xl extends Gl{static type="dropdown";on(t){}action(t){throw new Error(`[${this.constructor.name}] Abstract method 'action()' must be implemented`)}}class Zl extends Gl{static type="dropdown-free";on(t){}off(){}}class Jl extends Gl{static type="field"}class Ql extends Gl{static type="input";toolbarInputKeyDown(t){}toolbarInputChange(t){}}class ta extends Gl{static type="modal";open(t){throw new Error(`[${this.constructor.name}] Abstract method 'open()' must be implemented`)}}class ea extends Gl{static type="popup";show(){throw new Error(`[${this.constructor.name}] Abstract method 'show()' must be implemented`)}}const sa=class extends Yl{static key="blockquote";static className="";constructor(t){super(t),this.title=this.$.lang.tag_blockquote,this.icon="blockquote",this.quoteTag=Pe.utils.createElement("BLOCKQUOTE")}active(t,e){return/blockquote/i.test(t?.nodeName)?(Pe.utils.addClass(e,"active"),!0):(Pe.utils.removeClass(e,"active"),!1)}action(){const t=Pe.query.getParentElement(this.$.selection.getNode(),"blockquote");t?this.$.format.removeBlock(t,{selectedFormats:null,newBlockElement:null,shouldDelete:!1,skipHistory:!1}):this.$.format.applyBlock(this.quoteTag.cloneNode(!1))}},ia=["javascript","typescript","html","css","json","python","java","c","cpp","csharp","go","rust","ruby","php","swift","kotlin","sql","bash","markdown","xml","yaml"];class na extends Yl{static key="codeBlock";static className="";#fc;#vc;#bc;#yc;#wc;#Cc;#_c;#kc;#xc;constructor(t,e){if(super(t),this.title=this.$.lang.codeBlock||"Code Block",this.icon="code_block",this.#fc=Pe.utils.createElement("PRE"),this.#bc=e?.langs??ia,!this.#bc.length)return;this.afterItem=Pe.utils.createElement("button",{class:"se-btn se-tooltip se-sub-arrow-btn",type:"button","data-command":na.key,"data-type":"dropdown"},`${this.$.icons.arrow_down}${this.$.lang.codeLanguage||"Language"}`);const s=function(t,e){const s=t.lang.codeLanguage_none||"None";let i='
      ';i+=`
    • `;for(const t of e)i+=`
    • `;return i+="
    ",Pe.utils.createElement("DIV",{class:"se-dropdown se-list-layer se-list-code-block"},i)}(this.$,this.#bc);this.#vc=s.querySelectorAll("li button"),this.$.menu.initDropdownTarget({key:na.key,type:"dropdown"},s);const i=Pe.utils.createElement("DIV",{class:"se-controller se-code-lang"});this.#yc=Pe.utils.createElement("DIV",{class:"se-code-lang-button"}),this.#$c(""),i.appendChild(this.#yc),this.#Cc=new Ii(this,this.$,i,{position:"top",isWWTarget:!0}),this.#xc=ze.debounce((t=>{this.#kc=this.$.eventManager.removeEvent(this.#kc),t&&i.contains(t.relatedTarget)?this.#Sc():this.#Ec()}),0),this.#wc=new Ai(this.$,{position:"bottom-right",dir:this.$.options.get("_rtl")?"rtl":"ltr",maxHeight:"214px",minWidth:"132px",closeMethod:this.#xc}),this.#wc.on(this.#yc,this.#Tc.bind(this)),this.#Mc(""),this.$.eventManager.addEvent(i,"mousedown",(t=>{Oe.isMobile||this.#wc.form?.contains(Pe.query.getEventTarget(t))?this.$.store.set("_preventBlur",!0):t.preventDefault()})),this.$.eventManager.addEvent(this.#yc,"click",(t=>{if(t.preventDefault(),t.stopPropagation(),this.#wc.isOpen)this.#wc.close();else{const t=this.#Nc(this.#_c);this.#Mc(t);const e=this.#wc.items,s=t?e.indexOf(t):0;this.#wc.open(null,s>=0?`[data-index="${s}"]`:null)}}))}onMouseMove({event:t}){if(!this.#Cc)return;const e=Pe.query.getEventTarget(t).closest("pre");e&&!this.#Bc()&&0===this.$.ui.opendControllers.length&&this.#Ic(e)}active(t,e){return/^PRE$/i.test(t?.nodeName)?(Pe.utils.addClass(e,"active"),!0):(Pe.utils.removeClass(e,"active"),!1)}action(t){const e=t?.getAttribute("data-value")||"",s=this.$.selection.getNode(),i=Pe.query.getParentElement(s,(t=>/^PRE$/i.test(t.nodeName)));if(i&&!e)this.$.format.setLine(Pe.utils.createElement(this.$.options.get("defaultLine")));else if(i||this.$.format.setBrLine(this.#fc.cloneNode(!1)),e){const t=Pe.query.getParentElement(this.$.selection.getNode(),(t=>/^PRE$/i.test(t.nodeName)));t&&this.#Lc(t,e)}this.$.menu.dropdownOff(),this.$.focusManager.focus(),this.$.history.push(!1)}on(){if(!this.#vc)return;const t=this.#Nc(this.$.selection.getNode());for(let e=0,s=this.#vc.length;e</>${t||this.$.lang.codeLanguage||"Language"}`}#Bc(){return this.#wc?.isOpen||this.#Cc?.isOpen}#Nc(t){const e="PRE"===t?.nodeName?t:Pe.query.getParentElement(t,(t=>/^PRE$/i.test(t.nodeName)));return e&&e.className.match(/language-(\S+)/)?.[1]||""}#Lc(t,e){t.className=t.className.replace(/\s*language-\S+/g,"").trim(),e?(Pe.utils.addClass(t,"language-"+e),t.setAttribute("data-se-lang",e)):t.removeAttribute("data-se-lang")}destroy(){this.#_c&&Pe.utils.removeClass(this.#_c,"se-pre-code-focus"),this.#Cc?.form?.parentNode?.removeChild(this.#Cc.form),this.#_c=null}}const oa=na,{_w:ra,_d:la}=Oe;const aa=class extends Yl{static key="exportPDF";static className="se-component-enabled";constructor(t,e){super(t),this.title=this.$.lang.exportPDF,this.icon="PDF",this.apiUrl=e.apiUrl,this.fileName=e.fileName||"suneditor-pdf",this.apiUrl?this.apiManager=new Kr(this,this.$,{method:"POST",url:this.apiUrl,headers:{"Content-Type":"application/json"},responseType:"blob"}):console.warn('[SUNEDITOR.plugins.exportPDF.error] Requires exportPDF."apiUrl" options.')}async action(){if(!this.apiUrl)return void console.warn('[SUNEDITOR.plugins.exportPDF.error] Requires exportPDF."apiUrl" options.');this.$.ui.showLoading();let t=null;try{const e=this.$.frameContext.get("documentTypePageMirror")||this.$.frameContext.get("wysiwygFrame"),s=(this.$.options.get("_themeClass")||"").trim(),i=s?e.className.replace(s,"").trim():e.className,n=Pe.utils.createElement("div",{class:i},e.innerHTML);t=Pe.utils.createElement("div",{style:"position: absolute; top: -10000px; left: -10000px; width: 21cm; columns: 21cm; height: auto;"},n);const o=ra.getComputedStyle(e).padding,r=Pe.utils.applyInlineStylesAll(n,!0,this.$.options.get("allUsedStyles"));if(r.style.padding=r.style.paddingTop=r.style.paddingBottom=r.style.paddingLeft=r.style.paddingRight="0",t.innerHTML=`\n\t\t\t\t\n\t\t\t\t${r.outerHTML}`,la.body.appendChild(t),!1===await this.$.eventManager.triggerEvent("onExportPDFBefore",{target:t}))return;return void await this.#Rc(t)}catch(t){console.error("[SUNEDITOR.plugins.exportPDF.error]",t.message)}finally{Pe.utils.removeItem(t),this.$.ui.hideLoading()}}async#Rc(t){const e={fileName:this.fileName,htmlContent:t.innerHTML},s=await this.apiManager.asyncCall({data:JSON.stringify(e)});if(200!==s.status){let t;try{t=JSON.parse(s.responseText).errorMessage}catch{}throw Error(`[SUNEDITOR.plugins.exportPDF.error] ${t||s.statusText}`)}const i=new Blob([s.response],{type:"application/pdf"}),n=s.getResponseHeader("Content-Disposition"),o=URL.createObjectURL(i),r=(n.match(/filename="([^"]+)/)||[])[1]||this.fileName+".pdf",l=Pe.utils.createElement("A",{href:o,download:r,style:"display: none;"},null);try{la.body.appendChild(l),l.click()}finally{ra.setTimeout((()=>{Pe.utils.removeItem(l),URL.revokeObjectURL(o)}),100)}}},{NO_EVENT:ha}=Oe;class ca extends Yl{static key="fileUpload";static className="";static options={eventIndex:1e4};static component(t){return Pe.check.isAnchor(t)&&t.hasAttribute("data-se-file-download")?t:null}#zc;#Pc=null;constructor(t,e){super(t),this.title=this.$.lang.fileUpload,this.icon="file_upload",e.uploadUrl||console.warn('[SUNEDITOR.fileUpload.warn] "fileUpload" plugin must be have "uploadUrl" option.'),this.uploadUrl=e.uploadUrl,this.uploadHeaders=e.uploadHeaders,this.uploadSizeLimit=De.get(e.uploadSizeLimit,0),this.uploadSingleSizeLimit=De.get(e.uploadSingleSizeLimit,0),this.allowMultiple=!!e.allowMultiple,this.acceptedFormats="string"!=typeof e.acceptedFormats?"*":e.acceptedFormats.trim()||"*",this.as=e.as||"box",this.insertBehavior=e.insertBehavior,this.input=Pe.utils.createElement("input",{type:"file",accept:this.acceptedFormats}),this.allowMultiple&&this.input.setAttribute("multiple","multiple"),this.#zc=this.acceptedFormats.split(", ");const s={"custom-download":{command:"download",title:this.$.lang.download,icon:"download",action:t=>{const e=t.getAttribute("href");e&&Pe.utils.createElement("A",{href:e},null).click()}},"custom-as":{command:"as",value:"link",title:this.$.lang.asLink,icon:"reduction",action:(t,e)=>{this.convertFormat(t,e)}}},i=(e.controls||[["custom-as","align","edit","custom-download","copy","remove"]]).map((t=>t.map((t=>t.startsWith("custom-")?s[t]:t))));if(this.figure=new ji(this,this.$,i,{}),this.fileManager=new ql(this,this.$,{query:"a[download][data-se-file-download]",loadEventName:"onFileLoad",actionEventName:"onFileAction"}),/\bedit\b/.test(JSON.stringify(i))){const t=function({lang:t,icons:e}){const s=`\n\t\t
    \n\t\t
    \n\t\t\t
    \n\t\t\t\t\n\t\t\t\t\n\t\t\t\t\n\t\t\t
    \n\t\t
    \n\t\t`;return Pe.utils.createElement("DIV",{class:"se-controller se-controller-simple-input"},s)}(this.$);this.controller=new Ii(this,this.$,t,{position:"bottom",disabled:!0},ca.key),this.editInput=t.querySelector("input")}this.$.eventManager.addEvent(this.input,"change",this.#Zh.bind(this))}action(){this.$.store.set("_preventBlur",!0),this.input.click()}onFilePasteAndDrop({file:t}){const e=t.type;this.#zc.some((t=>!!t.startsWith("*")||(!!t.startsWith(e)||void 0)))&&(this.submitFile([t]),this.$.focusManager.focus())}controllerAction(t){const e=t.getAttribute("data-command");if(e){if("edit"===e){if(0===this.editInput.value.trim().length)return;this.#Pc.textContent=this.editInput.value}this.controller.close(),this.$.component.select(this.#Pc,ca.key)}}componentSelect(t){this.#Pc=t;const e=this.figure.controller.form.querySelector('[data-command="__c__as"]');if(e)return Pe.check.isFigure(t.parentElement)?(e.innerHTML=this.$.icons.reduction+Pe.utils.createTooltipInner(this.$.lang.asLink),e.setAttribute("data-value","link"),void this.figure.open(t,{nonResizing:!0,nonSizeInfo:!0,nonBorder:!0,figureTarget:!0,infoOnly:!1})):(e.innerHTML=this.$.icons.expansion+Pe.utils.createTooltipInner(this.$.lang.asBlock),e.setAttribute("data-value","box"),this.figure.controllerOpen(t,{isWWTarget:!0}),!0)}componentEdit(t){this.editInput.value=t.textContent,this.figure.controllerHide(),this.controller.open(t,null,{isWWTarget:!Pe.check.isFigure(t.parentElement),initMethod:null,addOffset:null}),this.editInput.focus()}async componentDestroy(t){if(!t)return;const e=ji.GetContainer(t),s=Pe.query.getParentElement(t,".se-component")||t;if(!1===await this.$.eventManager.triggerEvent("onFileDeleteBefore",{element:e.target,container:e,url:e.target.getAttribute("href")}))return;const i=this.$.component.isInline(s)?s.previousSibling||s.nextSibling:s.previousElementSibling||s.nextElementSibling;Pe.utils.removeItem(s),this.$.ui.offCurrentController(),this.$.focusManager.focusEdge(i),this.$.history.push(!1)}async submitFile(t){if(0===t.length)return;let e=0;const s=[],i=this.uploadSingleSizeLimit;for(let n,o,r=0,l=t.length;r0&&o>i){const t="[SUNEDITOR.fileUpload.fail] Size of uploadable single file: "+i/1e3+"KB",e=await this.$.eventManager.triggerEvent("onFileUploadError",{error:t,limitSize:i,uploadSize:o,file:n});return this.$.ui.alertOpen(e===ha?t:e||t,"error"),!1}s.push(n),e+=o}const n=this.uploadSizeLimit,o=this.fileManager.getSize();if(n>0&&e+o>n){const t="[SUNEDITOR.fileUpload.fail] Size of uploadable total files: "+n/1e3+"KB",s=await this.$.eventManager.triggerEvent("onFileUploadError",{error:t,limitSize:n,currentSize:o,uploadSize:e});return this.$.ui.alertOpen(s===ha?t:s||t,"error"),!1}const r={url:this.uploadUrl,uploadHeaders:this.uploadHeaders,files:s},l=async function(t,e,s){e=s||e;t(await this.fileManager.asyncUpload(e.url,e.uploadHeaders,e.files))}.bind(this,this.#mc.bind(this),r),a=await this.$.eventManager.triggerEvent("onFileUploadBefore",{info:r,handler:l});return void 0===a||!1!==a&&(null!==a&&"object"==typeof a&&l(a),void(!0!==a&&a!==ha||l(null)))}convertFormat(t,e){if("link"===e){this.figure.close();const{container:e}=ji.GetContainer(t),s=e.nextElementSibling,i=e.parentElement;t.removeAttribute("data-se-non-focus"),t.setAttribute("contenteditable","false"),Pe.utils.addClass(t,"se-component|se-inline-component");const n=Pe.utils.createElement(this.$.options.get("defaultLine"),null,t);i.insertBefore(n,s),Pe.utils.removeItem(e)}else{this.$.selection.setRange(t,0,t,1);const e=this.$.html.remove(),s=this.$.nodeTransform.split(e.container,e.offset,0);s?.previousElementSibling&&Pe.check.isZeroWidth(s.previousElementSibling)&&Pe.utils.removeItem(s.previousElementSibling),t.setAttribute("data-se-non-focus","true"),t.removeAttribute("contenteditable"),Pe.utils.removeClass(t,"se-component|se-component-selected|se-inline-component");const i=ji.CreateContainer(t,"se-file-figure se-flex-component");(s||e.container).parentElement.insertBefore(i.container,s)}this.$.history.push(!1),this.$.component.select(t,ca.key)}create(t,e,s){const i=e.name||t,n=Pe.utils.createElement("A",{href:t,title:i,download:i,"data-se-file-download":"",contenteditable:"false","data-se-non-focus":"true","data-se-non-link":"true"},i);if(this.fileManager.setFileData(n,e),"link"===this.as)return n.className="se-component se-inline-component",void this.$.component.insert(n,{scrollTo:!!s,insertBehavior:s?this.insertBehavior:null});const o=ji.CreateContainer(n);if(Pe.utils.addClass(o.container,"se-file-figure|se-flex-component"),this.$.component.insert(o.container,{scrollTo:!!s,insertBehavior:s?this.insertBehavior:null})){if(s)if(this.$.options.get("componentInsertBehavior"))this.$.component.select(n,ca.key);else{const t=this.$.format.addLine(o.container,null);t&&this.$.selection.setRange(t,0,t,0)}}else this.$.focusManager.focus()}#pc(t){t.result.forEach(((t,e,s)=>{this.create(t.url,{name:t.name,size:t.size},e===s.length-1)}))}async#gc(t){const e=await this.$.eventManager.triggerEvent("onFileUploadError",{error:t});if(!1===e)return;const s=e===ha?t.errorMessage:e||t.errorMessage;this.$.ui.alertOpen(s,"error"),console.error("[SUNEDITOR.plugin.fileUpload.error]",s)}#mc(t){const e=JSON.parse(t.responseText);e.errorMessage?this.#gc(e):this.#pc(e)}async#Zh(t){const e=Pe.query.getEventTarget(t);await this.submitFile(e.files)}}const da=ca;class ua extends Yl{static key="list_bulleted";static className="se-icon-flip-rtl";#Dc;constructor(t){super(t),this.title=this.$.lang.bulletedList,this.icon="list_bulleted",this.afterItem=Pe.utils.createElement("button",{class:"se-btn se-tooltip se-sub-arrow-btn",type:"button","data-command":ua.key,"data-type":"dropdown"},`${this.$.icons.arrow_down}${this.$.lang.bulletedList}`);const e=function(){const t=`\n\t
    \n\t\t
      \n\t\t\t${e=["disc","circle","square"],e.map((t=>`\n\t\t\t
    • \n\t\t\t\t\n\t\t\t
    • \n\t\t`)).join("")}\n\t\t
    \n\t
    `;var e;return Pe.utils.createElement("DIV",{class:"se-dropdown se-list-layer"},t)}();this.#Dc=e.querySelectorAll("li button ul"),this.$.menu.initDropdownTarget({key:ua.key,type:"dropdown"},e)}active(t,e){return Pe.check.isListCell(t)&&/^UL$/i.test(t.parentElement.nodeName)?(Pe.utils.addClass(e,"active"),!0):(Pe.utils.removeClass(e,"active"),!1)}action(t){const e=this.$.format.getBlock(this.$.selection.getNode()),s=t?.querySelector("ul")?.style.listStyleType;Pe.check.isList(e)&&s?e.style.listStyleType=s:this.submit(s),this.$.menu.dropdownOff()}on(){const t=this.#Dc,e=this.$.format.getBlock(this.$.selection.getNode()),s=e?.style?e.style.listStyleType||"disc":"";for(let e,i=0,n=t.length;i${this.$.lang.numberedList}`);const e=function(){const t=`\n\t
    \n\t\t
      \n\t\t\t${ma(["decimal","upper-roman","lower-roman"])}\n\t\t
    \n\t\t
      \n\t\t${ma(["lower-latin","upper-latin","lower-greek"])}\n\t\t
    \n\t
    `;return Pe.utils.createElement("DIV",{class:"se-dropdown se-list-layer"},t)}();this.#Dc=e.querySelectorAll("li button ol"),this.$.menu.initDropdownTarget({key:ga.key,type:"dropdown"},e)}active(t,e){return Pe.check.isListCell(t)&&/^OL$/i.test(t.parentElement.nodeName)?(Pe.utils.addClass(e,"active"),!0):(Pe.utils.removeClass(e,"active"),!1)}action(t){const e=this.$.format.getBlock(this.$.selection.getNode()),s=t?.querySelector("ol")?.style.listStyleType;Pe.check.isList(e)&&s?e.style.listStyleType=s:this.submit(s),this.$.menu.dropdownOff()}on(){const t=this.#Dc,e=this.$.format.getBlock(this.$.selection.getNode()),s=e?.style?e.style.listStyleType||"decimal":"";for(let e,i=0,n=t.length;i`\n\t\t\t
  • \n\t\t\t\t\n\t\t\t
  • \n\t\t`)).join("")}const fa=ga,{debounce:va}=ze;function ba(t){return`
    ${t.key}${t.name?`${t.name}`:""}
    `}function ya(t,e){return{tag:"span",attrs:{"data-se-autocomplete":e+t.key},text:e+t.key}}const wa=class extends Jl{static key="autocomplete";static className="";#Fc=0;#Hc=0;#qc=null;#Wc=null;constructor(t,e){super(t);const s=e.limitSize||5,i=e.searchStartLength||0,n="number"==typeof e.delayTime?e.delayTime:120,o=e.useCachingData??!0,r=e.useCachingFieldData??!0;this.triggerContexts=new Map;const l=e.triggers||{};for(const[t,e]of Object.entries(l)){const n=e.limitSize??s;this.triggerContexts.set(t,{trigger:t,limitSize:n,searchStartLength:e.searchStartLength??i,directData:e.data||null,apiUrl:e.apiUrl?.replace(/\s/g,"").replace(/\{limitSize\}/i,String(n))||"",apiHeaders:e.apiHeaders||null,transformResponse:e.transformResponse||null,renderItem:e.renderItem||ba,onSelect:e.onSelect||ya,apiManager:e.apiUrl?new Kr(this,this.$,{headers:e.apiHeaders}):null,cachingData:e.useCachingData??o?new Map:null,cachingFieldData:e.useCachingFieldData??r?[]:null})}this.sortedTriggers=[...this.triggerContexts.keys()].sort(((t,e)=>e.length-t.length));const a=Pe.utils.createElement("DIV",{class:"se-controller se-empty-controller"},"
    ");this.selectMenu=new Ai(this.$,{position:"right-bottom",dir:"ltr",closeMethod:()=>this.controller.close()}),this.controller=new Ii(this,this.$,a,{position:"bottom",initMethod:()=>{this.#Uc(),this.selectMenu.close()}},null),this.selectMenu.on(a.firstElementChild,this.#Vc.bind(this)),this.onInput=va(this.onInput.bind(this),n)}#Uc(){this.#Wc?.apiManager&&this.#Wc.apiManager.cancel()}async onInput(){this.#Uc();const t=this.$.selection.get();if(!t.rangeCount)return void this.selectMenu.close();const e=t.anchorNode,s=t.anchorOffset,i=e.textContent.substring(0,s);for(const t of this.sortedTriggers){const n=i.lastIndexOf(t);if(-1===n)continue;const o=i.substring(n+t.length,s),r=i[n-1]?.trim();if(!/\s/.test(o)&&(!r||Pe.check.isZeroWidth(r))){const i=this.triggerContexts.get(t);if(o.lengtht.key.toLowerCase().startsWith(n))).slice(0,i);else{const s=await t.apiManager.asyncCall({method:"GET",url:this.#Gc(t,e)}),i=JSON.parse(s.responseText);o=t.transformResponse?t.transformResponse(i,s):i}if(t.cachingFieldData){const e=new Set;o=t.cachingFieldData.concat(o).filter((({key:t})=>!e.has(t)&&(e.add(t),t.toLowerCase().startsWith(n)))).slice(0,i)}if(!o?.length)return this.selectMenu.close(),!1;const r=[],l=[];for(let e,s=0,i=o.length;se.key===t.key))&&e.cachingFieldData.push(t)}},{debounce:Ca}=ze;const _a=class extends Jl{static key="slashCommand";static className="";#Kc;#Yc;#Xc;#oa;#Fc=0;#Hc=0;#qc=null;#Zc=!1;constructor(t,e){super(t),this.#Kc="string"==typeof e.triggerChar&&e.triggerChar.length>0?e.triggerChar:"/",this.#Yc="number"==typeof e.limitSize&&e.limitSize>0?e.limitSize:1/0,this.#Xc="string"==typeof e.emptyMessage?e.emptyMessage:"";const s="number"==typeof e.delayTime?e.delayTime:120;this.#oa=new gn(this,this.$,{items:Array.isArray(e.items)?e.items:[],resolveButton:us,renderCustomItem:"function"==typeof e.renderItem?e.renderItem:null,prepareCommit:()=>this.#Jc(),selectMenuParams:{position:"bottom-left",dir:"ltr",minWidth:"string"==typeof e.minWidth?e.minWidth:"200px",maxHeight:"string"==typeof e.maxHeight?e.maxHeight:"320px",closeMethod:()=>this.#Qc()}});const i=Pe.utils.createElement("DIV",{class:"se-controller se-empty-controller"},"
    ");this.controller=new Ii(this,this.$,i,{position:"bottom",escGuard:()=>this.#oa.hasOpenSubPanel()},null),this.#oa.attach(i.firstElementChild,this.#Vc.bind(this),{class:"se-block-action-menu se-slash-command-menu"}),this.onInput=Ca(this.onInput.bind(this),s)}onKeyDown({event:t}){Fe.isEsc(t.code)&&this.onInput.cancel?.()}onInput(){if(0===this.#oa.getItems().length)return;const t=this.$.selection.get();if(!t.rangeCount)return void this.#td();const e=t.anchorNode,s=t.anchorOffset;if(!e||"string"!=typeof e.textContent)return void this.#td();const i=e.textContent.substring(0,s),n=this.#Kc,o=i.lastIndexOf(n);if(-1===o)return void this.#td();const r=i.substring(o+n.length,s);if(/\s/.test(r))return void this.#td();const l=i[o-1];if(l&&""!==l.trim()&&!Pe.check.isZeroWidth(l))return void this.#td();const a=this.#oa.filter(r,this.#Yc);0!==a.length?(this.controller.open(e,null,{isWWTarget:!0,initMethod:null,addOffset:null}),this.#oa.createRows(a),this.#oa.open(),this.#oa.setItem(0),this.#ed(e,o,s)):this.#Xc?(this.#sd(e),this.#ed(e,o,s)):this.#td()}open(t){if(!t)return!1;const e=this.#oa.filter("",this.#Yc);return 0!==e.length&&(this.controller.open(t,null,{isWWTarget:!0,initMethod:null,addOffset:null}),this.#oa.createRows(e),this.#oa.open(),this.#oa.setItem(0),this.#ed(t,0,0),!0)}#td(){this.#Zc=!0,this.#oa.close(),this.#Zc=!1}#Qc(){this.#Zc||this.#Jc(),this.#qc=null,this.controller.close()}#Jc(){const t=this.#qc;if(!t||!t.parentNode)return;if(t.textContent?.[this.#Fc]!==this.#Kc)return;this.$.selection.setRange(t,this.#Fc,t,this.#Hc);const e=this.$.selection.getRange();e&&!e.collapsed&&this.$.html.remove()}#ed(t,e,s){this.#qc=t,this.#Fc=e,this.#Hc=s}#sd(t){this.controller.open(t,null,{isWWTarget:!0,initMethod:null,addOffset:null}),this.#oa.selectMenu.create([null],[`${this.#Xc}`]),this.#oa.open()}#Vc(t){if(!t)return!1;const e=this.#qc;if(!e)return!1;const s=this.#Kc,i=(e.textContent||"").substring(this.#Fc+s.length,this.#Hc);if("dropdownFree"!==t.kind)return this.#Jc(),this.#td(),void this.#oa.dispatch(t,{triggerChar:s,query:i,item:t.raw});const n=this.#oa.hasOpenSubPanel();this.#oa.dispatch(t,{triggerChar:s,query:i,item:t.raw}),n||this.#oa.hasOpenSubPanel()||this.#td()}};class ka extends Xl{static key="align";static className="";constructor(t,e){super(t),this.title=this.$.lang.align,this.icon=this.$.options.get("_rtl")?"align_right":"align_left",this.defaultDir="",this.alignIcons={justify:this.$.icons.align_justify,left:this.$.icons.align_left,right:this.$.icons.align_right,center:this.$.icons.align_center};const s=this.$.menu.initDropdownTarget(ka,function({lang:t,icons:e,options:s},i){return(Array.isArray(i)?i:s.get("_rtl")?["right","center","left","justify"]:["left","center","right","justify"]).map((s=>{const i=t["align"+s.charAt(0).toUpperCase()+s.slice(1)];return{command:s,title:i,innerHTML:`${e["align_"+s]}${i}`}}))}(this.$,e.items),{className:"se-list-align"});this._itemMenu=s.querySelector("ul"),this.alignList=s.querySelectorAll("li button")}active(t,e){const s=e.firstElementChild;if(t){if(this.$.format.isLine(t)){const i=t.style.textAlign;return i?(Pe.utils.changeElement(s,this.alignIcons[i]||this.alignIcons[this.defaultDir]),e.setAttribute("data-focus",i),!0):void 0}}else Pe.utils.changeElement(s,this.alignIcons[this.defaultDir]),e.removeAttribute("data-focus");return!1}on(t){const e=t.getAttribute("data-focus")||this.defaultDir;if(!e)return;const s=this.alignList;for(let t=0,i=s.length;t'+this.$.lang.font+""+this.$.icons.arrow_down;const s=e.items||["Arial","Comic Sans MS","Courier New","Impact","Georgia","tahoma","Trebuchet MS","Verdana"],i=`
  • `,n=this.$.menu.initDropdownTarget($a,function(t){return t.map((t=>{const e=t.split(",")[0];return{command:t,title:e,innerHTML:e,attrs:{"data-txt":e,style:`font-family:${t};`}}}))}(s),{className:"se-list-font-family",prependHTML:i});this.currentFont="",this.fontList=n.querySelectorAll("ul li button"),this.fontArray=s,this.#nd=n.querySelector(".se-sub-list span")}active(t,e){const s=e.querySelector(".se-txt"),i=e.parentNode.querySelector(".se-tooltip-text");let n="";if(t){if(this.$.format.isLine(t))return;if(n=Pe.utils.getStyle(t,"fontFamily")){const t=n.replace(/["']/g,"");return Pe.utils.changeTxt(s,t),Pe.utils.changeTxt(i,this.$.lang.font+" ("+t+")"),!0}}else{const t=this.$.store.get("hasFocus")?this.$.frameContext.get("wwComputedStyle").fontFamily:this.$.lang.font;Pe.utils.changeTxt(s,t),Pe.utils.changeTxt(i,this.$.store.get("hasFocus")?this.$.lang.font+(t?" ("+t+")":""):t)}return!1}on(t){const e=this.fontList,s=t.querySelector(".se-txt").textContent;if(s!==this.currentFont){let t=!1;for(let i=0,n=e.length;ithis.$.format.isLine(t)))}off(){this.colorPicker.hueSliderClose()}colorPickerAction(t){if(t){const e=Pe.utils.createElement("SPAN",{style:"color: "+t+";"});this.$.inline.apply(e,{stylesToModify:["color"],nodesToRemove:null,strictRemove:null})}else this.$.inline.apply(null,{stylesToModify:["color"],nodesToRemove:["span"],strictRemove:!0});this.$.menu.dropdownOff()}}const Ta=Ea;class Ma extends Zl{static key="backgroundColor";static className="";constructor(t,e){super(t),this.title=this.$.lang.backgroundColor,this.icon="background_color";const s=Pe.utils.createElement("DIV",{class:"se-dropdown se-list-layer"},null);this.colorPicker=new zl(this,this.$,"backgroundColor",{form:s,colorList:e.items,splitNum:e.splitNum,disableHEXInput:e.disableHEXInput,hueSliderOptions:{controllerOptions:{isOutsideForm:!0}}}),this.$.menu.initDropdownTarget(Ma,s)}active(t,e){const s=e.querySelector("path.se-svg-color-helper");if(!s)return;let i="";if(t){if(this.$.format.isLine(t))return;if(i=Pe.utils.getStyle(t,"backgroundColor"))return s.style.color=i,!0}else s.style.color=i;return!1}on(t){this.colorPicker.init(this.$.selection.getNode(),t,(t=>this.$.format.isLine(t)))}off(){this.colorPicker.hueSliderClose()}colorPickerAction(t){if(t){const e=Pe.utils.createElement("SPAN",{style:"background-color: "+t+";"});this.$.inline.apply(e,{stylesToModify:["background-color"],nodesToRemove:null,strictRemove:null})}else this.$.inline.apply(null,{stylesToModify:["background-color"],nodesToRemove:["span"],strictRemove:!0});this.$.menu.dropdownOff()}}const Na=Ma;class Ba extends Xl{static key="hr";static className="";static component(t){return/^hr$/i.test(t?.nodeName)?t:null}constructor(t,e){super(t),this.title=this.$.lang.horizontalLine,this.icon="horizontal_line";const s=this.$.menu.initDropdownTarget(Ba,function({lang:t},e){return(e||[{name:t.hr_solid,class:"__se__solid",style:null},{name:t.hr_dashed,class:"__se__dashed",style:null},{name:t.hr_dotted,class:"__se__dotted",style:null}]).map((t=>({command:"hr",title:t.name,innerHTML:``})))}(this.$,e.items),{className:"se-list-line"});this.list=s.querySelectorAll("button")}componentSelect(t){Pe.utils.addClass(t,"on")}componentDeselect(t){Pe.utils.removeClass(t,"on")}componentDestroy(t){if(!t)return;const e=t.previousElementSibling||t.nextElementSibling;Pe.utils.removeItem(t),this.$.focusManager.focusEdge(e),this.$.history.push(!1)}shortcut({line:t,range:e}){const s=this.$.nodeTransform.split(e.endContainer,e.endOffset,0);this.submit("__se__solid"),Pe.utils.removeItem(t),this.$.selection.setRange(s,0,s,0)}action(t){const e=this.submit(t.firstElementChild.className),s=this.$.format.addLine(e);this.$.selection.setRange(s,1,s,1),this.$.menu.dropdownOff()}submit(t){const e=Pe.utils.createElement("hr",{class:t});return this.$.focusManager.focus(),this.$.component.insert(e,{insertBehavior:"line"}),e}}const Ia=Ba;class La extends Xl{static key="list";static className="se-icon-flip-rtl";#Dc;#od;constructor(t){super(t),this.title=this.$.lang.list,this.icon="list_numbered",this.#od={bulleted:this.$.icons.list_bulleted,numbered:this.$.icons.list_numbered};const e=this.$.menu.initDropdownTarget(La,function({lang:t,icons:e}){return[{command:"ol",title:t.numberedList,innerHTML:e.list_numbered,className:"se-tooltip se-icon-flip-rtl"},{command:"ul",title:t.bulletedList,innerHTML:e.list_bulleted,className:"se-tooltip se-icon-flip-rtl"}]}(this.$));this.#Dc=e.querySelectorAll("li button")}active(t,e){const s=e.firstElementChild;if(Pe.check.isList(t)){const i=t.nodeName.toLowerCase();return e.setAttribute("data-focus",i),Pe.utils.addClass(e,"active"),/^ul$/.test(i)?Pe.utils.changeElement(s,this.#od.bulleted):Pe.utils.changeElement(s,this.#od.numbered),!0}return e.removeAttribute("data-focus"),Pe.utils.changeElement(s,this.#od.numbered),Pe.utils.removeClass(e,"active"),!1}on(t){const e=t.getAttribute("data-focus")||"",s=this.#Dc;for(let t=0,i=s.length;t

    `.repeat(e)}function ih(t){return t=t.toLowerCase(),Pe.utils.createElement(t,null,"

    ")}function nh(t,e,s){let i=Za.get(t);return i||(i=function(t){const e=[],s=t.rows,i=[];for(let t=0,n=s.length;t1)for(let e=1;e{const e=i.indexOf(t);return e>-1?n[e]:null})).filter((t=>null!==t))}}function rh(t){t&&(Xa.delete(t),Za.delete(t))}function lh(t,e,s){const i=[];let n="";for(const o in Ha){if(s.includes(o))continue;const r=Ha[o];i.push(o),n+=`\n\t\t\t`}return{items:i,menus:Pe.utils.createElement("DIV",null,n).querySelectorAll("button")}}const ah=class{#rd;#J;#I;constructor(t,{mergeButton:e,unmergeButton:s,splitButton:i,openCellMenuFunc:n,closeCellMenuFunc:o}){this.#rd=t,this.#J=t.$,this.#I=t.state,this.mergeButton=e,this.unmergeButton=s,this.splitButton=i;const r=(l=this.#J.lang,{items:["vertical","horizontal"],menus:Pe.utils.createElement("DIV",null,`\n\t\t
    \n\t\t\t${l.verticalSplit}\n\t\t
    \n\t\t
    \n\t\t\t${l.horizontalSplit}\n\t\t
    `).querySelectorAll("div")});var l;this.selectMenu_split=new Ai(this.#J,{checkList:!1,position:"bottom-center",openMethod:n,closeMethod:o}),this.selectMenu_split.on(this.splitButton,this._OnSplitCells.bind(this)),this.selectMenu_split.create(r.items,r.menus)}get#ld(){return this.#rd.selectionService}openSplitMenu(){this.selectMenu_split.open()}mergeCells(t,e=!1){const s=t[0].closest("table");rh(s);const{clonedTable:i,clonedSelectedCells:n}=e?{clonedTable:s,clonedSelectedCells:t}:oh(s,t);this.#rd.setTableInfo(i),t=n,this.#rd.setState("ref",null),this.#ld.setMultiCells(t[0],Pe.query.findVisualLastCell(t));const o=this.#I.ref,r=t[0];let l=null,a=null;const h=o.ce-o.cs+1;let c=o.re-o.rs+1,d="",u=null;for(let e,s,i=1,n=t.length;i0&&o+i>=e&&(t.rowSpan-=De.getOverlapRangeAtIndex(e,s,o,o+i));else i.push(t[o]);for(let t=0,e=i.length;tl.closest("tr").rowIndex||r.cellIndex>l.cellIndex?r:l,this.#ld.setMultiCells(o,r),this.#rd.setState("selectedCells",Array.from(a.querySelectorAll(".se-selected-table-cell")))):this.#rd.setCellInfo(r,!0),this.#ld.initCellSelection(o),this.#rd.setState("selectedCell",r),this.setUnMergeButton(),this.#rd.controller_cell.resetPosition(r),this.#rd.historyPush())}findMergedCells(t){const e=[];return t?.forEach((t=>{t&&(t.rowSpan>1||t.colSpan>1)&&e.push(t)})),e}setMergeSplitButton(){this.#I.ref?(this.splitButton.style.display="none",this.mergeButton.style.display="block"):(this.splitButton.style.display="block",this.mergeButton.style.display="none")}setUnMergeButton(){const t=this.findMergedCells(this.#I.selectedCells?.length?this.#I.selectedCells:[this.#I.fixedCell]).length>0;this.unmergeButton.style.display=t?"block":"none"}_OnSplitCells(t){rh(this.#rd._element);const e="vertical"===t,s=this.#I.tdElement,i=this.#I.trElements,n=this.#I.trElement,o=this.#I.logical_cellIndex,r=this.#I.rowIndex,l=ih(s.nodeName);if(e){const t=s.colSpan;if(l.rowSpan=s.rowSpan,t>1)l.colSpan=Math.floor(t/2),s.colSpan=t-l.colSpan,n.insertBefore(l,s.nextElementSibling);else{let e=[],r=[];for(let n,l,a=0,h=this.#I.rowCnt;a0)for(let t,e=0;ea||(d>=t.index?(l+=t.cs,d+=t.cs,t.rs-=1,t.row=a+1,t.rs<1&&(r.splice(e,1),e--)):u===p-1&&(t.rs-=1,t.row=a+1,t.rs<1&&(r.splice(e,1),e--)));if(d<=o&&c>0&&e.push({index:d,cs:h+1,rs:c,row:-1}),i!==s&&d<=o&&d+h>=o+t-1){i.colSpan+=1;break}if(d>o)break;l+=h}r=r.concat(e).sort((function(t,e){return t.index-e.index})),e=[]}n.insertBefore(l,s.nextElementSibling)}}else{const t=s.rowSpan;if(l.colSpan=s.colSpan,t>1){l.rowSpan=Math.floor(t/2);const e=t-l.rowSpan,r=[],a=Pe.utils.getArrayIndex(i,n)+e;for(let t,e,s=0;s=o));h++)i=t[h],n=i.rowSpan-1,n>0&&n+s>=a&&l=d.index&&(u+=d.cs,i+=d.cs,d=r.shift()),i>=o||n===a-1){h.insertBefore(l,t.nextElementSibling);break}u+=e}s.rowSpan=e}else{l.rowSpan=s.rowSpan;const t=Pe.utils.createElement("TR");t.appendChild(l);for(let t,e=0;e=r&&(t[s].rowSpan+=1)}const e=this.#I.physical_cellIndex,o=n.cells;for(let t=0,s=o.length;t{r.set(t,!0)}));const l=i.rows,a=l.length,h=Array.from(l[0].cells).reduce(((t,e)=>t+(e.colSpan||1)),0),c=Array.from({length:a},(()=>Array(h).fill(null)));for(let t=0;t0&&c[t-1][s]===i)continue;const n=i.cloneNode(!0);let l=1,d=1;for(;t+l1&&(n.rowSpan=l),d>1&&(n.colSpan=d),e.appendChild(n)}}const d=Pe.utils.createElement("figure");d.className=e.className,d.appendChild(n);const u=`\x3c!--StartFragment--\x3e${d.outerHTML}\x3c!--EndFragment--\x3e`;t.clipboardData.setData("text/html",u)}pasteTableCellMatrix(t,e){if(!t||!e)return;rh(e.closest("table"));const s=t.rows;let i=0;const n=[];for(let t=0;t0||g>0){const t=d[d.length-1],e=t.cells[t.cells.length-1];for(let t=0;t1||o>1)for(let e=1;e=f&&(o>1||r>1)&&b.push(n),s+=o}}b.length>0&&(this.#hd.unmergeCells(b,!0),this.#rd.setState("trElements",d=c.rows));const w=[],C=[],_=[];for(let t=0,e=r.rowCnt;t1)for(let t=1;t=l&&c<=a&&h.push(n),s+=o}}h.length>0&&w.push(h),i+=o}}if(w.length>0){for(const t of w)this.#rd.setState("ref",null),this.#rd.setState("trElements",c.rows),this.#hd.mergeCells(t,!0);this.#rd.setState("trElements",d=c.rows)}const k=[],x=[];for(let t=0;t1)for(let e=1;e=f&&r+i-1<=v&&(e.innerHTML=s.innerHTML,k.push(e),a++),r+=i}}return l.replaceWith(c),this.#rd._closeTableSelectInfo(),this.#rd.setTableInfo(c),this.#hd.setMergeSplitButton(),this.#hd.setUnMergeButton(),this.#ld.focusCellEdge(k[0]),this.#rd.historyPush(),k}};const ch=class{#rd;#J;#I;constructor(t,{columnButton:e,rowButton:s,openCellMenuFunc:i,closeCellMenuFunc:n}){this.#rd=t,this.#J=t.$,this.#I=t.state;const o=(r=this.#J.lang,l=this.#J.icons,{items:["insert-left","insert-right","delete"],menus:Pe.utils.createElement("DIV",null,`\n\t\t
    \n\t\t\t${l.insert_column_left}${r.insertColumnBefore}\n\t\t
    \n\t\t
    \n\t\t\t${l.insert_column_right}${r.insertColumnAfter}\n\t\t
    \n\t\t
    \n\t\t\t${l.delete_column}${r.deleteColumn}\n\t\t
    `).querySelectorAll("div")});var r,l;this.selectMenu_column=new Ai(this.#J,{checkList:!1,position:"bottom-center",openMethod:i,closeMethod:n}),this.selectMenu_column.on(e,this.#cd.bind(this)),this.selectMenu_column.create(o.items,o.menus);const a=function(t,e){return{items:["insert-above","insert-below","delete"],menus:Pe.utils.createElement("DIV",null,`\n\t\t
    \n\t\t\t${e.insert_row_above}${t.insertRowAbove}\n\t\t
    \n\t\t
    \n\t\t\t${e.insert_row_below}${t.insertRowBelow}\n\t\t
    \n\t\t
    \n\t\t\t${e.delete_row}${t.deleteRow}\n\t\t
    `).querySelectorAll("div")}}(this.#J.lang,this.#J.icons);this.selectMenu_row=new Ai(this.#J,{checkList:!1,position:"bottom-center",openMethod:i,closeMethod:n}),this.selectMenu_row.on(s,this.#dd.bind(this)),this.selectMenu_row.create(a.items,a.menus)}get#ld(){return this.#rd.selectionService}openColumnMenu(){this.selectMenu_column.open()}openRowMenu(){this.selectMenu_row.menus[0].style.display=this.selectMenu_row.menus[1].style.display=/^TH$/i.test(this.#I.tdElement?.nodeName)?"none":"",this.selectMenu_row.open()}editTable(t,e){const s=this.#rd._element,i="row"===t;if(i){const t=this.#I.trElement.parentElement;if(/^THEAD$/i.test(t.nodeName)){if("up"===e)return;if(!t.nextElementSibling||!/^TBODY$/i.test(t.nextElementSibling.nodeName))return void(e?s.innerHTML+=""+sh("td",this.#I.logical_cellCnt)+"":(Pe.utils.removeItem(this.#I.figureElement),this.#rd._closeTableSelectInfo()))}}if(this.#I.ref){const t=this.#I.tdElement,s=this.#I.selectedCells;if(i)if(e)this.#rd.setCellInfo("up"===e?s[0]:s.at(-1),!0),this.editRow(e,null,t);else{let t=s[0].parentNode;const i=[s[0]];for(let e,n=1,o=s.length;n0){const t=!e[v+1];for(let e,s=0;sm||(f>=e.index?(g+=e.cs,f=v+g,e.rs-=1,e.row=m+1,e.rs<1&&(c.splice(s,1),s--)):t&&(e.rs-=1,e.row=m+1,e.rs<1&&(c.splice(s,1),s--)))}s>0&&h.push({rs:s,cs:l+1,index:f,row:-1}),f>=a&&f+l<=a+o?u.push(t):f<=a+o&&f+l>=a?t.colSpan-=De.getOverlapRangeAtIndex(r,r+o,f,f+l):s>0&&(fa+o)&&p.push({cell:t,i:m,rs:m+s}),g+=l}else{if(v>=a)break;if(l>0){if(d<1&&l+v>=a){t.colSpan+=1,a=null,d=s+1;break}a-=l}if(!n){for(let t,e=0;e0){d-=1;continue}null!==a&&e.length>0&&(s=ih(e[0].nodeName),s=t.insertBefore(s,e[a]))}}const g=this.#rd._element.querySelector("colgroup");if(g){const t=g.querySelectorAll("col");if(i)Pe.utils.removeItem(t[a]);else{if(!(!Pe.utils.hasClass(this.#rd._element,"se-table-layout-fixed")&&"fixed"!==this.#rd._element.style.tableLayout)&&Array.prototype.some.call(t,(t=>De.get(t.style.width)>0))){let e=0;for(let s,i=0,n=t.length;ir&&r>e&&(t[n].rowSpan=s+l,h-=i)}if(i){const t=a[o+1];if(t){const e=[];let s=a[o].cells,i=0;for(let t,n,o=0,r=s.length;o1&&(t.rowSpan-=1,e.push({cell:t.cloneNode(!0),index:n}));if(e.length>0){let n=e.shift();s=t.cells,i=0;for(let o,r,l=0,a=s.length;l=n.index)||(l--,i--,i+=n.cell.colSpan-1,t.insertBefore(n.cell,o),n=e.shift(),n));l++);if(n){t.appendChild(n.cell);for(let s=0,i=e.length;s1)for(;Pe.check.isTableRow(t)&&s>1;)t=t.nextElementSibling,--s;this.#ld.deleteStyleSelectedCells(),this.#rd.setRowInfo(t),this.#J.ui.enableBackWrapper("ns-resize"),this.#pd||=this.#J.frameContext.get("wrapper").querySelector(Pa),this.#gd=this.#J.frameContext.get("wrapper").querySelector(Da),this._startRowResizing(t,i.startY,De.get(dh.getComputedStyle(t).height,0)),this.#rd._editorEnable(!1)}catch(t){console.warn("[SUNEDITOR.plugins.table.error]",t),this.#rd._editorEnable(!0),this.#hi()}finally{this.#rd.setState("fixedCell",null),this.#rd.setState("selectedCell",null),this.#rd.controller_table.hide(),this.#rd.controller_cell.hide()}return!1}}#bd(t){const e=t.querySelector("colgroup").querySelectorAll("col"),s=t.offsetWidth;e.forEach((t=>{const e=t.style.width;if(!e.endsWith("%")){const i=(t.offsetWidth||De.get(e,0))/s*100;t.style.width=i+"%"}}))}_startCellResizing(t,e,s,i){const n=this.#I.figureElement;Pe.utils.removeClass(n,"se-component-selected"),this.#bd(this.#rd._element),this.#md(n,this.#I.tdElement,this.#gd,i),this.#gd.style.display="block";const o=t.style.width,r=t.nextElementSibling,l=r.style.width,a=Pe.utils.hasClass(this.#rd._element,"se-table-layout-fixed")?l:ze.getWidthInPercentage(r||t);_i.get("__dragHandler")&&(_i.get("__dragHandler").style.display="none"),this.#yd(this.#wd.bind(this,t,r,n,this.#I.tdElement,this.#pd,i,e,s,De.get(o,0),De.get(a,0),this.#rd._element.offsetWidth),(()=>{this.#hi(),this.#bd(this.#rd._element),this.#J.history.push(!0),this.#J.component.hoverSelect(this.#rd._element),this.#rd._editorEnable(!0)}),(e=>{this._stopResize(t,o,"width",e),this._stopResize(r,l,"width",e)}))}#wd(t,e,s,i,n,o,r,l,a,h,c,d){const u=(l+(d.clientX-r))/c*100;if(u>0){t.style.width=`${u}%`;const r=a-u;e.style.width=`${h+r}%`,this.#md(s,i,n,o)}}_startRowResizing(t,e,s){const i=this.#I.figureElement;Pe.utils.removeClass(i,"se-component-selected"),this.#fd(i,t,this.#gd),this.#gd.style.display="block";const n=t.style.height;_i.get("__dragHandler")&&(_i.get("__dragHandler").style.display="none"),this.#yd(this.#Cd.bind(this,t,i,this.#pd,e,s),(()=>{this.#hi(),this.#J.history.push(!0),this.#J.component.hoverSelect(this.#rd._element),this.#rd._editorEnable(!0)}),this._stopResize.bind(this,t,n,"height"))}#Cd(t,e,s,i,n,o){const r=n+(o.clientY-i);t.style.height=`${r}px`,this.#fd(e,t,s)}_startFigureResizing(t,e){const s=this.#I.figureElement;Pe.utils.removeClass(s,"se-component-selected"),this.#md(s,s,this.#gd,e),this.#gd.style.display="block";const i=ze.getWidthInPercentage(s);_i.get("__dragHandler")&&(_i.get("__dragHandler").style.display="none"),this.#yd(this.#_d.bind(this,s,this.#pd,e,t,s.offsetWidth,De.get(i,0)),(()=>{this.#hi(),De.get(s.style.width,0)>100&&(s.style.width="100%"),this.#J.history.push(!0),this.#J.component.hoverSelect(this.#rd._element),this.#rd._editorEnable(!0)}),this._stopResize.bind(this,s,s.style.width,"width"))}#_d(t,e,s,i,n,o,r){const l=(n+(s?i-r.clientX:r.clientX-i))/n*o;l>0&&(t.style.width=`${l}%`,this.#md(t,t,e,s))}#md(t,e,s,i){const n=this.#J.offset.getLocal(e),o=this.#J.offset.getLocal(t);s.style.left=`${n.left+(i?0:e.offsetWidth)}px`,s.style.top=`${o.top}px`,s.style.height=`${t.offsetHeight}px`}#fd(t,e,s){const i=this.#J.offset.getLocal(e),n=this.#J.offset.getLocal(t);s.style.top=`${i.top+e.offsetHeight}px`,s.style.left=`${n.left}px`,s.style.width=`${t.offsetWidth}px`}_stopResize(t,e,s,i){Fe.isEsc(i.code)&&(this.#hi(),this.#J.component.hoverSelect(this.#rd._element),this.#rd._editorEnable(!0),t.style[s]=e,"width"===s&&this.#J.component.select(this.#rd._element,this.#rd.constructor.key,{isInput:!0}))}#yd(t,e,s){this.#it.resize=this.#J.eventManager.addGlobalEvent("mousemove",t,!1),this.#it.resizeStop=this.#J.eventManager.addGlobalEvent("mouseup",e,!1),this.#it.resizeKeyDown=this.#J.eventManager.addGlobalEvent("keydown",s,!1),this.#ud=!0}#hi(){this.#ud=!1,this.#J.ui.disableBackWrapper(),this.#vd(),this.#gd&&(this.#gd.style.display="none",this.#gd=null);const t=this.#it;for(const e in t)t[e]&&=this.#J.eventManager.removeGlobalEvent(t[e]);this.#ud=!1,this.#pd=null}#vd(){this.#pd&&(this.#pd.style.display="none",this.#pd=null),this.#rd._element&&(this.#rd._element.style.cursor="")}init(){this.#hi()}};const ph=class{#rd;#J;#I;#kd;#xd;#$d;#Sd;#it;#Ed=null;constructor(t){this.#rd=t,this.#J=t.$,this.#I=t.state,this.#kd=this.#Td.bind(this),this.#xd=this.#Md.bind(this),this.#$d=this.#Nd.bind(this),this.#Sd=this.#Bd.bind(this),this.#it={on:null,off:null,shiftOff:null,touchOff:null,resize:null,resizeStop:null,resizeKeyDown:null}}get#hd(){return this.#rd.cellService}selectCells(t){const e=t[0],s=Pe.query.findVisualLastCell(t);return this.#Ed=e.nodeName,this.setMultiCells(e,s),{fixedCell:e,selectedCell:s}}setMultiCells(t,e){const s=this.#I.selectedTable,i=s.rows;if(this.deleteStyleSelectedCells(),Pe.utils.addClass(t,"se-selected-table-cell"),t===e&&!this.#I.isShiftPressed)return;const n=function(t,e){const s=t.parentNode,i=e.parentNode;return`${s.rowIndex},${t.cellIndex}-${i.rowIndex},${e.cellIndex}`}(t,e);let o=Xa.get(s);const r=o?.get(n);if(r)return this.#rd.setState("ref",r),void this.#Id(i,r);const l=this.#Ld(i,t,e);this.#rd.setState("ref",l),o||(o=new Map,Xa.set(s,o)),o.set(n,l),this.#Id(i,l)}#Ld(t,e,s){let i=!0,n=[],o=[];const r={_i:0,cs:null,ce:null,rs:null,re:null};for(let l,a,h=0,c=t.length;h0)for(let t,e=0;eh||(c>=t.index?(a+=t.cs,c+=t.cs,t.rs-=1,t.row=h+1,t.rs<1&&(n.splice(e,1),e--)):p===g-1&&(t.rs-=1,t.row=h+1,t.rs<1&&(n.splice(e,1),e--)));if(i){if(t!==e&&t!==s||(r.cs=null!==r.cs&&r.csc+d?r.ce:c+d,r.rs=null!==r.rs&&r.rsh+u?r.re:h+u,r._i+=1),2===r._i){i=!1,n=[],o=[],h=-1;break}}else{const t=r.csc+d?r.ce:c+d,s=r.rsh+u?r.re:h+u;if(De.getOverlapRangeAtIndex(r.cs,r.ce,c,c+d)&&De.getOverlapRangeAtIndex(r.rs,r.re,h,h+u)&&(r.cs!==t||r.ce!==e||r.rs!==s||r.re!==i)){r.cs=t,r.ce=e,r.rs=s,r.re=i,h=-1,n=[],o=[];break}}u>0&&o.push({index:c,cs:d+1,rs:u,row:-1}),a+=t.colSpan-1}n=n.concat(o).sort(((t,e)=>t.index-e.index)),o=[]}return r}#Id(t,e){let s=[],i=[];for(let n,o,r=0,l=t.length;r0)for(let t,e=0;er||(l>=t.index?(o+=t.cs,l+=t.cs,t.rs-=1,t.row=r+1,t.rs<1&&(s.splice(e,1),e--)):c===d-1&&(t.rs-=1,t.row=r+1,t.rs<1&&(s.splice(e,1),e--)));De.getOverlapRangeAtIndex(e.cs,e.ce,l,l+a)&&De.getOverlapRangeAtIndex(e.rs,e.re,r,r+h)&&Pe.utils.addClass(t,"se-selected-table-cell"),h>0&&i.push({index:l,cs:a+1,rs:h,row:-1}),o+=t.colSpan-1}s=s.concat(i).sort(((t,e)=>t.index-e.index)),i=[]}}initCellSelection(t){this.#rd.setState("fixedCell",t),this.#I.selectedCells?.length||this.#rd.setState("selectedCells",[t]),this.#Ed=t.nodeName,this.#rd.setState("selectedTable",Pe.query.getParentElement(t,"TABLE")),this.deleteStyleSelectedCells(),Pe.utils.addClass(t,"se-selected-cell-focus")}startCellSelection(t,e){this.#I.isShiftPressed||this.#I.ref||this.#hi(),this.#rd.setState("isShiftPressed",e),this.initCellSelection(t),e?(this.#it.shiftOff=this.#J.eventManager.addGlobalEvent("keyup",this.#$d,!1),this.#it.on=this.#J.eventManager.addGlobalEvent("mousedown",this.#kd,!1)):this.#it.on=this.#J.eventManager.addGlobalEvent("mousemove",this.#kd,!1),this.#it.off=this.#J.eventManager.addGlobalEvent("mouseup",this.#xd,!1),this.#it.touchOff=this.#J.eventManager.addGlobalEvent("touchmove",this.#Sd,!1)}deleteStyleSelectedCells(){Pe.utils.removeClass([this.#I.fixedCell,this.#I.selectedCell],"se-selected-cell-focus");const t=this.#I.fixedCell?.closest("table");if(t){const e=t.querySelectorAll(".se-selected-table-cell");for(let t=0,s=e.length;t0?this.#I.selectedCell:e;this.#rd._setController(s)}#Nd(){if(this.#I.ref){this.#hi(),this.#rd._editorEnable(!0),this.focusCellEdge(this.#I.fixedCell);const t=this.#I.selectedCells?.length>0?this.#I.selectedCell:this.#I.fixedCell;this.#rd._setController(t)}else this.#rd._closeController()}#Bd(){this.#rd.resetInfo()}#hi(){this.#J.ui.disableBackWrapper();const t=this.#it;for(const e in t)t[e]&&=this.#J.eventManager.removeGlobalEvent(t[e])}init(){this.#hi()}},{_w:gh}=Oe;const mh=class{#rd;#I;#J;constructor(t,{pluginOptions:e,controller_table:s}){this.#rd=t,this.#I=t.state,this.#J=t.$,this.sliderType="",this.resizeButton=s.querySelector("._se_table_resize"),this.resizeText=s.querySelector("._se_table_resize > span > span"),this.columnFixedButton=s.querySelector("._se_table_fixed_column"),this.headerButton=s.querySelector("._se_table_header"),this.captionButton=s.querySelector("._se_table_caption");const i=function({lang:t,icons:e,options:s}){const i=s.get("_rtl")?["right","center","left","justify"]:["left","center","right","justify"];let n="";for(let s,o,r=0;r\n\t\t\t${e["align_"+s]}\n\t\t\t\n\t\t\t\t${o}\n\t\t\t\n\t\t`;const o=["top","middle","bottom"];let r="";for(let s,i,n=0;n\n\t\t\t${e["align_"+s]}\n\t\t\t\n\t\t\t\t${i}\n\t\t\t\n\t\t`;const l=`\n\t\t
    \n\t\t\t
    \n\t\t\t\t\n\t\t\t\t${t.tableProperties}\n\t\t\t
    \n\t\t\t
    \n\n\t\t\t\t${t.border}\n\t\t\t\t
    \n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t
    \n\n\t\t\t\t${t.color}\n\t\t\t\t
    \n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t
    \n\n\t\t\t\t${t.font}\n\t\t\t\t
    \n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t
    \n\n\t\t\t\t
    \n\t\t\t\t\t${t.align} ( ${t.table} )\n\t\t\t\t\t
    \n\t\t\t\t\t\t
    \n\t\t\t\t\t\t\t${n}\n\t\t\t\t\t\t
    \n\t\t\t\t\t\t
    \n\t\t\t\t\t\t\t${r}\n\t\t\t\t\t\t
    \n\t\t\t\t\t
    \n\t\t\t\t
    \n\t\t\t
    \n\t\t\t
    \n\t\t\t\t\n\t\t\t\t\n\t\t\t
    \n\t\t
    `,a=Pe.utils.createElement("DIV",{class:"se-controller se-table-props"},l);return{html:a,controller_props_title:a.querySelector(".se-controller-title"),borderButton:a.querySelector('[data-command="props_onborder_style"]'),borderFormatButton:a.querySelector('[data-command="props_onborder_format"]'),cell_alignment:a.querySelector(".se-table-props-align .__se__a_h"),cell_alignment_vertical:a.querySelector(".se-table-props-align .__se__a_v"),cell_alignment_table_text:a.querySelector(".se-table-props-align .__se__a_table_t"),border_style:a.querySelector('[data-command="props_onborder_style"] .se-txt'),border_color:a.querySelector(".__se_border_color"),border_width:a.querySelector(".__se__border_size"),back_color:a.querySelector(".__se_back_color"),font_color:a.querySelector(".__se_font_color"),palette_border_button:a.querySelector('[data-command="props_onpalette"][data-value="border"]'),font_bold:a.querySelector('[data-command="props_font_style"][data-value="bold"]'),font_underline:a.querySelector('[data-command="props_font_style"][data-value="underline"]'),font_italic:a.querySelector('[data-command="props_font_style"][data-value="italic"]'),font_strike:a.querySelector('[data-command="props_font_style"][data-value="strike"]')}}(this.#J),n=[this.#rd.controller_table,this.#rd.controller_cell];this.controller_props=new Ii(this,this.#J,i.html,{position:"bottom",parents:n,isInsideForm:!0}),this.controller_props_title=i.controller_props_title;const o=Pe.utils.createElement("DIV",{class:"se-controller se-list-layer"},null);this.controller_colorPicker=new Ii(this,this.#J,o,{position:"bottom",parents:[this.controller_props].concat(n),isInsideForm:!0,isWWTarget:!1,initMethod:()=>{this.colorPicker.hueSlider.close(),Pe.utils.removeClass(this.controller_colorPicker.currentTarget,"on")}}),this.colorPicker=new zl(this,this.#J,"",{form:o,colorList:e.colorList||Ga,splitNum:5,disableRemove:!0,hueSliderOptions:{controllerOptions:{isOutsideForm:!0,parents:[this.controller_colorPicker],parentsHide:!0}}});const r=function(){let t="";for(let e,s=0,i=Fa.length;s\n\t\t\t${e}\n\t\t`;const e=Pe.utils.createElement("DIV",null,t);return{items:Fa,menus:e.querySelectorAll("div")}}(),l=i.borderButton;this.selectMenu_props_border=new Ai(this.#J,{checkList:!1,position:"bottom-center"}),this.selectMenu_props_border.on(l,this.#Ad.bind(this)),this.selectMenu_props_border.create(r.items,r.menus);const a=lh(this.#J.lang,this.#J.icons,[]),h=i.borderFormatButton;this.selectMenu_props_border_format=new Ai(this.#J,{checkList:!1,position:"bottom-left",dir:"ltr",splitNum:5}),this.selectMenu_props_border_format.on(h,this.#Od.bind(this,"all")),this.selectMenu_props_border_format.create(a.items,a.menus);const c=lh(this.#J.lang,this.#J.icons,qa);this.selectMenu_props_border_format_oneCell=new Ai(this.#J,{checkList:!1,position:"bottom-left",dir:"ltr",splitNum:6}),this.selectMenu_props_border_format_oneCell.on(h,this.#Od.bind(this,"outside")),this.selectMenu_props_border_format_oneCell.create(c.items,c.menus),this.maxText=this.#J.lang.maxSize,this.minText=this.#J.lang.minSize,this.propTargets={cell_alignment:i.cell_alignment,cell_alignment_vertical:i.cell_alignment_vertical,cell_alignment_table_text:i.cell_alignment_table_text,border_format:h,border_style:i.border_style,border_color:i.border_color,border_width:i.border_width,back_color:i.back_color,font_color:i.font_color,palette_border_button:i.palette_border_button,font_bold:i.font_bold,font_underline:i.font_underline,font_italic:i.font_italic,font_strike:i.font_strike},this._propsCache=[],this._currentFontStyles=[],this._propsAlignCache="",this._propsVerticalAlignCache="",this._typeCache=""}get#ld(){return this.#rd.selectionService}colorPickerAction(t){this.applyColorPicker(t)}controllerAction(t){const e=t.getAttribute("data-command");if(!e)return;const s=t.getAttribute("data-value");switch(e){case"props_onborder_format":this.openBorderFormatMenu();break;case"props_onborder_style":this.openBorderStyleMenu();break;case"props_onpalette":this.openColorPalette(t,s);break;case"props_font_style":this.toggleFontStyle(s);break;case"props_submit":this.submitProps(t);break;case"props_align":this.setAlignProps(t.getAttribute("data-value"));break;case"props_align_vertical":this.setVerticalAlignProps(t.getAttribute("data-value"))}}openTableProps(t){this.controller_props.currentTarget===t&&"block"===this.controller_props.form?.style.display?this.controller_props.close():(this.controller_props_title.textContent=this.#J.lang.tableProperties,this.#Rd("table"),this.controller_props.open(t,this.#rd.controller_table.form,{isWWTarget:!1,initMethod:null,addOffset:null}))}openCellProps(t){this.controller_props.currentTarget===t&&"block"===this.controller_props.form?.style.display?this.controller_props.close():(this.controller_props_title.textContent=this.#J.lang.cellProperties,this.#Rd("cell"),this.controller_props.open(t,this.#rd.controller_cell.form,{isWWTarget:!1,initMethod:null,addOffset:null}))}openBorderFormatMenu(){1===this._propsCache.length?this.selectMenu_props_border_format_oneCell.open():this.selectMenu_props_border_format.open()}openBorderStyleMenu(){this.selectMenu_props_border.open()}openColorPalette(t,e){const{back_color:s,font_color:i,border_color:n}=this.propTargets,o="border"===e?n:"back"===e?s:i;this.controller_colorPicker.isOpen&&e===this.sliderType?this.controller_colorPicker.close():(this.sliderType=e,Pe.utils.addClass(t,"on"),this.colorPicker.init(o?.value||"",t),this.controller_colorPicker.open(t,null,{isWWTarget:!1,initMethod:null,addOffset:null}))}toggleFontStyle(t){Pe.utils.toggleClass(this.propTargets[`font_${t}`],"on")}toggleHeader(){const t=this.headerButton,e=Pe.utils.hasClass(t,"active"),s=this.#rd._element;if(rh(s),e)Pe.utils.removeItem(s.querySelector("thead"));else{const t=Pe.utils.createElement("THEAD");t.innerHTML=""+sh("th",this.#I.logical_cellCnt)+"",s.insertBefore(t,s.querySelector("tbody"))}Pe.utils.toggleClass(t,"active"),/TH/i.test(this.#I.tdElement.nodeName)?this.#rd._closeController():this.#rd._setCellControllerPosition(this.#I.tdElement,!1)}toggleCaption(){const t=this.captionButton,e=Pe.utils.hasClass(t,"active"),s=this.#rd._element;if(e)Pe.utils.removeItem(s.querySelector("caption"));else{const t=Pe.utils.createElement("CAPTION",{class:`se-table-caption-${this.#rd.captionPosition}`});t.innerHTML="

    ",s.insertBefore(t,s.firstElementChild)}Pe.utils.toggleClass(t,"active"),this.#rd._setCellControllerPosition(this.#I.tdElement,!1)}resetHeaderButton(t){t.querySelector("thead")?Pe.utils.addClass(this.headerButton,"active"):Pe.utils.removeClass(this.headerButton,"active")}resetCaptionButton(t){t.querySelector("caption")?Pe.utils.addClass(this.captionButton,"active"):Pe.utils.removeClass(this.captionButton,"active")}resetPropsAlign(){const{cell_alignment:t}=this.propTargets,e=t.querySelector('[data-value="left"]'),s=t.querySelector('[data-value="right"]'),i=e.parentElement,n=s.parentElement;i.appendChild(s),n.appendChild(e)}revertProps(){const t=this._propsCache;for(let e=0,s=t.length;enew Array(r-o+1).fill(0))),a=o;n-=e,e-=e,r-=o,o-=o;let h=t;for(let t,i,c,d,u,p=0,g=0,m=s.length,y=0;p1){const t=u-1;for(let e=y;e<=y+t;e++)l[e][c]+=d-(y===e?1:0)}else d>1&&(l[y][c]+=d-1)}catch{}const w=y+u-1===n;y===e&&$.top.push(t),(y===n||w)&&$.bottom.push(t),c===o&&$.left.push(t),c!==r&&c+d-1!==r||$.right.push(t),w||y===e||y===n||c===o||c===r||$.middle.push(t),i=t.style,i.textAlign=v,i.verticalAlign=b,i.backgroundColor=C,i.color=_,this.#Pd(i),k||(i.border=f?i.borderLeft=i.borderTop=i.borderRight=i.borderBottom="":x)}0===$.middle.length&&($.middle=s)}$.all=s,k&&this.#Dd($,p,x),this.#rd.historyPush(),this.controller_props.close(),this.#I.tdElement&&(this.#ld.recallStyleSelectedCells(),this.#rd.setCellInfo(this.#I.tdElement,!0),Pe.utils.addClass(this.#I.tdElement,"se-selected-cell-focus"))}catch(t){console.warn("[SUNEDITOR.plugins.table.setProps.error]",t)}finally{t.disabled=!1}}closeProps(){this.controller_props.close(),this.controller_colorPicker.close()}#Rd(t){this._typeCache=t;const e="table"===t,s=e?[this.#rd._element]:this.#I.selectedCells;if(!s?.[0])return;const{border_format:i,border_color:n,border_style:o,border_width:r,back_color:l,font_color:a,cell_alignment:h,cell_alignment_vertical:c,cell_alignment_table_text:d,font_bold:u,font_underline:p,font_italic:g,font_strike:m}=this.propTargets,{border:f,backgroundColor:v,color:b,textAlign:y,verticalAlign:w,fontWeight:C,textDecoration:_,fontStyle:k}=gh.getComputedStyle(s[0]),x=this.#Fd(f);h.querySelector('[data-value="justify"]').style.display=e?"none":"",d.style.display=e?"":"none",c.style.display=e?"none":"";let $=ze.rgb2hex(x.c),S=x.s,E=x.w,T=ze.rgb2hex(v),M=ze.rgb2hex(b),N=/.+/.test(C),B=/underline/i.test(_),I=/line-through/i.test(_),L=/italic/i.test(k),A=e?this.#I.figureElement?.style.float:y,O=w;this._propsCache=[];for(let t,i,n=0;t=s[n];n++){const{cssText:s,border:n,backgroundColor:o,color:r,textAlign:l,verticalAlign:a,fontWeight:h,textDecoration:c,fontStyle:d}=t.style;if(this._propsCache.push([t,s]),i)continue;const{c:u,s:p,w:g}=this.#Fd(n);let m=o,f=r;if(m||f){const e=gh.getComputedStyle(t);m&&(m=e.backgroundColor),f&&(f=e.color)}$&&x.c!==u&&($=""),S&&x.s!==p&&(S=""),E&&x.w!==g&&(E=""),T!==ze.rgb2hex(m)&&(T=""),M!==ze.rgb2hex(f)&&(M=""),A!==(e?this.#I.figureElement?.style.float:l)&&(A=""),O&&O!==a&&(O=""),N&&N!==/.+/.test(h)&&(N=!1),B&&B!==/underline/i.test(c)&&(B=!1),I&&I!==/line-through/i.test(c)&&(I=!1),L&&L!==/italic/i.test(d)&&(L=!1),$&&S&&E&&T&&M||(i=!0)}i.firstElementChild.innerHTML=this.#J.icons[Ha[1===s.length?"outside":"all"]],i.setAttribute("se-border-format","all"),Pe.utils.removeClass(i,"active"),S||=Fa[0],o.textContent=S,n.style.borderColor=n.value=$,r.value=E,this.#Hd(S===Fa[0]),l.value=l.style.borderColor=T,a.value=a.style.borderColor=M,N&&Pe.utils.addClass(u,"on"),B&&Pe.utils.addClass(p,"on"),I&&Pe.utils.addClass(m,"on"),L&&Pe.utils.addClass(g,"on"),this.#zd(h,this._propsAlignCache=A,!0),this.#zd(c,this._propsVerticalAlignCache=O,!0)}#Pd(t){const{font_bold:e,font_italic:s,font_strike:i,font_underline:n}=this.propTargets;t.fontWeight=Pe.utils.hasClass(e,"on")?"bold":"",t.fontStyle=Pe.utils.hasClass(s,"on")?"italic":"",t.textDecoration=((Pe.utils.hasClass(i,"on")?"line-through ":"")+(Pe.utils.hasClass(n,"on")?"underline":"")).trim()}#Fd(t){const e=t.split(/\s(?![^()]*\))/);let s="",i="",n="";return 3===e.length?(s=e[0],i=e[1],n=e[2]):2===e.length?/\d/.test(e[0])?(s=e[0],i=e[1]):(i=e[0],n=e[1]):1===e.length&&(/\d/.test(e[0])?s=e[0]:i=e[0]),{w:s,s:i,c:ze.rgb2hex(n)}}#Dd(t,e,s){const{left:i,top:n,right:o,bottom:r,all:l}=t;switch(e){case"inside":if(1===l.length)return;Pe.utils.setStyle(l.filter((t=>!r.includes(t))),ja,s),Pe.utils.setStyle(l.filter((t=>!o.includes(t))),Va,s);break;case"horizon":if(1===l.length)return;Pe.utils.setStyle(l.filter((t=>!r.includes(t))),ja,s);break;case"vertical":if(1===l.length)return;Pe.utils.setStyle(l.filter((t=>!o.includes(t))),Va,s);break;case"outside":Pe.utils.setStyle(i,Wa,s),Pe.utils.setStyle(n,Ua,s),Pe.utils.setStyle(o,Va,s),Pe.utils.setStyle(r,ja,s);break;case"left":Pe.utils.setStyle(i,Wa,s);break;case"top":Pe.utils.setStyle(n,Ua,s);break;case"right":Pe.utils.setStyle(o,Va,s);break;case"bottom":Pe.utils.setStyle(r,ja,s)}}#Hd(t){const{border_color:e,border_width:s,palette_border_button:i}=this.propTargets;t?(e.disabled=!0,s.disabled=!0,i.disabled=!0,s.disabled=!0):(e.disabled=!1,s.disabled=!1,i.disabled=!1,s.disabled=!1)}#zd(t,e,s){Pe.utils.removeClass(t.querySelectorAll("button"),"on"),s||t.getAttribute("se-cell-align")!==e?(Pe.utils.addClass(t.querySelector(`[data-value="${e}"]`),"on"),t.setAttribute("se-cell-align",e)):t.setAttribute("se-cell-align","")}#Ad(t){this.propTargets.border_style.textContent=t,this.#Hd(t===Fa[0]),this.selectMenu_props_border.close()}#Od(t,e){const{border_format:s}=this.propTargets;s.setAttribute("se-border-format",e),s.firstElementChild.innerHTML=this.#J.icons[Ha[e]],e!==t?Pe.utils.addClass(s,"active"):Pe.utils.removeClass(s,"active"),this.selectMenu_props_border_format.close(),this.selectMenu_props_border_format_oneCell.close()}init(){const{border_format:t,border_color:e,border_style:s,border_width:i,back_color:n,font_color:o,cell_alignment:r,cell_alignment_vertical:l,font_bold:a,font_underline:h,font_italic:c,font_strike:d}=this.propTargets;Pe.utils.removeClass([t,e,s,i,n,o,r,l,a,h,c,d],"on")}},{_w:fh,ON_OVER_COMPONENT:vh}=Oe;class bh extends Zl{static key="table";static className="";static options={isInputComponent:!0};static component(t){return Pe.check.isTable(t)?t:null}#qd;#Wd;#Ud;#Vd;#jd;#Gd=[];#Kd=!0;#Yd=!1;#Xd=!1;constructor(t,e){super(t),this.title=this.$.lang.table,this.icon="table",this.figureScrollList=["se-scroll-figure-xy","se-scroll-figure-x","se-scroll-figure-y"],this.figureScroll="string"==typeof e.scrollType?e.scrollType.toLowerCase():"x",this.captionPosition="bottom"!==e.captionPosition?"top":"bottom",this.cellControllerTop="table"==("cell"!==e.cellControllerPosition?"table":"cell");const s=Pe.utils.createElement("DIV",{class:"se-dropdown se-selector-table"},'\n\t
    \n\t\t
    \n\t\t
    \n\t\t
    \n\t
    \n\t
    1 x 1
    '),i=s.querySelector(".se-controller-table-picker"),n=function({lang:t,icons:e}){const s=`\n\t
    \n\t
    \n\t\t\n\t\t\n\t\t\n\t\t\n\t\t\n\t\t\n\t\t\n\t
    `;return Pe.utils.createElement("DIV",{class:"se-controller se-controller-table"},s)}(this.$),o=function({lang:t,icons:e},s){const i=`\n\t
    \n
    \n\t\t\n \n \n \n \n\t\t\n
    `,n=Pe.utils.createElement("DIV",{class:"se-controller se-controller-table-cell"},i);return{html:n,splitButton:n.querySelector('[data-command="onsplit"]'),columnButton:n.querySelector('[data-command="oncolumn"]'),rowButton:n.querySelector('[data-command="onrow"]'),mergeButton:n.querySelector('[data-command="merge"]'),unmergeButton:n.querySelector('[data-command="unmerge"]')}}(this.$,this.cellControllerTop);this.$.contextProvider.applyToRoots((t=>{t.get("wrapper").appendChild(Pe.utils.createElement("DIV",{class:Ra.replace(/^\./,"")})),t.get("wrapper").appendChild(Pe.utils.createElement("DIV",{class:za.replace(/^\./,"")})),t.get("wrapper").appendChild(Pe.utils.createElement("DIV",{class:Pa.replace(/^\./,"")})),t.get("wrapper").appendChild(Pe.utils.createElement("DIV",{class:Da.replace(/^\./,"")}))})),this.cellControllerTop?(this.controller_cell=new Ii(this,this.$,o.html,{position:"top"}),this.controller_table=new Ii(this,this.$,n,{position:"top"}),this.controller_cell.sibling=this.controller_table.form,this.controller_table.sibling=this.controller_cell.form,this.controller_table.siblingMain=!0):(this.controller_table=new Ii(this,this.$,n,{position:"top"}),this.controller_cell=new Ii(this,this.$,o.html,{position:"bottom"})),this.figure=new ji(this,this.$,null,{}),this._element=null,this.state=Ka,this.#qd=s,this.#Wd=s.querySelector(".se-table-size-highlighted"),this.#Ud=s.querySelector(".se-table-size-unhighlighted"),this.#Vd=s.querySelector(".se-table-size-display");const r=yh.bind(this,!0),l=yh.bind(this,!1),a={...o,openCellMenuFunc:r,closeCellMenuFunc:l};this.cellService=new ah(this,a),this.clipboardService=new hh(this),this.gridService=new ch(this,a),this.resizeService=new uh(this),this.selectionService=new ph(this),this.styleService=new mh(this,{pluginOptions:e,controller_table:n}),this.$.menu.initDropdownTarget(bh,s),this.$.eventManager.addEvent(i,"mousemove",this.#Zd.bind(this)),this.$.eventManager.addEvent(i,"click",this.#Jd.bind(this))}setState(t,e){this.state[t]=e}#Qd(){Object.assign(this.state,Ka)}off(){this.#tu()}componentSelect(t){if(this.#eu(t),this.state.figureElement||this.setTableInfo(t),this.#Kd="100%"===this.state.figureElement?.style.width,this.#Yd=Pe.utils.hasClass(t,"se-table-layout-fixed")||"fixed"===t.style.tableLayout,this.styleService.setTableLayout(this.#Kd?"width|column":"width",this.#Kd,this.#Yd,!0),_i.get("__overInfo")===vh)return;if(!this.state.tdElement)return;this.setCellInfo(this.state.tdElement,!0);const e=this.state.selectedCells?.length>1,s=Pe.query.getParentElement(t,Pe.check.isFigure);this.controller_table.open(s,null,{isWWTarget:!1,initMethod:null,addOffset:null,disabled:e}),this.state.fixedCell&&(this.cellService.setUnMergeButton(),this.controller_cell.open(this.state.tdElement,this.cellControllerTop?s:null,{isWWTarget:!1,initMethod:null,addOffset:null,disabled:e}))}componentDeselect(){this.resetInfo()}componentDestroy(t){if(!t)return;const e=t.parentNode;Pe.utils.removeItem(t),this._closeTableSelectInfo(),e!==this.$.frameContext.get("wysiwyg")&&this.$.nodeTransform.removeAllParents(e,(function(t){return 0===t.childNodes.length}),null),this.$.focusManager.focus(),this.$.history.push(!1)}componentCopy({event:t,cloneContainer:e}){const s=e.querySelectorAll(".se-selected-table-cell");Pe.utils.removeClass(s,"se-selected-table-cell|se-selected-cell-focus"),s.length>0&&(this.clipboardService.copySelectedTableCells(t,e,s),this.$.ui.showToast(this.$.lang.message_copy_success,550))}onPaste({event:t,doc:e}){const s=Pe.query.getParentElement(Pe.query.getEventTarget(t),Pe.check.isTableCell);if(!s)return;const i=e.body;if(1!==i.childElementCount)return;const n=this.$.component.get(i.firstElementChild);if(n?.pluginName!==bh.key)return;const o=n.target,r=this.clipboardService.pasteTableCellMatrix(o,s),{fixedCell:l,selectedCell:a}=this.selectionService.selectCells(r);return this.setState("selectedCells",r),this.setState("fixedCell",l),this.setState("selectedCell",a),this.setState("selectedTable",Pe.query.getParentElement(l,"TABLE")),!1}retainFormat(){return{query:"table",method:t=>{const e=t.querySelector("colgroup");let s=Pe.check.isFigure(t.parentNode)?t.parentNode:null;if(!e){const e=t.rows,s=function(t){const e=t.rows;let s=0;for(let t=0,i=e.length;t=s)break;n&&!i[r]&&(i[r]=n);for(let t=0;t=s||!n)continue;l[r+t]=!0;const e=De.get(n,-1);for(let t=0;t=s)continue;const l=i[o];if(null===l)i[o]=`width: ${n};`;else{const t=De.get(l.replace("width: ","").replace(";",""),-1);1===a&&e!==t&&(i[o]=`width: ${n};`)}}}r+=a}if(t===s)break}const n=[];for(let t=0;t`)}const o=Pe.utils.createElement("colgroup",null,n.join(""));t.insertBefore(o,t.firstElementChild);for(let t=0;te!==t)).join("|"))}else Pe.utils.removeClass(s,this.figureScrollList.join("|"))}}}setDir(){this.#tu(),this.styleService.resetPropsAlign()}onMouseMove({event:t}){if(this.resizeService.isResizing())return;const e=Pe.query.getEventTarget(t),s=Pe.query.getParentElement(e,Ja);s&&1!==t.buttons?!1!==this.resizeService.onResizeGuide(t,s)&&(this._element&&(this._element.style.cursor=""),this.resizeService.offResizeGuide()):this.resizeService.offResizeGuide()}onMouseDown({event:t}){this.setState("ref",null),this.setState("selectedCell",null);const e=Pe.query.getEventTarget(t);if(this._element&&Pe.query.getParentElement(e,Qa))return void this._closeController();const s=Pe.query.getParentElement(e,Ja);s&&(this.cellControllerTop||this.controller_cell.hide(),!1!==this.resizeService.readyResizeFromEdge(t,s)&&(this.state.isShiftPressed&&s!==this.state.fixedCell||(this.selectionService.deleteStyleSelectedCells(),/^TR$/i.test(s.nodeName)||(this.#Xd=!1,this.selectionService.startCellSelection(s,!1)))))}onMouseUp(){this.setState("isShiftPressed",!1)}onMouseLeave(){this.resizeService.offResizeGuide()}onKeyDown({event:t,range:e,line:s}){this.setState("ref",null);const i=t.code,n=Fe.isTab(i);if(this.$.ui.selectMenuOn||this.resizeService.isResizing()||!n&&this.#Xd||Fe.isCtrl(t))return;if(this.cellControllerTop||this.controller_cell.hide(),this.#Xd=Fe.isShift(t),n){this.selectionService.deleteStyleSelectedCells();const i=Pe.query.getParentElement(s,Pe.check.isTableCell);if(i&&e.collapsed&&Pe.check.isEdgePoint(e.startContainer,e.startOffset)){this._closeController();const e=this.#Xd;this.setState("isShiftPressed",this.#Xd=!1);const s=Pe.query.getParentElement(i,"table"),n=Pe.query.getListChildren(s,Pe.check.isTableCell,null),o=e?Pe.utils.prevIndex(n,i):Pe.utils.nextIndex(n,i);if(o===n.length&&!e){if(!Pe.query.getParentElement(i,"thead")){const t=s.rows,e=this.gridService.insertBodyRow(s,t.length,this.state.cellCnt).querySelector("td div");this.$.selection.setRange(e,0,e,0)}return t.preventDefault(),t.stopPropagation(),!1}if(-1===o&&e)return!1;const r=n[o];if(!r)return;const l=r.firstElementChild||r;return this.$.selection.setRange(l,0,l,0),t.preventDefault(),t.stopPropagation(),!1}}let o=null;if(!Fe.isShift(t)){if(o=Pe.query.getParentElement(s,Pe.check.isTableCell),!Pe.utils.hasClass(o,"se-selected-cell-focus"))return;return this.selectionService.deleteStyleSelectedCells(),this._editorEnable(!0),this.#su(),void this._closeController()}return this.state.isShiftPressed||this.state.ref?void 0:(o||=Pe.query.getParentElement(s,Pe.check.isTableCell),o?(this.#Xd=t.shiftKey,this.setState("fixedCell",o),this._closeController(),this.selectionService.startCellSelection(o,this.#Xd),!1):void 0)}onKeyUp({line:t}){this.#Xd=!1,this.state.isShiftPressed&&Pe.query.getParentElement(t,Pe.check.isTableCell)===this.state.fixedCell&&(this.selectionService.deleteStyleSelectedCells(),this._editorEnable(!0),this.#su()),this.setState("isShiftPressed",!1)}onScroll(){this.resizeService.offResizeGuide()}controllerAction(t){const e=t.getAttribute("data-command");if(e){switch(e){case"header":this.styleService.toggleHeader(),this.historyPush();break;case"caption":this.styleService.toggleCaption(),this.historyPush();break;case"onsplit":this.cellService.openSplitMenu();break;case"oncolumn":this.gridService.openColumnMenu();break;case"onrow":this.gridService.openRowMenu();break;case"openTableProperties":this.styleService.openTableProps(t);break;case"openCellProperties":this.styleService.openCellProps(t);break;case"revert":this.styleService.revertProps();break;case"merge":this.cellService.mergeCells(this.state.selectedCells);break;case"unmerge":this.cellService.unmergeCells(this.state.selectedCells);break;case"resize":this.#Kd=!this.#Kd,this.styleService.setTableLayout("width",this.#Kd,this.#Yd,!1),this.historyPush(),fh.setTimeout((()=>{this.$.component.select(this._element,bh.key,{isInput:!0})}),0);break;case"layout":this.#Yd=!this.#Yd,this.styleService.setTableLayout("column",this.#Kd,this.#Yd,!1),this.historyPush(),fh.setTimeout((()=>{this.$.component.select(this._element,bh.key,{isInput:!0})}),0);break;case"copy":this.$.component.copy(this.state.figureElement);break;case"remove":this.componentDestroy(this.state.figureElement)}/(^revert|Properties$)/.test(e)||this.styleService.closeProps(),/^(remove|on|open)/.test(e)||this._setCellControllerPosition(this.state.tdElement,this.state.isShiftPressed)}}setCellInfo(t,e){const s=this.setTableInfo(t);if(s&&(this.setState("fixedCell",t),this.setState("trElement",t.parentNode),this.styleService.resetHeaderButton(s),this.styleService.resetCaptionButton(s),e||0===this.state.physical_cellCnt)){this.state.tdElement!==t&&this.setState("tdElement",t),this.state.selectedCells?.length||this.setState("selectedCells",[t]);const e=s.rows;this.setState("trElements",e);const i=t.cellIndex;let n=0;for(let t=0,s=e[0].cells,i=e[0].cells.length;t8?10:e+2,o=s<5?5:s>8?10:s+2;if(this.#Ud.style.width=n+"em",this.#Ud.style.height=o+"em",i){const t=n-(this.#jd||5);if(0!==t){const e=De.get(this.#qd.style.left);this.#qd.style.left=e-18*t+"px",this.#jd=n}}Pe.utils.changeTxt(this.#Vd,e+" x "+s),this.#Gd=[e,s]}#Jd(){this.insert(this.#Gd[0],this.#Gd[1])}insert(t,e){const s=t>0?t:Oa[0],i=e>0?e:Oa[1],n=Pe.utils.createElement("TABLE"),o=`${`${sh("td",s)}`.repeat(i)}`,r=`${``.repeat(s)}`;n.innerHTML=r+o;let l="";this.figureScroll&&(l=` se-scroll-figure-${this.figureScroll}`);const a=Pe.utils.createElement("FIGURE",{class:"se-flex-component se-input-component"+l,style:"width: 100%;"});if(a.appendChild(n),this.#Kd=!0,!this.$.component.insert(a,{insertBehavior:"none"}))return!1;this.#tu(),this.$.menu.dropdownOff();const h=n.querySelector("td div");return this.$.selection.setRange(h,0,h,0),!0}#su(){this.resizeService.init(),this.selectionService.init(),this.styleService.init()}}function yh(t){this.controller_cell.bringToTop(t)}const wh=bh;class Ch extends Xl{static key="blockStyle";static className="se-btn-select se-btn-tool-format";constructor(t,e){super(t),this.title=this.$.lang.formats,this.inner=''+this.$.lang.formats+""+this.$.icons.arrow_down;const s=this.$.menu.initDropdownTarget(Ch,function({lang:t},e){const s=["p","blockquote","h1","h2","h3","h4","h5","h6"],i=e&&0!==e.length?e:s,n=[];for(let e,o,r,l,a,h,c,d=0,u=i.length;d${l}`,attrs:{"data-class":c||""}})}return n}(this.$,e.items),{className:"se-list-format"});this.formatList=s.querySelectorAll("li button"),this.currentFormat=""}active(t,e){let s=this.$.lang.formats;const i=e.querySelector(".se-txt");if(t){if(this.$.format.isLine(t)){const e=this.formatList,n=t.nodeName.toLowerCase(),o=(t.className.match(/(\s|^)__se__format__[^\s]+/)||[""])[0].trim();for(let t,i=0,r=e.length;i({command:"layout",value:String(e),title:t.name,innerHTML:t.name})))}(this.items))}action(t){const e=Number(t.getAttribute("data-value")),s=this.items[this.selectedIndex=e];if(!s.html)throw this.$.menu.dropdownOff(),Error('[SUNEDITOR.layout.fail] cause : "layouts[i].html not found"');this.$.html.set(s.html),this.$.menu.dropdownOff()}}const xh=kh;class $h extends Xl{static key="lineHeight";static className="";#nd;constructor(t,e){super(t),this.title=this.$.lang.lineHeight,this.icon="line_height";const s=`
  • `,i=this.$.menu.initDropdownTarget($h,(e.items||[{text:"1",value:"1em"},{text:"1.2",value:"1.2em"},{text:"1.7",value:"1.7em"},{text:"2",value:"2em"}]).map((t=>({command:t.value,title:t.text,innerHTML:t.text}))),{prependHTML:s});this.sizeList=i.querySelectorAll("li button"),this.currentSize=null,this.#nd=i.querySelector(".se-sub-list span")}active(t,e){return this.$.format.isLine(t)&&t.style.lineHeight.length>0?(Pe.utils.addClass(e,"active"),!0):(Pe.utils.removeClass(e,"active"),!1)}on(){const t=this.$.format.getLine(this.$.selection.getNode()),e=t?t.style.lineHeight+"":"";if(e!==this.currentSize){let t=!1;const s=this.sizeList;for(let i=0,n=s.length;i({command:"template",value:String(e),title:t.name,innerHTML:t.name})))}(this.items))}action(t){const e=Number(t.getAttribute("data-value")),s=this.items[this.selectedIndex=e];if(!s.html)throw this.$.menu.dropdownOff(),Error('[SUNEDITOR.template.fail] cause : "templates[i].html not found"');this.$.html.insert(s.html,{selectInserted:!1,skipCharCount:!1,skipCleaning:!1}),this.$.menu.dropdownOff()}}const Th=Eh;class Mh extends Xl{static key="paragraphStyle";static className="";constructor(t,e){super(t),this.title=this.$.lang.paragraphStyle,this.icon="paragraph_style";const s=this.$.menu.initDropdownTarget(Mh,function({lang:t},e){const s={spaced:{name:t.menu_spaced,class:"__se__p-spaced",_class:""},bordered:{name:t.menu_bordered,class:"__se__p-bordered",_class:""},neon:{name:t.menu_neon,class:"__se__p-neon",_class:""}},i=e&&0!==e.length?e:["spaced","bordered","neon"],n=[];for(let t,e,o,r=0,l=i.length;r${e}`,className:t._class||void 0})}return n}(this.$,e.items),{className:"se-list-format"});this.classList=s.querySelectorAll("li button")}on(){const t=this.classList,e=this.$.format.getLine(this.$.selection.getNode());for(let s=0,i=t.length;s${o}`})}return n}(this.$,e.items),{className:"se-list-format"});this.styleList=s.querySelectorAll("li button")}on(){const t=this.styleList,e=this.$.selection.getNode();for(let s,i,n,o=0,r=t.length;o\n\t\t
    \n\t\t\t\n\t\t\t${t.link_modal_title}\n\t\t
    \n\t\t
    \n\t\t\n\t`;return Pe.utils.createElement("DIV",{class:"se-modal-content"},s)}(this.$),i=function({lang:t,icons:e}){const s=`\n\t
    \n\t`;return Pe.utils.createElement("DIV",{class:"se-controller se-controller-link"},s)}(this.$),n="string"==typeof e.uploadUrl?e.uploadUrl:null;this.target=null,this.isUpdateState=!1,this.pluginOptions={...e,uploadUrl:n,uploadHeaders:e.uploadHeaders||null,uploadSizeLimit:De.get(e.uploadSizeLimit,0),uploadSingleSizeLimit:De.get(e.uploadSingleSizeLimit,0),acceptedFormats:"string"==typeof e.acceptedFormats?e.acceptedFormats.trim():null,enableFileUpload:!!n},this.anchor=new Vl(this.$,s,this.pluginOptions),this.modal=new Fl(this,this.$,s),this.controller=new Ii(this,this.$,i,{position:"bottom",disabled:!1}),this.#iu=this.controller.form.querySelector("a")}active(t){if(Pe.check.isAnchor(t)&&!t.hasAttribute("data-se-non-link")){const e=this.#iu,s=t.getAttribute("href");return e.href=s,e.textContent=e.title=t.textContent,e.target=s?.startsWith("#")?t.target:"_blank",Pe.utils.addClass(t,"on"),this.anchor.set(t),this.controller.open(t,null,{isWWTarget:!1,initMethod:null,addOffset:null}),this.target=t,!0}return this.controller.close(),!1}open(){this.modal.open()}modalOn(t){this.isUpdateState=t,this.anchor.on(t)}async modalAction(){const t=this.anchor.create(!1);if(null===t)return!1;if(this.isUpdateState){const t=this.controller.currentTarget.childNodes[0];this.$.selection.setRange(t,0,t,t.textContent.length)}else{const e=this.$.format.getLines();if(e.length>1){if(!this.$.html.insertNode(Pe.utils.createElement(e[0].nodeName,null,t),{afterNode:null,skipCharCount:!1}))return!0}else if(!this.$.html.insertNode(t,{afterNode:null,skipCharCount:!1}))return!0;this.$.selection.setRange(t.childNodes[0],0,t.childNodes[0],t.textContent.length)}return this.$.history.push(!1),!0}modalInit(){this.controller.close(),this.anchor.init()}controllerAction(t){const e=t.getAttribute("data-command");if(/update/.test(e))this.modal.open();else if(/copy/.test(e))this.$.html.copy(this.target);else if(/unlink/.test(e)){const t=Pe.query.getEdgeChild(this.controller.currentTarget,(function(t){return 0===t.childNodes.length||3===t.nodeType}),!1),e=Pe.query.getEdgeChild(this.controller.currentTarget,(function(t){return 0===t.childNodes.length||3===t.nodeType}),!0);this.$.selection.setRange(t,0,e,e.textContent.length),this.$.inline.apply(null,{stylesToModify:null,nodesToRemove:["A"],strictRemove:!1})}else Pe.utils.removeItem(this.controller.currentTarget),this.controller.currentTarget=null,this.$.focusManager.focus(),this.$.history.push(!1)}controllerClose(){Pe.utils.removeClass(this.controller.currentTarget,"on")}},Ah="%",Oh="px",Rh={BLOCK:"block",INLINE:"inline"},zh="image/*";const Ph=class{#rd;#J;#I;#nu;#ud;#ou;#ru;#lu={w:0,h:0};#au=null;#hu=null;#cu=null;constructor(t,e){if(this.#rd=t,this.#J=t.$,this.#I=t.state,this.#nu=t.pluginOptions,this.#ud=this.#nu.canResize,this.#ou="auto"===this.#nu.defaultWidth?"":this.#nu.defaultWidth,this.#ru="auto"===this.#nu.defaultHeight?"":this.#nu.defaultHeight,this.#ud){this.#au=e.proportion,this.#hu=e.inputX,this.#cu=e.inputY,this.#hu.value=this.#nu.defaultWidth,this.#cu.value=this.#nu.defaultHeight;const t=this.#du.bind(this);this.#J.eventManager.addEvent(this.#hu,"keyup",this.#uu.bind(this,"x")),this.#J.eventManager.addEvent(this.#cu,"keyup",this.#uu.bind(this,"y")),this.#J.eventManager.addEvent(this.#hu,"change",t),this.#J.eventManager.addEvent(this.#cu,"change",t),this.#J.eventManager.addEvent(this.#au,"change",t),this.#J.eventManager.addEvent(e.revertBtn,"click",this.#pu.bind(this))}}setInputSize(t,e){this.#hu.value="auto"===t?"":t,this.#I.onlyPercentage||(this.#cu.value="auto"===e?"":e)}getInputSize(){return{w:this.#hu?.value||"",h:this.#cu?.value||""}}setOriginSize(t,e){this.#ou=t,this.#ru=e}applySize(t,e){t||=this.#hu?.value||this.#nu.defaultWidth,e||=this.#cu?.value||this.#nu.defaultHeight,this.#I.onlyPercentage&&(t?/%$/.test(t)||(t+=Ah):t="100%"),this.#rd.figure.setSize(t,e)}on(){if(!this.#ud)return;const t=this.#nu.defaultWidth,e=this.#nu.defaultHeight;this.setInputSize(t,e),this.setOriginSize(t,e)}ready(t,e,s){this.setInputSize(e,s);const i=this.#I.onlyPercentage&&this.#rd.figure.isVertical;this.#au.checked=!0,this.#hu.disabled=i,this.#cu.disabled=i,this.#au.disabled=i,this.#lu=this.#au.checked?t.ratio:{w:0,h:0}}init(){this.#lu={w:0,h:0},this.#ud&&(this.setInputSize(this.#nu.defaultWidth,this.#nu.defaultHeight),this.#au.checked=!0)}#uu(t,e){if(Fe.isSpace(e.code))return void e.preventDefault();const s=e.target;if("x"===t&&this.#I.onlyPercentage&&Number(s.value)>100)s.value="100";else if(this.#au.checked){const e=ji.CalcRatio(this.#hu.value,this.#cu.value,this.#I.sizeUnit,this.#lu);"x"===t?this.#cu.value=String(e.h):this.#hu.value=String(e.w)}}#du(){this.#lu=this.#au.checked?ji.GetRatio(this.#hu.value,this.#cu.value,this.#I.sizeUnit):{w:0,h:0}}#pu(){this.#I.onlyPercentage?this.#hu.value=Number(this.#ou)>100?"100":this.#ou:(this.#hu.value=this.#ou,this.#cu.value=this.#ru)}},{NO_EVENT:Dh}=Oe;const Fh=class{#rd;#J;#nu;#ud;constructor(t){this.#rd=t,this.#J=t.$,this.#nu=t.pluginOptions,this.#ud=this.#nu.canResize,this._base64RenderIndex=0}get#gu(){return this.#rd.sizeService}serverUpload(t){if(!t.files)return;const e=this.#nu.uploadUrl;"string"==typeof e&&e.length>0?this.#rd.fileManager.upload(e,this.#nu.uploadHeaders,t.files,this.#mu.bind(this,t),this.#gc.bind(this)):this.#fu(t)}urlUpload(t){this.#rd.setState("produceIndex",0);const e=t.url;this.#rd.modal.isUpdate?this.#vu(e,t.element,t.files):this.#bu(e,t.anchor,t.inputWidth,t.inputHeight,t.align,t.files,t.alt,!0)}#bu(t,e,s,i,n,o,r,l){this.#rd.as!==Rh.INLINE?this.#rd.create(t,e,s,i,n,o,r,l):this.#rd.createInline(t,e,s,i,o,r,l)}#vu(t,e,s){e.src=t,this.#rd.fileManager.setFileData(e,s),this.#J.component.select(e,this.#rd.constructor.key)}#pc(t,e){this.#rd.setState("produceIndex",0);const s=e.result;for(let e,i=0,n=s.length;i\n\t\t\t\n\t\t\t${Fl.CreateFileInput({icons:e,lang:t},i)}\n\t\t`:"",o=i.createUrlInput?`\n\t\t
    \n\t\t\t\n\t\t\t
    \n\t\t\t\t\n\t\t\t\t${s.imageGallery?``:""}\n\t\t\t
    \n\t\t\t\n\t\t
    `:"",r=i.canResize?`\n\t\t
    \n\t\t\t
    \n\t\t\t\t\n\t\t\t\t\n\t\t\t\t\n\t\t\t
    \n\t\t\t\n\t\t\t\n\t\t\t\n\t\t\t\n\t\t\t\n\t\t
    `:"",l=i.useFormatType?`\n\t\t
    \n\t\t\t
    \n\t\t\t\t\n\t\t\t\t\n\t\t\t
    \n\t\t
    `:"",a=`\n\t\t
    \n\t\t\t\n\t\t\t${t.image_modal_title}\n\t\t
    \n\t\t
    \n\t\t\t\n\t\t\t\n\t\t
    \n\t\t
    \n\t\t\t
    \n\t\t\t\t
    \n\t\t\t\t\t${n}\n\t\t\t\t\t${o}\n\t\t\t\t\t
    \n\t\t\t\t\t
    \n\t\t\t\t\t\t\n\t\t\t\t\t
    \n\t\t\t\t\t${r}\n\t\t\t\t\t${l}\n\t\t\t\t\t\n\t\t\t\t
    \n\t\t\t
    \n\t\t\t\n\t\t\t\n\t\t
    `,h=Pe.utils.createElement("DIV",{class:"se-modal-content"},a);return{html:h,alignForm:h.querySelector(".se-figure-align"),fileModalWrapper:h.querySelector(".se-flex-input-wrapper"),imgInputFile:h.querySelector(".__se__file_input"),imgUrlFile:h.querySelector(".se-input-url"),altText:h.querySelector("._se_image_alt"),captionCheckEl:h.querySelector("._se_image_check_caption"),previewSrc:h.querySelector("._se_tab_content_image .se-link-preview"),tabs:h.querySelector(".se-modal-tabs"),galleryButton:h.querySelector(".__se__gallery"),proportion:h.querySelector("._se_check_proportion"),inputX:h.querySelector("._se_size_x"),inputY:h.querySelector("._se_size_y"),revertBtn:h.querySelector(".se-modal-btn-revert"),asBlock:h.querySelector('[data-command="asBlock"]'),asInline:h.querySelector('[data-command="asInline"]'),fileRemoveBtn:h.querySelector(".se-file-remove")}}(this.$,this.pluginOptions),n=this.pluginOptions.useFormatType?"as":"",o=e.controls||(this.pluginOptions.canResize?[[n,"resize_auto,100,75,50","rotate_l","rotate_r","mirror_h","mirror_v"],["edit","align","caption","revert","copy","remove"]]:[[n,"mirror_h","mirror_v","align","caption","edit","revert","copy","remove"]]);this.alignForm=i.alignForm,o.some((t=>t.includes("align")))||(this.alignForm.style.display="none");const r=this.$.plugins.link?this.$.plugins.link.pluginOptions:{};this.anchor=new Vl(this.$,i.html,{...r,textToDisplay:!1,title:!0}),this.modal=new Fl(this,this.$,i.html),this.figure=new ji(this,this.$,o,{sizeUnit:s}),this.fileManager=new ql(this,this.$,{query:"img",loadEventName:"onImageLoad",actionEventName:"onImageAction"}),this.state={sizeUnit:s,onlyPercentage:this.pluginOptions.percentageOnlySize,produceIndex:0},this.fileModalWrapper=i.fileModalWrapper,this.imgInputFile=i.imgInputFile,this.imgUrlFile=i.imgUrlFile,this.focusElement=this.imgInputFile||this.imgUrlFile,this.altText=i.altText,this.captionCheckEl=i.captionCheckEl,this.captionEl=this.captionCheckEl?.parentElement,this.previewSrc=i.previewSrc,this.as=Rh.BLOCK,this.#ud=this.pluginOptions.canResize,this.#wu=!this.#ud||!this.pluginOptions.showHeightInput||this.pluginOptions.percentageOnlySize,this.sizeService=new Ph(this,i),this.uploadService=new Fh(this),this.$.eventManager.addEvent(i.tabs,"click",this.#Tu.bind(this)),this.imgInputFile&&this.$.eventManager.addEvent(i.fileRemoveBtn,"click",this.#Mu.bind(this)),this.imgUrlFile&&this.$.eventManager.addEvent(this.imgUrlFile,"input",this.#Nu.bind(this)),this.imgInputFile&&this.imgUrlFile&&this.$.eventManager.addEvent(this.imgInputFile,"change",this.#Bu.bind(this));const l=i.galleryButton;l&&this.$.eventManager.addEvent(l,"click",this.#Iu.bind(this)),this.pluginOptions.useFormatType&&(this.as=this.pluginOptions.defaultFormatType,this.asBlock=i.asBlock,this.asInline=i.asInline,this.$.eventManager.addEvent([this.asBlock,this.asInline],"click",this.#Lu.bind(this)))}setState(t,e){this.state[t]=e}open(){this.state.produceIndex=0,this.modal.open()}retainFormat(){return{query:"img",method:t=>{const e=ji.GetContainer(t);if(e&&e.container&&(e.cover||e.inlineCover))return;const{w:s,h:i}=this.#Au(t,!0);this.#Ou(s,i)}}}onFilePasteAndDrop({file:t}){/^image/.test(t.type)&&(this.submitFile([t]),this.$.focusManager.focus())}modalOn(t){t?this.imgInputFile&&this.pluginOptions.allowMultiple&&this.imgInputFile.removeAttribute("multiple"):(this.sizeService.on(),this.imgInputFile&&this.pluginOptions.allowMultiple&&this.imgInputFile.setAttribute("multiple","multiple")),this.anchor.on(t)}async modalAction(){return this.#ku=this.modal.form.querySelector('input[name="suneditor_image_radio"]:checked').value,this.modal.isUpdate&&(this.#Ru(),this.$.history.push(!1)),this.imgInputFile&&this.imgInputFile.files.length>0?await this.submitFile(this.imgInputFile.files):!!(this.imgUrlFile&&this.#_u.length>0)&&await this.submitURL(this.#_u)}modalInit(){Fl.OnChangeFile(this.fileModalWrapper,[]),this.imgInputFile&&(this.imgInputFile.value=""),this.imgUrlFile&&(this.#_u=this.previewSrc.textContent=this.imgUrlFile.value=""),this.imgInputFile&&this.imgUrlFile&&(this.imgUrlFile.disabled=!1,this.previewSrc.style.textDecoration=""),this.altText.value="",this.modal.form.querySelector('input[name="suneditor_image_radio"][value="none"]').checked=!0,this.captionCheckEl.checked=!1,this.#Pc=null,this.#Tu("init"),this.sizeService.init(),this.pluginOptions.useFormatType&&this.#zu((this.pluginOptions.keepFormatType?this.as:this.pluginOptions.defaultFormatType)===Rh.INLINE),this.anchor.init()}componentSelect(t){this.#Au(t)}componentEdit(){this.modal.open()}async componentDestroy(t){const e=t||this.#Pc,s=Pe.query.getParentElement(e,ji.is)||e,i=s.previousElementSibling||s.nextElementSibling,n=s.parentNode;!1!==await this.$.eventManager.triggerEvent("onImageDeleteBefore",{element:e,container:s,align:this.#ku,alt:this.altText.value,url:this.#_u})&&(Pe.utils.removeItem(s),this.modalInit(),n!==this.$.frameContext.get("wysiwyg")&&this.$.nodeTransform.removeAllParents(n,(function(t){return 0===t.childNodes.length}),null),this.$.focusManager.focusEdge(i),this.$.history.push(!1))}async submitFile(t){if(0===t.length)return!1;let e=0;const s=[],i=this.pluginOptions.uploadSingleSizeLimit;for(let n,o,r=0,l=t.length;r0&&o>i){const t="[SUNEDITOR.imageUpload.fail] Size of uploadable single file: "+i/1e3+"KB",e=await this.$.eventManager.triggerEvent("onImageUploadError",{error:t,limitSize:i,uploadSize:o,file:n});return this.$.ui.alertOpen(e===Hh?t:e||t,"error"),!1}s.push(n),e+=o}const n=this.pluginOptions.uploadSizeLimit,o=this.fileManager.getSize();if(n>0&&e+o>n){const t="[SUNEDITOR.imageUpload.fail] Size of uploadable total images: "+n/1e3+"KB",s=await this.$.eventManager.triggerEvent("onImageUploadError",{error:t,limitSize:n,currentSize:o,uploadSize:e});return this.$.ui.alertOpen(s===Hh?t:s||t,"error"),!1}const r={files:s,...this.#Pu()},l=function(t,e,s){t(e=s||e)}.bind(this,this.uploadService.serverUpload.bind(this.uploadService),r),a=await this.$.eventManager.triggerEvent("onImageUploadBefore",{info:r,handler:l});return void 0===a||!1!==a&&(null!==a&&"object"==typeof a&&l(a),void(!0!==a&&a!==Hh||l(null)))}async submitURL(t){if(!(t||=this.#_u))return!1;const e={name:t.split("/").pop(),size:0},s={url:t,files:e,...this.#Pu()},i=function(t,e,s){t(e=s||e)}.bind(this,this.uploadService.urlUpload.bind(this.uploadService),s),n=await this.$.eventManager.triggerEvent("onImageUploadBefore",{info:s,handler:i});return void 0===n||!1!==n&&(null!==n&&"object"==typeof n&&i(n),!0!==n&&n!==Hh||i(null),!0)}create(t,e,s,i,n,o,r,l){const a=Pe.utils.createElement("IMG");a.src=t,a.alt=r,e=this.#Du(a,e?e.cloneNode(!1):null);const h=ji.CreateContainer(e,"se-image-container"),c=h.cover,d=h.container;this.captionCheckEl.checked&&(this.#Eu=ji.CreateCaption(c,this.$.lang.caption)),this.#Pc=a,this.#$u=c,this.#Su=d,this.figure.open(a,{nonResizing:this.#wu,nonSizeInfo:!1,nonBorder:!1,figureTarget:!1,infoOnly:!0}),this.sizeService.applySize(s,i),this.figure.setAlign(a,n),this.fileManager.setFileData(a,o),this.setState("produceIndex",this.state.produceIndex+1),a.onload=this.#Fu.bind(this,a,this.#xu,d),this.$.component.insert(d,{scrollTo:!!l,insertBehavior:l?null:"line"})}createInline(t,e,s,i,n,o,r){const l=Pe.utils.createElement("IMG");l.src=t,l.alt=o,e=this.#Du(l,e?e.cloneNode(!1):null);const a=ji.CreateInlineContainer(e,"se-image-container").container;this.#Pc=l,this.#Su=a,this.figure.open(l,{nonResizing:this.#wu,nonSizeInfo:!1,nonBorder:!1,figureTarget:!1,infoOnly:!0}),this.sizeService.applySize(s,i),this.fileManager.setFileData(l,n),this.setState("produceIndex",this.state.produceIndex+1),l.onload=this.#Fu.bind(this,l,this.#xu,a),this.$.component.insert(a,{scrollTo:!!r,insertBehavior:r?null:"line"})}#Au(t,e=!1){if(!t)return;const s=this.figure.open(t,{nonResizing:this.#wu,nonSizeInfo:!1,nonBorder:!1,figureTarget:!1,infoOnly:e});this.anchor.set(Pe.check.isAnchor(t.parentNode)?t.parentNode:null),this.#Cu=this.anchor.currentTarget,this.#Pc=t,this.#$u=s.cover,this.#Su=s.container,this.#Eu=s.caption,this.#ku=s.align,t.style.float="",this.sizeService.setOriginSize(String(s.originWidth||s.w||""),String(s.originHeight||s.h||"")),this.altText.value=this.#Pc.alt,this.imgUrlFile&&(this.#_u=this.previewSrc.textContent=this.imgUrlFile.value=this.#Pc.src);(this.modal.form.querySelector('input[name="suneditor_image_radio"][value="'+this.#ku+'"]')||this.modal.form.querySelector('input[name="suneditor_image_radio"][value="none"]')).checked=!0,this.captionCheckEl.checked=!!this.#Eu;const{dw:i,dh:n}=this.figure.getSize(t);return this.#ud?(this.sizeService.ready(s,i,n),this.pluginOptions.useFormatType&&this.#zu(this.$.component.isInline(s.container)),{w:i,h:n}):{w:i,h:n}}#Pu(){const{w:t,h:e}=this.sizeService.getInputSize();return{element:this.#Pc,anchor:this.anchor.create(!0),inputWidth:t,inputHeight:e,align:this.#ku,isUpdate:this.modal.isUpdate,alt:this.altText.value}}#zu(t){t?(Pe.utils.addClass(this.asInline,"on"),Pe.utils.removeClass(this.asBlock,"on"),this.as=Rh.INLINE,this.alignForm&&(this.alignForm.style.display="none"),this.captionEl&&(this.captionEl.style.display="none")):(Pe.utils.addClass(this.asBlock,"on"),Pe.utils.removeClass(this.asInline,"on"),this.as=Rh.BLOCK,this.alignForm&&(this.alignForm.style.display=""),this.captionEl&&(this.captionEl.style.display=""))}#Ru(){const{w:t,h:e}=this.sizeService.getInputSize(),s=t||"auto",i=e||"auto";let n=this.#Pc;(this.as===Rh.BLOCK&&!this.#$u||this.as===Rh.INLINE&&this.#$u)&&(n=this.figure.convertAsFormat(n,this.as));const o=this.#$u,r=this.#Su===this.#$u?null:this.#Su;let l;const a=De.is(s)?s+this.state.sizeUnit:s,h=De.is(i)?i+this.state.sizeUnit:i;l=/%$/.test(n.style.width)?a!==r.style.width||h!==r.style.height:a!==n.style.width||h!==n.style.height,n.alt=this.altText.value;let c=!1;this.captionCheckEl.checked?this.#Eu||(this.#Eu=ji.CreateCaption(o,this.$.lang.caption),c=!0):this.#Eu&&(Pe.utils.removeItem(this.#Eu),this.#Eu=null,c=!0);let d=!1;const u=this.anchor.create(!0);if(u)this.#Cu===u&&r.contains(u)||(this.#Cu=u.cloneNode(!1),o.insertBefore(this.#Du(n,this.#Cu),this.#Eu),d=!0);else if(null!==this.#Cu&&o.contains(this.#Cu)){const t=n.cloneNode(!0);o.removeChild(this.#Cu),o.insertBefore(t,this.#Eu),n=t}d&&Pe.utils.removeItem(u),this.#ud&&l&&this.sizeService.applySize(s,i),(c||!this.state.onlyPercentage&&l)&&(/\d+/.test(n.style.height)||this.figure.isVertical&&this.captionCheckEl.checked)&&(/auto|%$/.test(s)||/auto|%$/.test(i)?this.figure.deleteTransform(n):this.#ud&&l&&this.figure.isVertical||this.figure.setTransform(n,s,i,0)),this.figure.setAlign(n,this.#ku),n.onload=()=>{this.componentSelect(n)}}#Ou(t,e){const{w:s,h:i}=this.sizeService.getInputSize();t||=s||"auto",e||=i||"auto";let n=this.#Pc,o=this.#$u,r=null,l=this.#Su===this.#$u?null:this.#Su,a=!1;if(!o||!l){a=!0,n=this.#Pc.cloneNode(!0);const e=this.pluginOptions.useFormatType&&"auto"!==t&&(/^span$/i.test(this.#Pc.parentElement?.nodeName)||this.$.format.isLine(this.#Pc.parentElement))?ji.CreateInlineContainer(n,"se-image-container"):ji.CreateContainer(n,"se-image-container");o=e.cover,l=e.container,r=e.inlineCover,this.figure.open(n,{nonResizing:!0,nonSizeInfo:!1,nonBorder:!1,figureTarget:!1,infoOnly:!0})}n.alt=this.altText.value;let h=!1;r||(this.captionCheckEl.checked?this.#Eu&&!a||(this.#Eu=ji.CreateCaption(o,this.$.lang.caption),h=!0):this.#Eu&&(Pe.utils.removeItem(this.#Eu),this.#Eu=null,h=!0));let c=null;const d=this.anchor.create(!0,Pe.check.isAnchor(this.#Pc.parentElement)?this.#Pc.parentElement.href:null);if(d)(this.#Cu!==d||a&&!l.contains(d))&&(this.#Cu=d.cloneNode(!1),o.insertBefore(this.#Du(n,this.#Cu),this.#Eu),c=this.#Pc);else if(null!==this.#Cu&&o.contains(this.#Cu)){const t=n.cloneNode(!0);o.removeChild(this.#Cu),o.insertBefore(t,this.#Eu),n=t}a&&(n=this.#Pc,this.figure.retainFigureFormat(l,this.#Pc,c?d:null,this.fileManager),this.#Pc=n=l.querySelector("img"),this.#$u=o,this.#Su=l),n.style.width="",n.style.height="",n.removeAttribute("width"),n.removeAttribute("height"),this.sizeService.applySize(t,e),c&&(a?(Pe.utils.removeItem(c),0===Pe.query.getListChildren(d,(t=>/IMG/i.test(t.tagName)),null).length&&Pe.utils.removeItem(d)):Pe.utils.removeItem(d)),!h&&this.state.onlyPercentage||(/\d+/.test(n.style.height)||this.figure.isVertical&&this.captionCheckEl.checked)&&(/auto|%$/.test(t)||/auto|%$/.test(e)?this.figure.deleteTransform(n):this.figure.setTransform(n,t,e,0)),this.figure.setAlign(n,this.#ku)}#Du(t,e){return e?(e.setAttribute("data-se-non-link","true"),e.appendChild(t),e):t}#Tu(t){const e=this.modal.form,s="string"==typeof t?e.querySelector("._se_tab_link"):Pe.query.getEventTarget(t);if(!/^BUTTON$/i.test(s.tagName))return!1;const i=s.getAttribute("data-tab-link");let n;const o=e.getElementsByClassName("_se_tab_content");for(n=0;n100?"100":this.#ou:(this.#hu.value=this.#ou,this.#cu.value=this.#ru)}#Gu(t){if(!this.frameRatioOption)return;let e=!1;const s=this.frameRatioOption.options;/%$/.test(t+"")||this.#I.onlyPercentage?t=De.get(t,2)/100+"":(!De.is(t)||Number(t)>=1)&&(t=""),this.#cu.placeholder="";for(let i=0,n=s.length;i100)s.value="100";else if(this.#au.checked&&!this.frameRatioOption?.value){const e=ji.CalcRatio(this.#hu.value,this.#cu.value,this.#I.sizeUnit,this.#lu);"x"===t?this.#cu.value=String(e.h):this.#hu.value=String(e.w)}"y"===t&&this.#Gu(s.value||this.#I.defaultRatio)}},{NO_EVENT:Uh}=Oe;const Vh=class{#rd;#J;#nu;constructor(t){this.#rd=t,this.#J=t.$,this.#nu=t.pluginOptions}serverUpload(t,e){if(!e)return;const s=this.#nu.uploadUrl;"string"==typeof s&&s.length>0&&this.#rd.fileManager.upload(s,this.#nu.uploadHeaders,e,this.#mu.bind(this,t),this.#gc.bind(this))}#pc(t,e){const s=e.result,i=this.#rd.createVideoTag();for(let e=0,n=s.length;et.endsWith(e)))&&!this.#Xu.some((e=>e.test(t))))}static#Yu=[".mp4",".avi",".mov",".webm",".flv",".mkv",".m4v",".ogv"];static#Xu=[/youtu\.?be/,/vimeo\.com\//,/dailymotion\.com\/video\//,/facebook\.com\/.+\/videos\//,/facebook\.com\/watch\/\?v=/,/twitter\.com\/.+\/status\//,/twitch\.tv\/videos\//,/twitch\.tv\/[^/]+$/,/tiktok\.com\/@[^/]+\/video\//,/instagram\.com\/p\//,/instagram\.com\/tv\//,/instagram\.com\/reel\//,/linkedin\.com\/posts\//,/\.(wistia\.com|wi\.st)\/(medias|embed)\//,/loom\.com\/share\//];#ud;#wu;#_u="";#ku="none";#Pc=null;#Su=null;constructor(t,e){super(t),this.title=this.$.lang.video,this.icon="video",this.pluginOptions={canResize:void 0===e.canResize||e.canResize,showHeightInput:void 0===e.showHeightInput||!!e.showHeightInput,defaultWidth:e.defaultWidth&&De.get(e.defaultWidth,0)?De.is(e.defaultWidth)?e.defaultWidth+"px":e.defaultWidth:"",defaultHeight:e.defaultHeight&&De.get(e.defaultHeight,0)?De.is(e.defaultHeight)?e.defaultHeight+"px":e.defaultHeight:"",percentageOnlySize:!!e.percentageOnlySize,createFileInput:!!e.createFileInput,createUrlInput:void 0===e.createUrlInput||!e.createFileInput||e.createUrlInput,uploadUrl:"string"==typeof e.uploadUrl?e.uploadUrl:null,uploadHeaders:e.uploadHeaders||null,uploadSizeLimit:De.get(e.uploadSizeLimit,0),uploadSingleSizeLimit:De.get(e.uploadSingleSizeLimit,0),allowMultiple:!!e.allowMultiple,acceptedFormats:"string"!=typeof e.acceptedFormats||"*"===e.acceptedFormats.trim()?"video/*":e.acceptedFormats.trim()||"video/*",defaultRatio:De.get(e.defaultRatio,4)||.5625,showRatioOption:void 0===e.showRatioOption||!!e.showRatioOption,ratioOptions:e.ratioOptions?e.ratioOptions:null,videoTagAttributes:e.videoTagAttributes||null,iframeTagAttributes:e.iframeTagAttributes||null,query_youtube:e.query_youtube||"",query_vimeo:e.query_vimeo||"",insertBehavior:e.insertBehavior};const s=this.pluginOptions.percentageOnlySize?"%":"px",i=function({lang:t,icons:e,plugins:s},i){let n=`\n\t
    \n\t\t
    \n\t\t\t\n\t\t\t${t.video_modal_title}\n\t\t
    \n\t\t
    `;if(i.createFileInput&&(n+=`\n\t\t\t
    \n\t\t\t\t\n\t\t\t\t${Fl.CreateFileInput({lang:t,icons:e},i)}\n\t\t\t
    `),i.createUrlInput&&(n+=`\n\t\t\t
    \n\t\t\t\t\n\t\t\t\t
    \n\t\t\t\t\t\n\t\t\t\t\t${s.videoGallery?``:""}\n\t\t\t\t
    \n\t\t\t\t\n\t\t\t
    `),i.canResize){const s=i.ratioOptions||[{name:"16:9",value:.5625},{name:"4:3",value:.75},{name:"21:9",value:.4285},{name:"9:16",value:1.78}],o=i.defaultRatio,r=i.percentageOnlySize,l=r?' style="display: none !important;"':"",a=i.showHeightInput?"":' style="display: none !important;"',h=i.showRatioOption?"":' style="display: none !important;"',c=r||i.showHeightInput||i.showRatioOption?"":' style="display: none !important;"';n+=`\n\t\t\t
    \n\t\t\t\t
    \n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t
    \n\t\t\t\t\n\t\t\t\t\n\t\t\t\t\n\t\t\t\t\n\t\t\t\t\n\t\t\t
    \n\t\t\t`}n+=`\n\t\t
    \n\t\t\n\t
    `;const o=Pe.utils.createElement("DIV",{class:"se-modal-content"},n);return{html:o,alignForm:o.querySelector(".se-figure-align"),fileModalWrapper:o.querySelector(".se-flex-input-wrapper"),videoInputFile:o.querySelector(".__se__file_input"),videoUrlFile:o.querySelector(".se-input-url"),previewSrc:o.querySelector(".se-link-preview"),galleryButton:o.querySelector(".__se__gallery"),proportion:o.querySelector("._se_check_proportion"),frameRatioOption:o.querySelector(".se-modal-ratio"),inputX:o.querySelector("._se_size_x"),inputY:o.querySelector("._se_size_y"),revertBtn:o.querySelector(".se-modal-btn-revert"),fileRemoveBtn:o.querySelector(".se-file-remove")}}(this.$,this.pluginOptions),n=e.controls||(this.pluginOptions.canResize?[["resize_auto,75,50","align","edit","revert","copy","remove"]]:[["align","edit","copy","remove"]]);n.some((t=>t.includes("align")))||(i.alignForm.style.display="none");const o=100*this.pluginOptions.defaultRatio+"%";this.modal=new Fl(this,this.$,i.html),this.figure=new ji(this,this.$,n,{sizeUnit:s,autoRatio:{current:o,default:o}}),this.fileManager=new ql(this,this.$,{query:"iframe, video",loadEventName:"onVideoLoad",actionEventName:"onVideoAction"}),this.fileModalWrapper=i.fileModalWrapper,this.videoInputFile=i.videoInputFile,this.videoUrlFile=i.videoUrlFile,this.focusElement=this.videoUrlFile||this.videoInputFile,this.previewSrc=i.previewSrc,this.#ud=this.pluginOptions.canResize,this.#wu=!this.#ud||!this.pluginOptions.showHeightInput||this.pluginOptions.percentageOnlySize,this.query={youtube:{pattern:/youtu\.?be/i,action:t=>(t=this.convertUrlYoutube(t),ze.addUrlQuery(t,this.pluginOptions.query_youtube)),tag:"iframe"},vimeo:{pattern:/vimeo\.com/i,action:t=>(t=this.convertUrlVimeo(t),ze.addUrlQuery(t,this.pluginOptions.query_vimeo)),tag:"iframe"},...e.embedQuery};const r=[];for(const t in this.query)r.push(this.query[t].pattern);Kh.#Yu=Kh.#Yu.concat(this.pluginOptions.extensions||[]),Kh.#Xu=Kh.#Xu.concat(e.urlPatterns||[]),this.state={onlyPercentage:this.pluginOptions.percentageOnlySize,sizeUnit:s,defaultRatio:100*this.pluginOptions.defaultRatio+"%"},this.sizeService=new Wh(this,i),this.uploadService=new Vh(this);const l=i.galleryButton;l&&this.$.eventManager.addEvent(l,"click",this.#Iu.bind(this)),this.videoInputFile&&this.$.eventManager.addEvent(i.fileRemoveBtn,"click",this.#Mu.bind(this)),this.videoUrlFile&&this.$.eventManager.addEvent(this.videoUrlFile,"input",this.#Nu.bind(this)),this.videoInputFile&&this.videoUrlFile&&this.$.eventManager.addEvent(this.videoInputFile,"change",this.#Bu.bind(this))}setState(t,e){this.state[t]=e}open(){this.modal.open()}retainFormat(){return{query:"iframe, video",method:async t=>{if(/^(iframe)$/i.test(t?.nodeName)&&!Kh.#Ku(t.src))return;const e=ji.GetContainer(t);if(e&&e.container&&e.cover)return;this.#Au(t,!0);const s=this.$.format.getLine(t);s&&(this.#ku=s.style.textAlign||s.style.float),this.#Ru(t)}}}onFilePasteAndDrop({file:t}){/^video/.test(t.type)&&(this.submitFile([t]),this.$.focusManager.focus())}modalOn(t){t?this.videoInputFile&&this.pluginOptions.allowMultiple&&this.videoInputFile.removeAttribute("multiple"):this.videoInputFile&&this.pluginOptions.allowMultiple&&this.videoInputFile.setAttribute("multiple","multiple"),this.sizeService.on(t)}async modalAction(){this.#ku=this.modal.form.querySelector('input[name="suneditor_video_radio"]:checked').value;let t=!1;return this.videoInputFile&&this.videoInputFile.files.length>0?t=await this.submitFile(this.videoInputFile.files):this.videoUrlFile&&this.#_u.length>0&&(t=await this.submitURL(this.#_u)),t&&jh.setTimeout(this.$.component.select.bind(this.$.component,this.#Pc,Kh.key),0),t}modalInit(){Fl.OnChangeFile(this.fileModalWrapper,[]),this.videoInputFile&&(this.videoInputFile.value=""),this.videoUrlFile&&(this.#_u=this.previewSrc.textContent=this.videoUrlFile.value=""),this.videoInputFile&&this.videoUrlFile&&(this.videoUrlFile.disabled=!1,this.previewSrc.style.textDecoration=""),this.modal.form.querySelector('input[name="suneditor_video_radio"][value="none"]').checked=!0,this.#wu=!1,this.sizeService.init()}componentSelect(t){this.#Au(t)}componentEdit(){this.modal.open()}async componentDestroy(t){const e=t||this.#Pc,s=Pe.query.getParentElement(e,ji.is)||e,i=s.previousElementSibling||s.nextElementSibling,n=s.parentNode;!1!==await this.$.eventManager.triggerEvent("onVideoDeleteBefore",{element:e,container:s,align:this.#ku,url:this.#_u})&&(Pe.utils.removeItem(s),this.modalInit(),n!==this.$.frameContext.get("wysiwyg")&&this.$.nodeTransform.removeAllParents(n,(function(t){return 0===t.childNodes.length}),null),this.$.focusManager.focusEdge(i),this.$.history.push(!1))}findProcessUrl(t){const e=this.query;for(const s in e){const i=e[s];if(i.pattern.test(t))return{origin:t,url:i.action(t),tag:i.tag}}return null}convertUrlYoutube(t){return/^http/.test(t)||(t="https://"+t),t=t.replace("watch?v=",""),/^\/\/.+\/embed\//.test(t)||(t=t.replace(t.match(/\/\/.+\//)[0],"//www.youtube.com/embed/").replace("&","?&")),t}convertUrlVimeo(t){return t.endsWith("/")&&(t=t.slice(0,-1)),t="https://player.vimeo.com/video/"+t.slice(t.lastIndexOf("/")+1)}addQuery(t,e){if(e.length>0)if(/\?/.test(t)){const s=t.split("?");t=s[0]+"?"+e+"&"+s[1]}else t+="?"+e;return t}create(t,e,s,i,n,o,r,l){let a=null;if(o){if((t=this.#Pc).src!==e){const s=this.findProcessUrl(e);if(/^iframe$/i.test(s?.tag)&&!/^iframe$/i.test(t.nodeName)){const s=this.createIframeTag();s.src=e,t.replaceWith(s),this.#Pc=t=s}else if(/^video$/i.test(s?.tag)&&!/^video$/i.test(t.nodeName)){const s=this.createVideoTag();s.src=e,t.replaceWith(s),this.#Pc=t=s}else t.src=e}a=this.#Su}else{t.src=e,this.#Pc=t;a=ji.CreateContainer(t,"se-video-container").container}this.#Pc=t,this.#Su=a,this.figure.open(t,{nonResizing:this.#wu,nonSizeInfo:!1,nonBorder:!1,figureTarget:!1,infoOnly:!0});const h=this.sizeService.resolveSize(s,i,t,o);s=h.width,i=h.height,this.figure.setAlign(t,n),this.fileManager.setFileData(t,r),o?(this.#ud&&h.isChanged&&this.figure.isVertical||this.figure.setTransform(t,s,i,0),this.$.history.push(!1)):this.$.component.insert(a,{scrollTo:!!l,insertBehavior:l?this.pluginOptions.insertBehavior:"line"})}createIframeTag(t){const e=Pe.utils.createElement("IFRAME");if(t)for(const s in t)e[s]=t[s];return this.#Zu(e),e}createVideoTag(t){const e=Pe.utils.createElement("VIDEO");if(t)for(const s in t)e[s]=t[s];return this.#Ju(e),e}async submitFile(t){if(0===t.length)return;let e=0;const s=[],i=this.pluginOptions.uploadSingleSizeLimit;for(let n,o,r=0,l=t.length;r0&&o>i){const t="[SUNEDITOR.videoUpload.fail] Size of uploadable single file: "+i/1e3+"KB",e=await this.$.eventManager.triggerEvent("onVideoUploadError",{error:t,limitSize:i,uploadSize:o,file:n});return this.$.ui.alertOpen(e===Gh?t:e||t,"error"),!1}s.push(n),e+=o}const n=this.pluginOptions.uploadSizeLimit,o=this.fileManager.getSize();if(n>0&&e+o>n){const t="[SUNEDITOR.videoUpload.fail] Size of uploadable total videos: "+n/1e3+"KB",s=await this.$.eventManager.triggerEvent("onVideoUploadError",{error:t,limitSize:n,currentSize:o,uploadSize:e});return this.$.ui.alertOpen(s===Gh?t:s||t,"error"),!1}const r={url:null,files:s,...this.#Pu()},l=function(t,e,s){t(e=s||e,e.files)}.bind(this,this.uploadService.serverUpload.bind(this.uploadService),r),a=await this.$.eventManager.triggerEvent("onVideoUploadBefore",{info:r,handler:l});return void 0===a||!1!==a&&(null!==a&&"object"==typeof a&&l(a),void(!0!==a&&a!==Gh||l(null)))}async submitURL(t){if(!(t=this.#_u))return!1;if(/^$/.test(t)){if(0===(t=(new DOMParser).parseFromString(t,"text/html").querySelector("iframe").src).length)return!1}const e=this.findProcessUrl(t);e&&(t=e.url);const s={name:t.split("/").pop(),size:0},i={url:t,files:s,...this.#Pu(),process:e},n=function(t,e){t=e||t,this.create(this[/^iframe$/i.test(t.process?.tag)?"createIframeTag":"createVideoTag"](),t.url,t.inputWidth,t.inputHeight,t.align,t.isUpdate,t.files,!0)}.bind(this,i),o=await this.$.eventManager.triggerEvent("onVideoUploadBefore",{info:i,handler:n});return void 0===o||!1!==o&&(null!==o&&"object"==typeof o&&n(o),!0!==o&&o!==Gh||n(null),!0)}#Au(t,e=!1){if(!t)return;const s=this.figure.open(t,{nonResizing:this.#wu,nonSizeInfo:!1,nonBorder:!1,figureTarget:!1,infoOnly:e});this.#Pc=t,this.#Su=s.container,this.#ku=s.align,t.style.float="";const i=String(s.width||s.originWidth||s.w||""),n=String(s.height||s.originHeight||s.h||"");this.sizeService.setOriginSize(i,n),this.videoUrlFile&&(this.#_u=this.previewSrc.textContent=this.videoUrlFile.value=this.#Pc.src||this.#Pc.querySelector("source")?.src||"");(this.modal.form.querySelector('input[name="suneditor_video_radio"][value="'+this.#ku+'"]')||this.modal.form.querySelector('input[name="suneditor_video_radio"][value="none"]')).checked=!0,this.#ud&&this.sizeService.ready(s,t)}#Pu(){const{w:t,h:e}=this.sizeService.getInputSize();return{inputWidth:t,inputHeight:e,align:this.#ku,isUpdate:this.modal.isUpdate,element:this.#Pc}}#Ru(t){if(!t)return;/^video$/i.test(t.nodeName)?this.#Ju(t):/^iframe$/i.test(t.nodeName)&&this.#Zu(t);const e=t,s=t.cloneNode(!0),i=ji.CreateContainer(s,"se-video-container"),n=i.container,o=ji.GetContainer(e)?.container?.querySelector("figcaption");let r=null;o&&(r=Pe.utils.createElement("figcaption"),r.innerHTML=o.innerHTML,Pe.utils.removeItem(o),i.cover.appendChild(r)),this.figure.open(s,{nonResizing:this.#wu,nonSizeInfo:!1,nonBorder:!1,figureTarget:!1,infoOnly:!0});const l=(s.getAttribute("data-se-size")||",").split(","),a=l[0]||e.width||"",h=l[1]||e.height||this.state.defaultRatio||"";this.sizeService.applySize(a,h);const c=this.$.format.getLine(e);return c&&(this.#ku=c.style.textAlign||c.style.float),this.figure.setAlign(s,this.#ku),this.figure.retainFigureFormat(n,this.#Pc,null,this.fileManager),s}#Ju(t){t.setAttribute("controls","true");const e=this.pluginOptions.videoTagAttributes;if(e)for(const s in e)t.setAttribute(s,e[s])}#Zu(t){t.frameBorder="0",t.allowFullscreen=!0;const e=this.pluginOptions.iframeTagAttributes;if(e)for(const s in e)t.setAttribute(s,e[s])}#Mu(){this.videoInputFile.value="",this.videoUrlFile&&(this.videoUrlFile.disabled=!1,this.previewSrc.style.textDecoration=""),Fl.OnChangeFile(this.fileModalWrapper,[])}#Nu(t){const e=Pe.query.getEventTarget(t).value.trim();/^$/.test(e)?(this.#_u=e,this.previewSrc.textContent=''):this.#_u=this.previewSrc.textContent=e?this.$.options.get("defaultUrlProtocol")&&!e.includes("://")&&0!==e.indexOf("#")?this.$.options.get("defaultUrlProtocol")+e:e.includes("://")?e:"/"+e:""}#Iu(){this.$.plugins.videoGallery.open(this.#Hu.bind(this))}#Hu(t){this.#_u=this.previewSrc.textContent=this.videoUrlFile.value=t.getAttribute("data-command")||t.src,this.videoUrlFile.focus()}#Bu(t){this.videoInputFile.value?(this.videoUrlFile.disabled=!0,this.previewSrc.style.textDecoration="line-through"):(this.videoUrlFile.disabled=!1,this.previewSrc.style.textDecoration="");const e=Pe.query.getEventTarget(t);Fl.OnChangeFile(this.fileModalWrapper,e.files)}}const Yh=Kh,{NO_EVENT:Xh,ON_OVER_COMPONENT:Zh}=Oe;class Jh extends ta{static key="audio";static className="";static component(t){return/^AUDIO$/i.test(t?.nodeName)?t:null}#Qu;#tp;#ep="";#Pc=null;constructor(t,e){super(t),this.title=this.$.lang.audio,this.icon="audio",this.pluginOptions={defaultWidth:e.defaultWidth?De.is(e.defaultWidth)?e.defaultWidth+"px":e.defaultWidth:"",defaultHeight:e.defaultHeight?De.is(e.defaultHeight)?e.defaultHeight+"px":e.defaultHeight:"",createFileInput:!!e.createFileInput,createUrlInput:void 0===e.createUrlInput||!e.createFileInput||e.createUrlInput,uploadUrl:"string"==typeof e.uploadUrl?e.uploadUrl:null,uploadHeaders:e.uploadHeaders||null,uploadSizeLimit:De.get(e.uploadSizeLimit,0),uploadSingleSizeLimit:De.get(e.uploadSingleSizeLimit,0),allowMultiple:!!e.allowMultiple,acceptedFormats:"string"!=typeof e.acceptedFormats||"*"===e.acceptedFormats.trim()?"audio/*":e.acceptedFormats.trim()||"audio/*",audioTagAttributes:e.audioTagAttributes||null,insertBehavior:e.insertBehavior};const s=function({lang:t,icons:e,plugins:s},i){let n=`\n
    \n
    \n \n ${t.audio_modal_title}\n
    \n
    `;i.createFileInput&&(n+=`\n
    \n \n ${Fl.CreateFileInput({lang:t,icons:e},i)}\n
    `);i.createUrlInput&&(n+=`\n
    \n \n\t\t\t
    \n\t\t\t\t\n\t\t\t\t${s.audioGallery?``:""}\n\t\t\t
    \n \n
    `);return n+=`\n
    \n \n
    `,Pe.utils.createElement("DIV",{class:"se-modal-content"},n)}(this.$,this.pluginOptions),i=function({lang:t,icons:e}){const s=`\n
    \n `;return Pe.utils.createElement("DIV",{class:"se-controller"},s)}(this.$);this.modal=new Fl(this,this.$,s),this.controller=new Ii(this,this.$,i,{position:"bottom",disabled:!0}),this.fileManager=new ql(this,this.$,{query:"audio",loadEventName:"onAudioLoad",actionEventName:"onAudioAction"}),this.figure=new ji(this,this.$,null,{}),this.fileModalWrapper=s.querySelector(".se-flex-input-wrapper"),this.audioInputFile=s.querySelector(".__se__file_input"),this.audioUrlFile=s.querySelector(".se-input-url"),this.preview=s.querySelector(".se-link-preview"),this.#Qu=this.pluginOptions.defaultWidth,this.#tp=this.pluginOptions.defaultHeight;const n=s.querySelector(".__se__gallery");n&&this.$.eventManager.addEvent(n,"click",this.#Iu.bind(this)),this.audioInputFile&&(this.$.eventManager.addEvent(s.querySelector(".se-modal-files-edge-button"),"click",this.#Mu.bind(this,this.audioUrlFile,this.preview)),this.audioUrlFile&&this.$.eventManager.addEvent(this.audioInputFile,"change",this.#sp.bind(this))),this.audioUrlFile&&this.$.eventManager.addEvent(this.audioUrlFile,"input",this.#Nu.bind(this))}open(){this.modal.open()}retainFormat(){return{query:"audio",method:t=>{const e=ji.GetContainer(t);if(e&&e.container&&e.cover)return;this.#Ju(t);const s=ji.CreateContainer(t.cloneNode(!0),"se-flex-component");this.figure.retainFigureFormat(s.container,t,null,this.fileManager)}}}onFilePasteAndDrop({file:t}){/^audio/.test(t.type)&&(this.submitFile([t]),this.$.focusManager.focus())}modalOn(t){t?this.#Pc?(this.#ep=this.preview.textContent=this.audioUrlFile.value=this.#Pc.src,this.audioInputFile&&this.pluginOptions.allowMultiple&&this.audioInputFile.removeAttribute("multiple")):this.audioInputFile&&this.pluginOptions.allowMultiple&&this.audioInputFile.removeAttribute("multiple"):this.audioInputFile&&this.pluginOptions.allowMultiple&&this.audioInputFile.setAttribute("multiple","multiple")}async modalAction(){return this.audioInputFile&&this.audioInputFile?.files.length>0?await this.submitFile(this.audioInputFile.files):!!(this.audioUrlFile&&this.#ep.length>0)&&await this.submitURL(this.#ep)}modalInit(){Fl.OnChangeFile(this.fileModalWrapper,[]),this.audioInputFile&&(this.audioInputFile.value=""),this.audioUrlFile&&(this.#ep=this.preview.textContent=this.audioUrlFile.value=""),this.audioInputFile&&this.audioUrlFile&&(this.audioUrlFile.disabled=!1,this.preview.style.textDecoration="")}controllerAction(t){switch(t.getAttribute("data-command")){case"update":this.audioUrlFile&&(this.#ep=this.preview.textContent=this.audioUrlFile.value=this.#Pc.src),this.open();break;case"copy":{const t=ji.GetContainer(this.#Pc);this.$.component.copy(t.container);break}case"delete":this.componentDestroy(null)}}componentSelect(t){this.figure.open(t,{nonResizing:!0,nonSizeInfo:!0,nonBorder:!0,figureTarget:!0,infoOnly:!1}),this.#Au(t)}async componentDestroy(t){const e=t||this.#Pc,s=ji.GetContainer(e),i=s.container||e,n=i.previousElementSibling||i.nextElementSibling;if(!1===await this.$.eventManager.triggerEvent("onAudioDeleteBefore",{element:e,container:s,url:e.getAttribute("src")}))return;const o=i.parentNode;Pe.utils.removeItem(i),this.modalInit(),this.controller.close(),o!==this.$.frameContext.get("wysiwyg")&&this.$.nodeTransform.removeAllParents(o,(function(t){return 0===t.childNodes.length}),null),this.$.focusManager.focusEdge(n),this.$.history.push(!1)}async submitFile(t){if(0===t.length)return!1;let e=0;const s=[],i=this.pluginOptions.uploadSingleSizeLimit;for(let n,o,r=0,l=t.length;r0&&o>i){const t="[SUNEDITOR.audioUpload.fail] Size of uploadable single file: "+i/1e3+"KB",e=await this.$.eventManager.triggerEvent("onAudioUploadError",{error:t,limitSize:i,uploadSize:o,file:n});return this.$.ui.alertOpen(e===Xh?t:e||t,"error"),!1}s.push(n),e+=o}const n=this.pluginOptions.uploadSizeLimit;if(n>0&&e+this.fileManager.getSize()>n){const t="[SUNEDITOR.audioUpload.fail] Size of uploadable total audios: "+n/1e3+"KB",s=await this.$.eventManager.triggerEvent("onAudioUploadError",{error:t,limitSize:n,currentSize:this.fileManager.getSize(),uploadSize:e});return this.$.ui.alertOpen(s===Xh?t:s||t,"error"),!1}const o={files:s,isUpdate:this.modal.isUpdate,element:this.#Pc},r=function(t,e,s){t(s=e||s,s.files)}.bind(this,this.#ip.bind(this),o),l=await this.$.eventManager.triggerEvent("onAudioUploadBefore",{info:o,handler:r});return void 0===l||!!l&&(null!==l&&"object"==typeof l&&r(l),!0!==l&&l!==Xh||r(null),!0)}async submitURL(t){if(0===t.length)return!1;const e={name:t.split("/").pop(),size:0},s={url:t,files:e,isUpdate:this.modal.isUpdate,element:this.#np()},i=function(t,e,s){t((s=e||s).element,s.url,s.files,s.isUpdate,!0)}.bind(this,this.create.bind(this),s),n=await this.$.eventManager.triggerEvent("onAudioUploadBefore",{info:s,handler:i});return void 0===n||!!n&&(null!==n&&"object"==typeof n&&i(n),!0!==n&&n!==Xh||i(null),!0)}create(t,e,s,i,n){if(i){if(this.#Pc&&(t=this.#Pc),this.fileManager.setFileData(t,s),!t||t.src===e)return void this.$.component.select(t,Jh.key);t.src=e,this.$.component.select(t,Jh.key)}else{this.fileManager.setFileData(t,s),t.src=e;const i=ji.CreateContainer(t,"se-flex-component");if(!this.$.component.insert(i.container,{scrollTo:!!n,insertBehavior:n?this.pluginOptions.insertBehavior:"line"}))return void(n&&this.$.focusManager.focus());if(!this.$.options.get("componentInsertBehavior")){const t=this.$.format.addLine(i.container,null);t&&this.$.selection.setRange(t,0,t,0)}}i&&this.$.history.push(!1)}#Au(t){_i.get("__overInfo")!==Zh&&(this.#Pc=t,this.controller.open(t,null,{isWWTarget:!1,addOffset:null}))}#pc(t,e){const s=e.result;for(let e,i,n=0,o=s.length;nt.src||t.href)),s=i?.src||i?.href}if(/^BLOCKQUOTE$/i.test(t?.nodeName)){const e=t.querySelector("a");if(e&&e.href)return i=t,s=e.href,this.#Ku(s)?i:null}return s?this.#Ku(s)?i:null:i}static#Ku(t){return t=t?.toLowerCase()||"",!!this.#Xu.some((e=>e.test(t)))}static#op(t,e){return!!t&&e.some((e=>e instanceof RegExp?e.test(t):t.startsWith(e)))}static#Xu=null;#Wu;#Uu;#ou;#ru;#ud;#rp;#wu;#_u="";#ku="none";#Pc=null;#$u=null;#Su=null;#lu={w:0,h:0};constructor(t,e){super(t),this.title=this.$.lang.embed,this.icon="embed",this.pluginOptions={canResize:void 0===e.canResize||e.canResize,showHeightInput:void 0===e.showHeightInput||!!e.showHeightInput,defaultWidth:e.defaultWidth&&De.get(e.defaultWidth,0)?De.is(e.defaultWidth)?e.defaultWidth+"px":e.defaultWidth:"",defaultHeight:e.defaultHeight&&De.get(e.defaultHeight,0)?De.is(e.defaultHeight)?e.defaultHeight+"px":e.defaultHeight:"",percentageOnlySize:!!e.percentageOnlySize,uploadUrl:"string"==typeof e.uploadUrl?e.uploadUrl:null,uploadHeaders:e.uploadHeaders||null,uploadSizeLimit:De.get(e.uploadSizeLimit,0),uploadSingleSizeLimit:De.get(e.uploadSingleSizeLimit,0),iframeTagAttributes:e.iframeTagAttributes||null,query_youtube:e.query_youtube||"",query_vimeo:e.query_vimeo||"",scriptSrcWhitelist:Array.isArray(e.scriptSrcWhitelist)?e.scriptSrcWhitelist:[],insertBehavior:e.insertBehavior};const s=this.pluginOptions.percentageOnlySize?"%":"px",i=function({lang:t,icons:e},s){let i=`\n\t
    \n\t\t
    \n\t\t\t\n\t\t\t${t.embed_modal_title}\n\t\t
    \n\t\t
    \n\t\t\t
    \n\t\t\t\t\n\t\t\t\t\n\t\t\t\t\n\t\t\t
    `;if(s.canResize){const n=s.percentageOnlySize,o=n?' style="display: none !important;"':"",r=s.showHeightInput?"":' style="display: none !important;"',l=s.showRatioOption?"":' style="display: none !important;"',a=n||s.showHeightInput||s.showRatioOption?"":' style="display: none !important;"';i+=`\n\t\t\t
    \n\t\t\t\t
    \n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t
    \n\t\t\t\t\n\t\t\t\t\n\t\t\t\t\n\t\t\t\t\n\t\t\t
    \n\t\t\t`}i+=`\n\t\t
    \n\t\t\n\t
    `;const n=Pe.utils.createElement("DIV",{class:"se-modal-content"},i);return{html:n,figureAlignBtn:n.querySelector(".se-figure-align"),fileModalWrapper:n.querySelector(".se-flex-input-wrapper"),embedInput:n.querySelector(".se-input-url"),previewSrc:n.querySelector(".se-link-preview"),proportion:n.querySelector("._se_check_proportion"),inputX:n.querySelector("._se_size_x"),inputY:n.querySelector("._se_size_y"),revertBtn:n.querySelector(".se-modal-btn-revert")}}(this.$,this.pluginOptions),n=e.controls||(this.pluginOptions.canResize?[["resize_auto,75,50","align","edit","revert","copy","remove"]]:[["align","edit","copy","remove"]]);n.some((t=>t.includes("align")))||(i.figureAlignBtn.style.display="none"),this.modal=new Fl(this,this.$,i.html),this.figure=new ji(this,this.$,n,{sizeUnit:s}),this.fileModalWrapper=i.fileModalWrapper,this.embedInput=i.embedInput,this.focusElement=this.embedInput,this.previewSrc=i.previewSrc,this.sizeUnit=s,this.proportion=null,this.inputX=null,this.inputY=null,this.#Wu=this.pluginOptions.defaultWidth,this.#Uu=this.pluginOptions.defaultHeight,this.#ou="auto"===this.pluginOptions.defaultWidth?"":this.pluginOptions.defaultWidth,this.#ru="auto"===this.pluginOptions.defaultHeight?"":this.pluginOptions.defaultHeight,this.#ud=this.pluginOptions.canResize,this.#rp=this.pluginOptions.percentageOnlySize,this.#wu=!this.#ud||!this.pluginOptions.showHeightInput||this.#rp,this.query={facebook:{pattern:/(?:https?:\/\/)?(?:www\.)?(?:facebook\.com)\/(.+)/i,action:t=>`https://www.facebook.com/plugins/post.php?href=${encodeURIComponent(t)}&show_text=true&width=500`,tag:"iframe"},twitter:{pattern:/^(?:https?:\/\/)?(?:(?:www\.)?(?:twitter\.com|x\.com)\/(?:[^/?#]+\/)?status\/\d+(?:[/?#]|$)|platform\.twitter\.com\/embed\/Tweet\.html(?:[?#].*)?$)/i,action:t=>`https://platform.twitter.com/embed/Tweet.html?url=${encodeURIComponent(t)}`,tag:"iframe"},instagram:{pattern:/(?:https?:\/\/)?(?:www\.)?(?:instagram\.com)\/p\/(.+)/i,action:t=>`https://www.instagram.com/p/${t.match(this.query.instagram.pattern)[1]}/embed`,tag:"iframe"},linkedin:{pattern:/(?:https?:\/\/)?(?:www\.)?(?:linkedin\.com)\/(.+)\/(.+)/i,action:t=>`https://www.linkedin.com/embed/feed/update/${encodeURIComponent(t.split("/").pop())}`,tag:"iframe"},pinterest:{pattern:/(?:https?:\/\/)?(?:www\.)?(?:pinterest\.com)\/pin\/(.+)/i,action:t=>`https://assets.pinterest.com/ext/embed.html?id=${t.match(this.query.pinterest.pattern)[1]}`,tag:"iframe"},spotify:{pattern:/(?:https?:\/\/)?(?:open\.)?(?:spotify\.com)\/(track|album|playlist|show|episode)\/(.+)/i,action:t=>{const e=t.match(this.query.spotify.pattern);return`https://open.spotify.com/embed/${e[1]}/${e[2]}`},tag:"iframe"},codepen:{pattern:/(?:https?:\/\/)?(?:www\.)?(?:codepen\.io)\/(.+)\/pen\/(.+)/i,action:t=>{const[,e,s]=t.match(this.query.codepen.pattern);return`https://codepen.io/${e}/embed/${s}`},tag:"iframe"},...e.embedQuery};const o=[];for(const t in this.query)o.push(this.query[t].pattern);sc.#Xu=o.concat(e.urlPatterns||[]),this.$.eventManager.addEvent(this.embedInput,"input",this.#Nu.bind(this)),this.#ud&&(this.proportion=i.proportion,this.inputX=i.inputX,this.inputY=i.inputY,this.inputX.value=this.pluginOptions.defaultWidth,this.inputY.value=this.pluginOptions.defaultHeight,this.$.eventManager.addEvent(this.inputX,"keyup",this.#uu.bind(this,"x")),this.$.eventManager.addEvent(this.inputY,"keyup",this.#uu.bind(this,"y")),this.$.eventManager.addEvent(i.revertBtn,"click",this.#pu.bind(this)))}open(){this.modal.open()}retainFormat(){return{query:"iframe",method:async t=>{if(!sc.#Ku(t.src))return;const e=ji.GetContainer(t);if(e&&e.container&&e.cover)return;this.#Au(t,!0);const s=this.$.format.getLine(t);s&&(this.#ku=s.style.textAlign||s.style.float),this.#Ru(t)}}}modalOn(t){!t&&this.#ud?(this.inputX.value=this.#ou="auto"===this.pluginOptions.defaultWidth?"":this.pluginOptions.defaultWidth,this.inputY.value=this.#ru="auto"===this.pluginOptions.defaultHeight?"":this.pluginOptions.defaultHeight,this.proportion.disabled=!0):t&&(this.#_u=this.previewSrc.textContent=this.embedInput.value=this.#$u.getAttribute("data-se-origin")||"")}async modalAction(){this.#ku=this.modal.form.querySelector('input[name="suneditor_embed_radio"]:checked').value;let t=!1;return this.#_u.length>0&&(t=await this.submitSRC(this.#_u)),t&&tc.setTimeout(this.$.component.select.bind(this.$.component,this.#Pc,sc.key),0),t}modalInit(){Fl.OnChangeFile(this.fileModalWrapper,[]),this.#_u=this.previewSrc.textContent=this.embedInput.value="",this.modal.form.querySelector('input[name="suneditor_embed_radio"][value="none"]').checked=!0,this.#lu={w:0,h:0},this.#wu=!1,this.#ud&&(this.inputX.value=this.pluginOptions.defaultWidth===this.#Wu?"":this.pluginOptions.defaultWidth,this.inputY.value=this.pluginOptions.defaultHeight===this.#Uu?"":this.pluginOptions.defaultHeight,this.proportion.checked=!1,this.proportion.disabled=!0)}componentSelect(t){this.#Au(t)}componentEdit(){this.modal.open()}async componentDestroy(t){const e=t||this.#Pc,s=Pe.query.getParentElement(e,ji.is)||e,i=s.previousElementSibling||s.nextElementSibling,n=s.parentNode;!1!==await this.$.eventManager.triggerEvent("onEmbedDeleteBefore",{element:e,container:s,align:this.#ku,url:this.#_u})&&(Pe.utils.removeItem(s),this.modalInit(),n!==this.$.frameContext.get("wysiwyg")&&this.$.nodeTransform.removeAllParents(n,(function(t){return 0===t.childNodes.length}),null),this.$.focusManager.focusEdge(i),this.$.history.push(!1))}findProcessUrl(t){const e=this.query;for(const s in e){const i=e[s];if(i.pattern.test(t))return{origin:t,url:i.action(t),tag:i.tag}}return null}async submitSRC(t){if(!(t||=this.#_u))return!1;let e=null;if(/^{Pe.utils.removeItem(d),d=null},h.appendChild(d);const t=new MutationObserver((e=>{for(const s of e)if("childList"===s.type&&!a.parentElement){this.$.history.resume(),this.$.history.push(!1),t.disconnect();break}}));t.observe(this.$.frameContext.get("wysiwyg"),{subtree:!0,childList:!0})}catch(t){this.$.history.resume(),console.warn("[SUNEDITOR] Embed tag script load error.",t)}if(!this.$.options.get("componentInsertBehavior")){const t=this.$.format.addLine(c,null);t&&this.$.selection.setRange(t,0,t,0)}}}#Ru(t){if(!t)return;this.#Zu(t);const e=t;t=t.cloneNode(!0);const s=ji.CreateContainer(t,"se-embed-container").container;this.figure.open(t,{nonResizing:this.#wu,nonSizeInfo:!1,nonBorder:!1,figureTarget:!1,infoOnly:!0});const i=(t.getAttribute("data-se-size")||",").split(","),n=i[0]||e.width||"",o=i[1]||e.height||"";this.#cp(n,o);const r=this.$.format.getLine(e);return r&&(this.#ku=r.style.textAlign||r.style.float),this.figure.setAlign(t,this.#ku),this.figure.retainFigureFormat(s,this.#Pc,null,null),t}#cp(t,e){t||=this.inputX?.value||this.pluginOptions.defaultWidth,e||=this.inputY?.value||this.pluginOptions.defaultHeight,this.#rp&&(t?/%$/.test(t+"")||(t+="%"):t="100%"),this.figure.setSize(t,e)}#Pu(){return{inputWidth:this.inputX?.value||"",inputHeight:this.inputY?.value||"",align:this.#ku,isUpdate:this.modal.isUpdate,element:this.#Pc}}#Zu(t){t.frameBorder="0",t.allowFullscreen=!0;const e=this.pluginOptions.iframeTagAttributes;if(e)for(const s in e)t.setAttribute(s,e[s])}#Nu(t){const e=Pe.query.getEventTarget(t).value.trim();/^$/.test(e)?(this.#_u=e,this.previewSrc.textContent=''):this.#_u=this.previewSrc.textContent=e?this.$.options.get("defaultUrlProtocol")&&!e.includes("://")&&0!==e.indexOf("#")?this.$.options.get("defaultUrlProtocol")+e:e.includes("://")?e:"/"+e:""}#pu(){this.#rp?this.inputX.value=Number(this.#ou)>100?"100":this.#ou:(this.inputX.value=this.#ou,this.inputY.value=this.#ru)}#uu(t,e){if(Fe.isSpace(e.code))return void e.preventDefault();const s=Pe.query.getEventTarget(e);if("x"===t&&this.#rp&&Number(s.value)>100)s.value="100";else if(this.proportion.checked){const e=ji.CalcRatio(this.inputX.value,this.inputY.value,this.sizeUnit,this.#lu);"x"===t?this.inputY.value=String(e.h):this.inputX.value=String(e.w)}}}const ic=sc,{_w:nc,_d:oc}=Oe;class rc extends ta{static key="math";static className="";static component(t){return Pe.utils.hasClass(t,"se-math|katex")&&Pe.check.isComponentContainer(t)?t:null}#Pc=null;constructor(t,e){super(t),this.title=this.$.lang.math,this.icon="math",this.katex=null,this.mathjax=null,(this.katex=this.#dp())||(this.mathjax=this.#up())||console.warn('[SUNEDITOR.plugins.math.warn] The math plugin must need either "KaTeX" or "MathJax" library. Please add the katex or mathjax option. See: https://github.com/ARA-developer/suneditor/blob/develop/guide/external-libraries.md'),this.pluginOptions={formSize:{width:"460px",height:"14em",maxWidth:"",maxHeight:"",minWidth:"400px",minHeight:"40px",...e.formSize},canResize:e.canResize??!0,autoHeight:!!e.autoHeight,fontSizeList:e.fontSizeList||[{text:"1",value:"1em"},{text:"1.5",value:"1.5em"},{text:"2",value:"2em"},{text:"2.5",value:"2.5em"}],onPaste:"function"==typeof e.onPaste?e.onPaste:null},this.pluginOptions.autoHeight&&(this.pluginOptions.formSize.height=this.pluginOptions.formSize.minHeight),this.defaultFontSize=null;const s=function(t){const{$:e,pluginOptions:s,katex:i}=t,{lang:n,icons:o}=e,{formSize:r,fontSizeList:l,canResize:a,autoHeight:h}=s,{width:c,height:d,maxWidth:u,maxHeight:p,minWidth:g,minHeight:m}=r,f=a?h?"horizontal":"auto":"none";let v=l[0].value,b=`\n
    \n
    \n \n ${n.math_modal_title}\n
    \n
    \n
    \n \n \n
    \n
    \n \n \n
    \n
    \n \n

    \n
    \n
    \n \n
    `,t.defaultFontSize=v,Pe.utils.createElement("DIV",{class:"se-modal-content se-modal-responsive",style:`max-width: ${u}; max-height: ${p};`},b)}(this),i=function({lang:t,icons:e}){const s=`\n
    \n `;return Pe.utils.createElement("DIV",{class:"se-controller se-controller-link"},s)}(this.$);this.modal=new Fl(this,this.$,s),this.controller=new Ii(this,this.$,i,{position:"bottom",disabled:!0}),this.textArea=s.querySelector(".se-math-exp"),this.previewElement=s.querySelector(".se-math-preview"),this.fontSizeElement=s.querySelector(".se-math-size"),this.isUpdateState=!1,this.previewElement.style.fontSize=this.defaultFontSize,this.$.eventManager.addEvent(this.textArea,"input",this.#pp.bind(this)),this.$.eventManager.addEvent(this.fontSizeElement,"change",function(t){this.fontSize=t.target.value}.bind(this.previewElement.style)),this.pluginOptions.onPaste&&this.$.eventManager.addEvent(this.textArea,"paste",this.pluginOptions.onPaste.bind(this))}open(){this.modal.open()}retainFormat(){return{query:".se-math, .katex, .MathJax",method:t=>{if(!this.katex&&!this.mathjax)return;const e=lc(t);if(!e)return;const s=oc.createRange().createContextualFragment(this.#gp(ze.entityToHTML(this.#mp(e,!0))));t.innerHTML=s.querySelector(".se-math, .katex").innerHTML,t.setAttribute("contenteditable","false"),Pe.utils.addClass(t,"se-component|se-inline-component|se-disable-pointer|se-math"),this.katex?Pe.utils.addClass(t,"katex"):Pe.utils.removeClass(t,"katex"),this.mathjax&&this.#fp(this.mathjax)}}}modalOn(t){if(this.isUpdateState=t,t){if(this.controller.currentTarget){const t=this.controller.currentTarget,e=ze.entityToHTML(this.#mp(lc(t),!0)),s=function(t){const e=t.getAttribute("data-se-type");if(e)return e;const s=t.getAttribute("data-font-size");return s?(t.removeAttribute("data-font-size"),t.setAttribute("data-se-type",s),s):null}(t)||"1em";this.textArea.value=e,this.fontSizeElement.value=s,this.previewElement.innerHTML=this.#gp(e),this.previewElement.style.fontSize=s}}else this.modalInit()}async modalAction(){if(0===this.textArea.value.trim().length||Pe.utils.hasClass(this.textArea,"se-error"))return this.textArea.focus(),!1;const t=this.textArea.value,e=this.previewElement.querySelector(".se-math, .katex");if(!e)return!1;if(Pe.utils.addClass(e,"se-component|se-inline-component|se-disable-pointer|se-math"),e.setAttribute("contenteditable","false"),e.setAttribute("data-se-value",ze.htmlToEntity(this.#mp(t,!1))),e.setAttribute("data-se-type",this.fontSizeElement.value),e.style.fontSize=this.fontSizeElement.value,this.katex?(Pe.utils.addClass(e,"katex"),Pe.utils.removeClass(e,"MathJax")):Pe.utils.removeClass(e,"katex"),this.isUpdateState){Pe.query.getParentElement(this.controller.currentTarget,".se-component").replaceWith(e);const t=this.$.component.get(e);return this.$.component.select(t.target,t.pluginName),!0}{const t=this.$.format.getLines();if(t.length>1){const s=Pe.utils.createElement(t[0].nodeName,null,e);this.$.component.insert(s,{insertBehavior:"none",scrollTo:!1})}else this.$.component.insert(e,{insertBehavior:"none",scrollTo:!1})}this.mathjax&&this.#fp(this.mathjax);const s=this.$.selection.getNearRange(e);return s?this.$.selection.setRange(s.container,s.offset,s.container,s.offset):this.$.component.select(e,rc.key),!0}modalInit(){this.textArea.value="",this.previewElement.innerHTML="",Pe.utils.removeClass(this.textArea,"se-error")}controllerAction(t){switch(t.getAttribute("data-command")){case"update":this.modal.open();break;case"copy":this.#vp(this.#Pc);break;case"delete":this.componentDestroy(this.controller.currentTarget)}}controllerClose(){this.#Pc=null}componentSelect(t){if(Pe.utils.hasClass(t,"se-math|katex")&&lc(t))return this.#Pc=t,void this.controller.open(t,null,{isWWTarget:!1,initMethod:null,addOffset:null})}async componentDestroy(t){Pe.utils.removeItem(t),this.controller.close(),this.$.focusManager.focus(),this.$.history.push(!1)}#gp(t){let e="";try{if(Pe.utils.removeClass(this.textArea,"se-error"),this.katex)e=this.katex.src.renderToString(t,{throwOnError:!0,displayMode:!0});else{if(!this.mathjax){const t=new Error('404 Not found. "KaTeX" or "MathJax" library');throw t.code="MATH_LIB_NOT_FOUND",t}e=this.mathjax.convert(t).outerHTML,/${e}`):e=`${e}`}}catch(t){Pe.utils.addClass(this.textArea,"se-error"),e="MATH_LIB_NOT_FOUND"===t.code?`${t.message}`:`Math syntax error. (Refer ${this.katex?`KaTeX`:`MathJax`})`,console.warn("[SUNEDITOR.math.error] ",t.message)}return e}#mp(t,e){return t.replace(/\\{2}/g,e?"\\":"\\\\")}async#vp(t){if(navigator.clipboard&&t)try{const e=lc(t);await this.$.html.copy(e),Pe.utils.addClass(t,"se-copy"),nc.setTimeout((()=>{Pe.utils.removeClass(t,"se-copy")}),120)}catch(t){console.error("[SUNEDITOR.math.copy.fail]",t)}}#pp(t){const e=Pe.query.getEventTarget(t);this.pluginOptions.autoHeight&&(e.style.height="5px",e.style.height=e.scrollHeight+5+"px"),this.previewElement.innerHTML=this.#gp(e.value),this.mathjax&&this.#fp(this.mathjax)}#fp(t){t.clear(),t.updateDocument()}#dp(){const t=this.$.options.get("externalLibs").katex;if(!t)return null;if(!t.src)return console.warn("[SUNEDITOR.math.katex.fail] The katex option is set incorrectly."),null;const e=[{throwOnError:!1},t.options||{}].reduce(((t,e)=>{for(const s in e)t[s]=e[s];return t}),{});return t.options=e,t}#up(){const t=this.$.options.get("externalLibs").mathjax;if(!t)return null;this.$.frameOptions.get("iframe")&&console.warn("[SUNEDITOR.math.mathjax.fail] The MathJax option is not supported in the iframe.");try{const e=t.browserAdaptor();t.RegisterHTMLHandler(e);const s=new t.TeX,i=new t.CHTML;return t.src.document(document,{InputJax:s,OutputJax:i})}catch(t){return console.warn("[SUNEDITOR.math.mathjax.fail] The MathJax option is set incorrectly.",t),null}}}function lc(t){const e=t.getAttribute("data-se-value");if(e)return e;const s=t.getAttribute("data-exp");return s?(t.removeAttribute("data-exp"),t.setAttribute("data-se-value",s),s):null}const ac=rc,{_w:hc}=Oe;const cc=class extends ta{static key="drawing";static className="";#st;#bp;constructor(t,e){super(t),this.title=this.$.lang.drawing,this.icon="drawing",this.pluginOptions={outputFormat:e.outputFormat||"dataurl",useFormatType:e.useFormatType??!1,defaultFormatType:["block","inline"].includes(e.defaultFormatType)?e.defaultFormatType:"block",keepFormatType:e.keepFormatType??!1,lineWidth:e.lineWidth||5,lineReconnect:!!e.lineReconnect,lineCap:["butt","round","square"].includes(e.lineCap)?e.lineCap:"round",lineColor:e.lineColor||"",formSize:{width:"750px",height:"50vh",maxWidth:"",maxHeight:"",minWidth:"150px",minHeight:"100px",...e.formSize},canResize:e.canResize??!0,maintainRatio:e.maintainRatio??!0},this.$.plugins.image?"svg"!==this.pluginOptions.outputFormat||this.$.plugins.image.pluginOptions.uploadUrl||console.warn('[SUNEDITOR.plugins.drawing.warn] The drawing plugin must need the "image" plugin with the "uploadUrl" option. Please add the "image" plugin with the "uploadUrl" option.'):console.warn('[SUNEDITOR.plugins.drawing.warn] The drawing plugin must need either "image" plugin. Please add the "image" plugin.');const s=function({lang:t,icons:e},s){const{width:i,height:n,maxWidth:o,maxHeight:r,minWidth:l,minHeight:a}=s.formSize,h=`\n
    \n
    \n \n ${t.drawing_modal_title}\n
    \n
    \n \n\t\t\t${s.canResize?'
    ':""}\n\t\t
    \n\t\t
    \n\t\t\t
    \n\t\t\t\t
    \n\t\t\t\t\t${s.useFormatType?`\n\t\t\t\t\t\t\t
    \n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t
    `:""}\n\t\t\t\t\t
    \n\t\t\t\t\t\t\n\t\t\t\t\t
    \n\t\t\t\t
    \n\t\t\t
    \n\t\t
    \n \n
    `;return Pe.utils.createElement("DIV",{class:"se-modal-content se-modal-responsive",style:`max-width: ${o}; max-height: ${r};`},h)}(this.$,this.pluginOptions);this.modal=new Fl(this,this.$,s),this.as=this.pluginOptions.defaultFormatType,this.pluginOptions.useFormatType&&(this.asBlock=s.querySelector('[data-command="asBlock"]'),this.asInline=s.querySelector('[data-command="asInline"]'),this.$.eventManager.addEvent([this.asBlock,this.asInline],"click",this.#Lu.bind(this))),this.canvas=null,this.ctx=null,this.isDrawing=!1,this.points=[],this.paths=[],this.resizeObserver=null,this.#st={touchstart:this.#yp.bind(this),touchmove:this.#wp.bind(this),mousedown:this.#Cp.bind(this),mousemove:this.#_p.bind(this),mouseup:this.#kp.bind(this),mouseleave:this.#xp.bind(this),mouseenter:this.#$p.bind(this)},this.#bp={touchstart:null,touchmove:null,mousedown:null,mousemove:null,mouseup:null,mouseleave:null,mouseenter:null},this.$.eventManager.addEvent(s.querySelector('[data-command="remove"]'),"click",this.#Sp.bind(this))}open(){this.pluginOptions.useFormatType&&this.#zu("inline"===(this.pluginOptions.keepFormatType?this.as:this.pluginOptions.defaultFormatType)),this.modal.open(),this.#Ep()}modalOff(){this.#Tp()}async modalAction(){if("svg"===this.pluginOptions.outputFormat){const t=this.#Mp();this.$.plugins.image.modalInit(),this.$.plugins.image.submitFile(t)}else{const t=this.canvas.toDataURL(),e={name:"drawing",size:0};this.$.plugins.image.modalInit(),"inline"!==this.as?this.$.plugins.image.create(t,null,"auto","","none",e,""):this.$.plugins.image.createInline(t,null,"auto","","none",e,"")}return!0}#Ep(){const t=this.canvas=this.modal.form.querySelector(".se-drawing-canvas");this.ctx=t.getContext("2d"),t.width=t.offsetWidth,t.height=t.offsetHeight,this.points=[],this.paths=[],this.#Np(),this.#bp.touchstart=this.$.eventManager.addEvent(t,"touchstart",this.#st.touchstart,{passive:!1,capture:!0}),this.#bp.touchmove=this.$.eventManager.addEvent(t,"touchmove",this.#st.touchmove,!0),this.#bp.mousedown=this.$.eventManager.addEvent(t,"mousedown",this.#st.mousedown,{passive:!1,capture:!0}),this.#bp.mousemove=this.$.eventManager.addEvent(t,"mousemove",this.#st.mousemove,!0),this.#bp.mouseup=this.$.eventManager.addEvent(t,"mouseup",this.#st.mouseup,!0),this.#bp.mouseleave=this.$.eventManager.addEvent(t,"mouseleave",this.#st.mouseleave),this.#bp.mouseenter=this.$.eventManager.addEvent(t,"mouseenter",this.#st.mouseenter),this.resizeObserver&&(this.resizeObserver.disconnect(),this.resizeObserver=null),Oe.isResizeObserverSupported&&(this.resizeObserver=new ResizeObserver((()=>{const e=t.width,s=t.height,i=t.offsetWidth,n=t.offsetHeight;t.width=i,t.height=n,e===t.width&&s===t.height||(this.pluginOptions.maintainRatio&&this.#Bp(e,s,i,n),this.#Ip())})),this.resizeObserver.observe(t))}#Tp(){this.resizeObserver&&(this.resizeObserver.disconnect(),this.resizeObserver=null),this.canvas&&(this.$.eventManager.removeEvent(this.#bp.mousedown),this.$.eventManager.removeEvent(this.#bp.mousemove),this.$.eventManager.removeEvent(this.#bp.mouseup),this.$.eventManager.removeEvent(this.#bp.mouseleave),this.$.eventManager.removeEvent(this.#bp.mouseenter)),this.canvas=null,this.ctx=null,this.points=[],this.paths=[],this.isDrawing=!1}#Np(){this.ctx.lineWidth=this.pluginOptions.lineWidth,this.ctx.lineCap=this.pluginOptions.lineCap,this.ctx.strokeStyle=this.pluginOptions.lineColor||hc.getComputedStyle(this.$.contextProvider.carrierWrapper).color}#Lp(){this.#Np(),this.ctx.beginPath(),this.points.forEach((([t,e],s)=>{0===s?this.ctx.moveTo(t,e):this.ctx.lineTo(t,e)})),this.ctx.stroke()}#Ip(){this.#Np(),this.ctx.clearRect(0,0,this.canvas.width,this.canvas.height),this.paths.forEach((t=>{this.points=t,this.#Lp()})),this.points=[]}#Bp(t,e,s,i){const n=s/t,o=i/e;this.paths=this.paths.map((t=>t.map((([t,e])=>[t*n,e*o]))))}#Ap(){this.ctx.clearRect(0,0,this.canvas.width,this.canvas.height),this.points=[],this.paths=[]}#Op(){const t="http://www.w3.org/2000/svg",e=document.createElementNS(t,"svg");return e.setAttribute("width",this.canvas.width+""),e.setAttribute("height",this.canvas.height+""),e.setAttribute("viewBox",`0 0 ${this.canvas.width} ${this.canvas.height}`),e.setAttribute("xmlns",t),this.paths.forEach((s=>{const i=s.reduce(((t,[e,s],i)=>t+(0===i?`M ${e} ${s}`:` L ${e} ${s}`)),""),n=document.createElementNS(t,"path");n.setAttribute("d",i),n.setAttribute("fill","none"),n.setAttribute("stroke",String(this.ctx.strokeStyle)),n.setAttribute("stroke-width",this.ctx.lineWidth+""),e.appendChild(n)})),e}#Mp(){const t=this.#Op(),e=(new XMLSerializer).serializeToString(t),s=new Blob([e],{type:"image/svg+xml"}),i=new File([s],"drawing.svg",{type:"image/svg+xml"}),n=new DataTransfer;return n.items.add(i),n.files}#Rp(t){const{touches:e}=t,s=this.canvas.getBoundingClientRect();return{x:e[0].clientX-s.left,y:e[0].clientY-s.top}}#zu(t){t?(Pe.utils.addClass(this.asInline,"on"),Pe.utils.removeClass(this.asBlock,"on"),this.as="inline"):(Pe.utils.addClass(this.asBlock,"on"),Pe.utils.removeClass(this.asInline,"on"),this.as="block")}#Cp(t){t.preventDefault(),this.isDrawing=!0,this.points.push([t.offsetX,t.offsetY]),this.#Lp()}#_p(t){t.preventDefault(),this.isDrawing&&(this.points.push([t.offsetX,t.offsetY]),this.#Lp())}#yp(t){t.preventDefault();const{x:e,y:s}=this.#Rp(t);this.isDrawing=!0,this.points.push([e,s]),this.#Lp()}#wp(t){t.preventDefault();const{x:e,y:s}=this.#Rp(t);this.isDrawing&&(this.points.push([e,s]),this.#Lp())}#kp(){this.isDrawing=!1,this.points.length>0&&(this.paths.push([...this.points]),this.points=[])}#xp(){this.isDrawing&&(this.paths.push([...this.points]),this.pluginOptions.lineReconnect||(this.points=[],this.isDrawing=!1))}#$p(t){if(1===t.buttons){if(this.isDrawing=!0,this.pluginOptions.lineReconnect){const e=this.paths.at(-1).at(-1);this.points.push([e[0],e[1]]),this.points.push([t.offsetX,t.offsetY])}else this.points.push([t.offsetX,t.offsetY]);this.#Lp()}}#Sp(){this.#Ap()}#Lu(t){this.#zu("asInline"===Pe.query.getEventTarget(t).getAttribute("data-command"))}};const dc=class extends Kl{static key="imageGallery";static className="";constructor(t,e){super(t),this.title=this.$.lang.imageGallery,this.icon="image_gallery",this.onSelectfunction=null,this.browser=new Xr(this,this.$,{title:this.$.lang.imageGallery,data:e.data,url:e.url,headers:e.headers,searchUrl:e.searchUrl,searchHeaders:e.searchHeaders,selectorHandler:this.#zp.bind(this),columnSize:4,className:"se-image-gallery"}),this.width="auto"===this.$.plugins.image.pluginOptions.defaultWidth?"":this.$.plugins.image.pluginOptions.defaultWidth,this.height="auto"===this.$.plugins.image.pluginOptions.defaultHeight?"":this.$.plugins.image.pluginOptions.defaultHeight}open(t){this.onSelectfunction=t,this.browser.open()}close(){this.onSelectfunction=null,this.browser.close()}#zp(t){if(this.onSelectfunction)this.onSelectfunction(t);else{const e={name:t.getAttribute("data-name"),size:0};this.$.plugins.image.modalInit(),this.$.plugins.image.create(t.getAttribute("data-command"),null,this.width,this.height,"none",e,t.alt,!0)}}};const uc=class extends Kl{static key="videoGallery";static className="";constructor(t,e){super(t),this.title=this.$.lang.videoGallery,this.icon="video_gallery",this.onSelectfunction=null;const s="string"==typeof e.thumbnail?e.thumbnail:this.$.icons.video_thumbnail;this.browser=new Xr(this,this.$,{title:this.$.lang.videoGallery,data:e.data,url:e.url,headers:e.headers,searchUrl:e.searchUrl,searchHeaders:e.searchHeaders,selectorHandler:this.#zp.bind(this),columnSize:4,className:"se-video-gallery",thumbnail:"function"==typeof e.thumbnail?e.thumbnail:()=>s,props:["frame"]}),this.width="auto"===this.$.plugins.video.pluginOptions.defaultWidth?"":this.$.plugins.video.pluginOptions.defaultWidth,this.height="auto"===this.$.plugins.video.pluginOptions.defaultHeight?"":this.$.plugins.video.pluginOptions.defaultHeight}open(t){this.onSelectfunction=t,this.browser.open()}close(){this.onSelectfunction=null,this.browser.close()}#zp(t){if(this.onSelectfunction)this.onSelectfunction(t);else{let e=t.getAttribute("data-command");const s=this.$.plugins.video.findProcessUrl(e);s&&(e=s.url);const i={name:t.getAttribute("data-name"),size:0};this.$.plugins.video.modalInit(),this.$.plugins.video.create(this.$.plugins.video["iframe"===t.getAttribute("data-frame")?"createIframeTag":"createVideoTag"]({poster:t.getAttribute("data-thumbnail")}),e,null,this.width,this.height,!1,i,!0)}}};const pc=class extends Kl{static key="audioGallery";static className="";constructor(t,e){super(t),this.title=this.$.lang.audioGallery,this.icon="audio_gallery",this.onSelectfunction=null;const s="string"==typeof e.thumbnail?e.thumbnail:this.$.icons.audio_thumbnail;this.browser=new Xr(this,this.$,{title:this.$.lang.audioGallery,data:e.data,url:e.url,headers:e.headers,searchUrl:e.searchUrl,searchHeaders:e.searchHeaders,selectorHandler:this.#zp.bind(this),columnSize:4,className:"se-audio-gallery",thumbnail:"function"==typeof e.thumbnail?e.thumbnail:()=>s})}open(t){this.onSelectfunction=t,this.browser.open()}close(){this.onSelectfunction=null,this.browser.close()}#zp(t){this.onSelectfunction?this.onSelectfunction(t):(this.$.plugins.audio.modalInit(),this.$.plugins.audio.submitURL(t.getAttribute("data-command")))}};const gc=class extends Kl{static key="fileGallery";static className="";constructor(t,e){super(t),this.title=this.$.lang.fileGallery,this.icon="file_gallery",this.onSelectfunction=null;const s="string"==typeof e.thumbnail?e.thumbnail:this.$.icons.file_thumbnail;this.browser=new Xr(this,this.$,{title:this.$.lang.fileGallery,data:e.data,url:e.url,headers:e.headers,searchUrl:e.searchUrl,searchHeaders:e.searchHeaders,selectorHandler:this.#zp.bind(this),columnSize:4,className:"se-file-gallery",thumbnail:"function"==typeof e.thumbnail?e.thumbnail:()=>s})}open(t){this.onSelectfunction=t,this.browser.open()}close(){this.onSelectfunction=null,this.browser.close()}#zp(t){if(this.onSelectfunction)this.onSelectfunction(t);else{const e={name:t.getAttribute("data-name"),size:0};this.$.plugins.fileUpload.create(t.getAttribute("data-command"),e,!0)}}};const mc=class extends Kl{static key="fileBrowser";static className="";constructor(t,e){super(t),this.title=this.$.lang.fileBrowser,this.icon="file_browser",this.onSelectfunction=null;const s={video:this.$.icons.video_thumbnail,audio:this.$.icons.audio_thumbnail,file:this.$.icons.file_thumbnail},i=this.$.icons.file_thumbnail;this.browser=new Xr(this,this.$,{title:this.$.lang.fileBrowser,data:e.data,url:e.url,headers:e.headers,searchUrl:e.searchUrl,searchHeaders:e.searchHeaders,selectorHandler:this.#zp.bind(this),columnSize:4,className:"se-file-browser",thumbnail:"function"==typeof e.thumbnail?e.thumbnail:t=>s[t.type]||i,props:[...new Set((e.props??[]).concat(["frame"]))],expand:e.expand})}open(t){this.onSelectfunction=t,this.browser.open()}close(){this.onSelectfunction=null,this.browser.close()}#zp(t){if(this.onSelectfunction)this.onSelectfunction(t);else{switch(t.getAttribute("data-type")){case"image":this.$.plugins.imageGallery.browser.selectorHandler(t);break;case"video":this.$.plugins.videoGallery.browser.selectorHandler(t);break;case"audio":this.$.plugins.audioGallery.browser.selectorHandler(t);break;case"file":this.$.plugins.fileGallery.browser.selectorHandler(t)}}}},fc={text:{default:"16px",list:[{title:"XX-Small",size:"8px"},{title:"X-Small",size:"10px"},{title:"Small",size:"13px"},{title:"Medium",size:"16px"},{title:"Large",size:"18px"},{title:"X-Large",size:"24px"},{title:"XX-Large",size:"32px"}]},px:{default:13,inc:1,min:8,max:72,list:[8,10,13,15,18,20,22,26,28,36,48,72]},pt:{default:10,inc:1,min:6,max:72,list:[6,8,10,12,14,18,22,26,32]},em:{default:1,inc:.1,min:.5,max:5,list:[.5,.75,1,1.25,1.5,1.75,2,2.5,3]},rem:{default:1,inc:.1,min:.5,max:5,list:[.5,.75,1,1.25,1.5,1.75,2,2.5,3]},vw:{inc:.1,min:.5,max:10,list:[2,3.5,4,4.5,6,8]},vh:{default:1.5,inc:.1,min:.5,max:10,list:[1,1.5,2,2.5,3,3.5,4]},"%":{default:100,inc:1,min:50,max:200,list:[50,70,90,100,120,140,160,180,200]}};class vc extends Ql{static key="fontSize";static className="se-btn-select se-btn-input se-btn-tool-font-size";#Pp;constructor(t,e){super(t),this.unitMap={...fc,...e.unitMap||{}},this.sizeUnit=/text/.test(e.sizeUnit)?"":e.sizeUnit||this.$.options.get("fontSizeUnits")[0];const s=this.unitMap[this.sizeUnit||"text"],i=function({lang:t},e,s,i){const n=e.list,o=e.default,r=i?t.default:"";let l='\n\t
    \n\t\t
      ';for(let t,e,i,a,h,c=0,d=n.length;c\n\t\t\t\t\n\t\t\t`;return l+="\n\t\t
    \n\t
    ",Pe.utils.createElement("DIV",{class:"se-dropdown se-list-layer se-list-font-size"},l)}(this.$,s,this.sizeUnit,e.showDefaultSizeLabel),n=!!this.sizeUnit&&(e.showIncDecControls??!1),o=!this.sizeUnit||(e.disableInput??!1);this.title=this.$.lang.fontSize,this.inner=!(o&&!n)&&(o?`${this.$.lang.fontSize}`:``),n?(this.beforeItem=Pe.utils.createElement("button",{class:"se-btn se-tooltip se-sub-btn",type:"button","data-command":vc.key,"data-type":"command","data-value":"dec"},`${this.$.icons.minus}${this.$.lang.decrease}`),this.afterItem=Pe.utils.createElement("button",{class:"se-btn se-tooltip se-sub-btn",type:"button","data-command":vc.key,"data-type":"command","data-value":"inc"},`${this.$.icons.plus}${this.$.lang.increase}`)):o?o&&!n&&(this.replaceButton=Pe.utils.createElement("button",{class:"se-btn se-tooltip se-btn-select se-btn-tool-font-size",type:"button","data-command":vc.key,"data-type":"dropdown"},`${this.$.lang.fontSize}${this.$.icons.arrow_down}${this.$.lang.fontSize}`),this.$.menu.initDropdownTarget({key:vc.key,type:"dropdown"},i)):(this.afterItem=Pe.utils.createElement("button",{class:"se-btn se-tooltip se-sub-arrow-btn",type:"button","data-command":vc.key,"data-type":"dropdown"},`${this.$.icons.arrow_down}${this.$.lang.fontSize}`),this.$.menu.initDropdownTarget({key:vc.key,type:"dropdown"},i)),this.currentSize="",this.sizeList=i.querySelectorAll("li button"),this.hasInputFocus=!1,this.isInputActive=!1,this.#Pp=o,this.$.menu.initDropdownTarget(vc,i)}active(t,e){if(!Pe.utils.hasClass(e,"__se__font_size"))return!1;let s="";if(t){if(this.$.format.isLine(t))return;if(s=Pe.utils.getStyle(t,"fontSize"))return this.#Dp(e,s),!0}else this.#Dp(e,this.#Fp());return!1}toolbarInputKeyDown({target:t,event:e}){const s=e.code;if(this.#Pp||Fe.isSpace(s))return void e.preventDefault();if(!/^(ArrowUp|ArrowDown|Enter)$/.test(s))return;const{value:i,unit:n}=this.#Hp(t);if(!i)return;const o=De.get(i),r=this.unitMap[n];let l=o;switch(s){case"ArrowUp":l+=r.inc,l>r.max&&(l=o);break;case"ArrowDown":l-=r.inc,ln?n:so?o:i;const r=Pe.utils.createElement("SPAN",{style:"font-size: "+i+s+";"});this.$.inline.apply(r,{stylesToModify:["font-size"],nodesToRemove:null,strictRemove:null})}else if(e){const t=Pe.utils.createElement("SPAN",{style:"font-size: "+e+";"});this.$.inline.apply(t,{stylesToModify:["font-size"],nodesToRemove:null,strictRemove:null})}else this.$.inline.apply(null,{stylesToModify:["font-size"],nodesToRemove:["span"],strictRemove:!0});this.$.menu.dropdownOff()}#Fp(){return this.$.frameContext.get("wwComputedStyle").fontSize}#Hp(t){if(!(t="string"==typeof t?t:t.parentElement.querySelector(".__se__font_size")))return{unit:this.sizeUnit,value:this.sizeUnit?0:""};const e="string"==typeof t?t:Pe.check.isInputElement(t)?t.value:t.textContent,s=this.sizeUnit?e.split(/(\d+)/):[e,""];let i=(s.pop()||"").trim().toLowerCase();i=this.$.options.get("fontSizeUnits").includes(i)?i:this.sizeUnit;const n=s.pop();return{unit:i,value:i?Number(n):n}}#Dp(t,e){return(t=t.parentElement.querySelector(".__se__font_size"))?Pe.check.isInputElement(t)?t.value=String(e):t.textContent=String(this.sizeUnit?e:this.unitMap.text.list.find((t=>t.size===e))?.title||e):0}}const bc=vc;const yc=class extends Ql{static key="pageNavigator";static className="se-btn-input se-btn-tool-pageNavigator";constructor(t){super(t),this.title=this.$.lang.pageNumber,this.inner=Pe.utils.createElement("input",{type:"number",class:"se-not-arrow-text",placeholder:"1",value:"1",min:"1"},null),this.afterItem=Pe.utils.createElement("span",{class:"se-btn se-sub-btn"},""),this.pageNum=1,this.totalPages=1,this.$.eventManager.addEvent(this.inner,"change",this.#qp.bind(this))}display(t,e){this.pageNum=t,this.totalPages=e,this.inner.value=String(t),this.afterItem.textContent=this.inner.max=String(e)}#qp(t){if(!this.$.frameContext.has("documentType_use_page"))return;const e=Pe.query.getEventTarget(t),s=Number(e.value)||1;this.$.frameContext.get("documentType").pageGo(s)}},{_w:wc}=Oe;class Cc extends ea{static key="anchor";static className="";static component(t){return Pe.check.isAnchor(t)&&t.hasAttribute("id")&&t.hasAttribute("data-se-anchor")?t:null}#Pc=null;#Wp=null;constructor(t){super(t),this.title=this.$.lang.anchor,this.icon="bookmark_anchor";const e=(new DOMParser).parseFromString(this.$.icons.bookmark_anchor,"image/svg+xml");this.bookmarkIcon=e.documentElement;const s=function({lang:t,icons:e}){const s=`\n\t
    \n\t`;return Pe.utils.createElement("DIV",{class:"se-controller se-controller-link"},s)}(this.$);this.displayId=s.querySelector(".se-controller-display"),this.controllerSelect=new Ii(this,this.$,s,{position:"bottom",disabled:!0},Cc.key);const i=function({lang:t,icons:e}){const s=`\n\t\t
    \n\t\t
    \n\t\t\t
    ${t.id}
    \n\t\t\t
    \n\t\t\t\t\n\t\t\t\t\n\t\t\t\t\n\t\t\t
    \n\t\t
    \n\t\t`;return Pe.utils.createElement("DIV",{class:"se-controller se-controller-simple-input"},s)}(this.$);this.inputEl=i.querySelector("input"),this.controller=new Ii(this,this.$,i,{position:"bottom",disabled:!0,parents:[this.controllerSelect.form],parentsHide:!0},Cc.key)}show(){this.controller.open(this.#Wp=this.$.selection.getRange()),wc.setTimeout((()=>{this.inputEl.focus()}),0)}componentSelect(t){this.#Pc=t,this.displayId.textContent=t.getAttribute("id"),this.controllerSelect.open(t)}componentDeselect(){this.#Ts()}controllerAction(t){const e=t.getAttribute("data-command");if(!e)return;const s=this.#Pc;switch(e){case"submit":if(this.controller.close(),s)s.id=this.inputEl.value,this.$.component.select(s,Cc.key);else{const t=this.inputEl.value.trim();if(!t)return void this.inputEl.focus();const e=Pe.utils.createElement("A",{id:t,"data-se-anchor":this.inputEl.value,"data-se-non-link":"true",contenteditable:"false",class:"se-component se-inline-component"});this.$.component.insert(e,{insertBehavior:"none",scrollTo:!1});const s=this.$.selection.getNearRange(e);s?this.$.selection.setRange(s.container,s.offset,s.container,s.offset):this.$.component.select(e,Cc.key),this.#Ts()}break;case"cancel":this.controller.close(!s),this.#Wp&&this.$.selection.setRange(this.#Wp),this.#Ts(),s&&this.componentSelect(s);break;case"edit":this.inputEl.value=this.displayId.textContent,this.controllerSelect.hide(),this.controller.open(s),this.inputEl.focus();break;case"delete":{const t=this.$.selection.getNearRange(s);Pe.utils.removeItem(s),this.controllerSelect.close(!0),t&&this.$.selection.setRange(t.container,t.offset,t.container,t.offset),this.#Ts();break}}}#Ts(){this.#Pc=null,this.#Wp=null,this.inputEl.value="",this.displayId.textContent=""}}const _c={blockquote:sa,codeBlock:oa,exportPDF:aa,fileUpload:da,list_bulleted:pa,list_numbered:fa,autocomplete:wa,slashCommand:_a,align:xa,font:Sa,fontColor:Ta,backgroundColor:Na,list:Aa,table:wh,blockStyle:_h,hr:Ia,layout:xh,lineHeight:Sh,template:Th,paragraphStyle:Nh,textStyle:Ih,link:Lh,image:qh,video:Yh,audio:Qh,embed:ic,math:ac,drawing:cc,imageGallery:dc,videoGallery:uc,audioGallery:pc,fileGallery:gc,fileBrowser:mc,fontSize:bc,pageNavigator:yc,anchor:Cc};class kc{async modalAction(){return!0}modalOn(t){}modalInit(){}modalOff(t){}modalResize(){}}class xc{controllerAction(t){}controllerOn(t,e){}controllerClose(){}}class $c{browserInit(){}}class Sc{colorPickerAction(t){}colorPickerHueSliderOpen(){}colorPickerHueSliderClose(){}}class Ec{hueSliderAction(){}hueSliderCancelAction(){}}class Tc{componentSelect(t){}componentDeselect(t){}componentEdit(t){}async componentDestroy(t){}componentCopy(t){}}const Mc={contract:t,manager:e,ui:i};Object.defineProperty(window,"SUNEDITOR",{enumerable:!0,writable:!1,configurable:!1,value:{...jl,plugins:_c,modules:Mc,helper:Ve,interfaces:n}})})()})(); \ No newline at end of file diff --git a/js/tickets.js b/js/tickets.js new file mode 100644 index 0000000..03ab103 --- /dev/null +++ b/js/tickets.js @@ -0,0 +1,17 @@ +/* HTML maxlength counts UTF-16 units; the server counts Unicode code points. */ +(function () { + 'use strict'; + function initialize() { + document.querySelectorAll('[data-character-limit]').forEach(function (field) { + const limit = Number(field.dataset.characterLimit); + function validate() { + const tooLong = Array.from(field.value.replace(/^[ \t\n\r\0\v]+|[ \t\n\r\0\v]+$/g, '')).length > limit; + field.setCustomValidity(tooLong ? 'Please enter ' + limit + ' characters or fewer.' : ''); + } + field.addEventListener('input', validate); + validate(); + }); + } + if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', initialize); + else initialize(); +}()); diff --git a/main.php b/main.php index 6396b93..3b68b64 100644 --- a/main.php +++ b/main.php @@ -1,28 +1,37 @@ status:($e instanceof InvalidArgumentException?422:500); - $message=$status<500?$e->getMessage():'The application could not complete this request. Please try again later.'; - if($e instanceof PDOException && $e->getCode()==='23000'){$status=409;$message='This record already exists or is still referenced by another record.';} - if($status>=500)error_log((string)$e); + $status = $e instanceof AppException ? $e->status : ($e instanceof InvalidArgumentException ? 422 : 500); + $message = $status < 500 ? $e->getMessage() : 'The application could not complete this request. Please try again later.'; + if ($e instanceof PDOException && $e->getCode() === '23000') { + $status = 409; + $message = 'This record already exists or is still referenced by another record.'; + } + if ($status >= 500) + error_log((string) $e); http_response_code($status); - if(strtolower($_SERVER['HTTP_X_REQUESTED_WITH']??'')==='xmlhttprequest'){ - header('Content-Type: application/json');echo json_encode(['ok'=>false,'error'=>$message]); - }else{header('Content-Type: text/html; charset=UTF-8');echo 'Request could not be completed

    Request could not be completed

    '.htmlspecialchars($message,ENT_QUOTES,'UTF-8').'

    Return to the application

    ';} + if (strtolower($_SERVER['HTTP_X_REQUESTED_WITH'] ?? '') === 'xmlhttprequest') { + header('Content-Type: application/json'); + echo json_encode(['ok' => false, 'error' => $message]); + } else { + header('Content-Type: text/html; charset=UTF-8'); + echo 'Request could not be completed

    Request could not be completed

    ' . htmlspecialchars($message, ENT_QUOTES, 'UTF-8') . '

    Return to the application

    '; + } }); require_once __DIR__ . '/classes/Base.php'; $application = new Base(); -$https = Transport::https($_SERVER,getenv('HCR_TRUSTED_PROXIES')?:''); +$https = Transport::https($_SERVER, getenv('HCR_TRUSTED_PROXIES') ?: ''); header("Content-Security-Policy: default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self'; connect-src 'self'; object-src 'none'; base-uri 'self'; form-action 'self'; frame-ancestors 'none'"); header('Permissions-Policy: camera=(), microphone=(), geolocation=()'); -if($https&&(string)$application->getSettings()->Environment==='Production')header('Strict-Transport-Security: max-age=31536000'); +if ($https && (string) $application->getSettings()->Environment === 'Production') + header('Strict-Transport-Security: max-age=31536000'); if ((string) $application->getSettings()->Environment === 'Production' && !$https) { http_response_code(400); exit('HTTPS is required. Open the secure application URL.'); diff --git a/migrations/004_tenants.sql b/migrations/004_tenants.sql new file mode 100644 index 0000000..350a70c --- /dev/null +++ b/migrations/004_tenants.sql @@ -0,0 +1,35 @@ +CREATE TABLE IF NOT EXISTS club_invitations ( + invitation_serial BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, + club_serial BIGINT UNSIGNED NOT NULL, + invite_email VARCHAR(100) NOT NULL, + membership_role ENUM('member','administrator') NOT NULL DEFAULT 'member', + invited_by BIGINT UNSIGNED NOT NULL, + invitation_status ENUM('pending','accepted','revoked') NOT NULL DEFAULT 'pending', + expires_at DATETIME NOT NULL, + sent_at DATETIME NOT NULL, + accepted_at DATETIME NULL, + UNIQUE KEY (club_serial,invite_email), + FOREIGN KEY (club_serial) REFERENCES clubs(club_serial) ON DELETE RESTRICT, + FOREIGN KEY (invited_by) REFERENCES users(user_serial) ON DELETE RESTRICT +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +CREATE TABLE IF NOT EXISTS club_tickets ( + ticket_serial BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, + club_serial BIGINT UNSIGNED NOT NULL, + user_serial BIGINT UNSIGNED NOT NULL, + subject VARCHAR(200) NOT NULL, + ticket_status ENUM('open','closed') NOT NULL DEFAULT 'open', + created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + INDEX (club_serial,user_serial,ticket_serial), + FOREIGN KEY (club_serial) REFERENCES clubs(club_serial) ON DELETE RESTRICT, + FOREIGN KEY (user_serial) REFERENCES users(user_serial) ON DELETE RESTRICT +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +CREATE TABLE IF NOT EXISTS club_ticket_messages ( + message_serial BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, + ticket_serial BIGINT UNSIGNED NOT NULL, + author_serial BIGINT UNSIGNED NOT NULL, + message_text TEXT NOT NULL, + created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + FOREIGN KEY (ticket_serial) REFERENCES club_tickets(ticket_serial) ON DELETE RESTRICT, + FOREIGN KEY (author_serial) REFERENCES users(user_serial) ON DELETE RESTRICT +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; diff --git a/migrations/005_security_capacity.sql b/migrations/005_security_capacity.sql new file mode 100644 index 0000000..3a0ecf7 --- /dev/null +++ b/migrations/005_security_capacity.sql @@ -0,0 +1,20 @@ +CREATE TABLE IF NOT EXISTS user_mfa ( + user_serial BIGINT UNSIGNED NOT NULL PRIMARY KEY, + secret_cipher TEXT NOT NULL, + last_counter BIGINT NOT NULL DEFAULT -1, + FOREIGN KEY (user_serial) REFERENCES users(user_serial) ON DELETE CASCADE +) ENGINE=InnoDB; +CREATE TABLE IF NOT EXISTS mfa_recovery ( + user_serial BIGINT UNSIGNED NOT NULL, + code_hash CHAR(64) CHARACTER SET ascii COLLATE ascii_bin NOT NULL, + PRIMARY KEY(user_serial,code_hash), + FOREIGN KEY (user_serial) REFERENCES users(user_serial) ON DELETE CASCADE +) ENGINE=InnoDB; +CREATE TABLE IF NOT EXISTS club_resource_usage ( + club_serial BIGINT UNSIGNED NOT NULL, + resource_name VARCHAR(32) NOT NULL, + window_started DATETIME NOT NULL, + used_count INT UNSIGNED NOT NULL, + PRIMARY KEY(club_serial,resource_name), + FOREIGN KEY (club_serial) REFERENCES clubs(club_serial) ON DELETE RESTRICT +) ENGINE=InnoDB; diff --git a/tests/application_harness.py b/tests/application_harness.py index b4839dd..57c8fa0 100644 --- a/tests/application_harness.py +++ b/tests/application_harness.py @@ -20,7 +20,8 @@ class Application: if not os.environ.get('HCR_TEST_DSN'): raise RuntimeError('An isolated HCR_TEST_DSN is required.') self.env=os.environ.copy() - self.env.update(HCR_APPLICATION_URL='',HCR_ENVIRONMENT='Development') + self.env['HCR_MFA_KEY']='AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=' + self.env.update(HCR_SUPER_ADMIN_EMAIL='',HCR_APPLICATION_URL='',HCR_ENVIRONMENT='Development',HCR_SMTP_HOST='127.0.0.1',HCR_SMTP_PORT='1',HCR_SMTP_USER='test@example.test',HCR_SMTP_PASSWORD='test-only',HCR_SMTP_FROM='test@example.test') self.database=self.fixture('create')['database'] self.env['HCR_DB_NAME']=self.database with socket.socket() as available: @@ -52,7 +53,27 @@ class Application: _,body,_=self.request() status,body,_=self.request(data={'action':'SignIn.login','csrf_token':self.csrf(body),'user_email':email,'user_password':password}) if status!=200 or b'name="csrf-token"' not in body:raise AssertionError('Login failed: '+body[:500].decode(errors='replace')) + if b'

    Account security

    ' in body: + if b'setup key' in body: + secret=re.search(rb'
    ([A-Z2-7]+)
    ',body).group(1).decode() + code=self.totp(secret) + status,body,_=self.request(data={'action':'security','csrf_token':self.csrf(body),'current_password':password,'mfa_code':code}) + if b'Save your recovery codes' not in body:raise AssertionError(body[:1000]) + recovery=re.findall(rb'\b[a-f0-9]{32}\b',body) + self.recovery=[c.decode() for c in recovery] + status,body,_=self.request() + else: + code=self.fixture('mfaCode',email)['code'] + status,body,_=self.request(data={'action':'security','csrf_token':self.csrf(body),'current_password':password,'mfa_code':code}) + if status!=200:raise AssertionError('MFA failed: '+str(status)) self.token=self.csrf(body) + @staticmethod + def totp(secret, at=None): + import base64,hashlib,hmac,struct,time + secret=base64.b32decode(secret+'='*((8-len(secret)%8)%8)) + digest=hmac.new(secret,struct.pack('>Q',int((time.time() if at is None else at)//30)),hashlib.sha1).digest() + offset=digest[-1]&15 + return str((int.from_bytes(digest[offset:offset+4],'big')&0x7fffffff)%1000000).zfill(6) def post(self,action,**values): return self.request(data={'action':action,'csrf_token':self.token,**values},ajax=True) def logout(self):self.post('signout') diff --git a/tests/auth_http.py b/tests/auth_http.py index 1b7de31..38b7b04 100644 --- a/tests/auth_http.py +++ b/tests/auth_http.py @@ -80,7 +80,7 @@ try: check(request(data={'action[]': 'bad'})[0] == 400, 'Array-shaped request fields are rejected') status, html, _ = request('/?Xaction=signup') check(status == 200 and 'name="user_first_name"' in html, 'Signup is reachable before login') - fields = {'action': 'SignUp.createAccount', 'csrf_token': csrf(html), 'user_first_name': 'HTTP', 'user_last_name': 'Tester', 'user_email': 'http@example.test', 'user_name': 'httpuser', 'user_password': 'HTTP long password!', 'user_password_confirm': 'HTTP long password!', 'user_role': 'Administrator'} + fields = {'action': 'SignUp.createAccount', 'csrf_token': csrf(html), 'user_first_name': 'HTTP', 'user_last_name': 'Tester', 'user_email': 'http@example.test', 'user_name': 'httpuser', 'user_password': 'HTTP long password!', 'user_password_confirm': 'HTTP long password!', 'user_role': 'Administrator','club_name':'HTTP signup club'} status, html, _ = request(data=fields) check(status == 200 and 'Your account has been created' in html, 'Signup form creates an account and redirects') status, html, _ = request() @@ -89,7 +89,7 @@ try: status, html, _ = request(data={'action': 'SignIn.login', 'csrf_token': csrf(html), 'user_email': 'http@example.test', 'user_password': 'HTTP long password!'}) check(status == 200 and 'name="csrf-token"' in html, 'Email/password form signs in and reaches the authenticated shell') token = csrf(html) - check(request(data={'action': 'Users.editUser', 'step': 'update', 'csrf_token': token, 'user_serial': '1', 'user_role': 'Administrator'})[0] == 403, 'Regular users cannot edit account privileges') + check(request(data={'action': 'Users.editUser', 'step': 'update', 'csrf_token': token, 'user_serial': '1', 'user_role': 'Administrator','club_name':'HTTP signup club'})[0] == 403, 'Regular users cannot edit account privileges') check(request(data={'action': 'RosterReports.csv', 'club_serial': '1', 'csrf_token': token})[0] == 403, 'Regular users cannot invoke administrative report actions') check(request(data={'action': 'Base.executeSQL', 'csrf_token': token})[0] == 404, 'Arbitrary helper methods cannot be dispatched') check(request(data={'action': 'signout'})[0] == 403, 'Logout rejects missing CSRF token') diff --git a/tests/backup_runner.py b/tests/backup_runner.py new file mode 100644 index 0000000..4d8b3c3 --- /dev/null +++ b/tests/backup_runner.py @@ -0,0 +1,5 @@ +import json,os,subprocess +from pathlib import Path +root=Path(__file__).resolve().parents[1] +php=json.loads(os.environ.get('PHP_TEST_COMMAND','["php"]')) +subprocess.run(php+['-d','memory_limit=16M','tests/backup_validation.php'],cwd=root,check=True) diff --git a/tests/backup_validation.php b/tests/backup_validation.php new file mode 100644 index 0000000..30acd69 --- /dev/null +++ b/tests/backup_validation.php @@ -0,0 +1,19 @@ +errors.push(error.message)); await page.exposeFunction('recordCspViolation',message=>errors.push(message));await page.addInitScript(()=>document.addEventListener('securitypolicyviolation',event=>window.recordCspViolation('CSP: '+event.violatedDirective+' '+event.blockedURI))); const pass=message=>{checks.push(message);console.log('PASS: '+message);}; + const openClubModal=async step=>{await page.locator('[data-club-step="'+step+'"]').first().click();await page.locator('.club-action-modal.show').waitFor();}; const submit=async data=>{await Promise.all([page.waitForNavigation({waitUntil:'load'}),page.evaluate(data=>formSubmit(data),data)]);await page.waitForFunction(()=>typeof formSubmit==='function');await page.waitForLoadState('networkidle');}; try{ await page.goto(process.env.HCR_TEST_URL+'/main.php'); - await page.locator('#user_email').fill('admin@example.test');await page.locator('#user_password').fill('Admin test password 123!');await Promise.all([page.waitForNavigation({waitUntil:'load'}),page.locator('#login button[type="submit"]').click()]);await page.waitForFunction(()=>typeof formSubmit==='function'); + await page.locator('#user_email').fill('admin@example.test');await page.locator('#user_password').fill('Admin test password 123!');await Promise.all([page.waitForNavigation({waitUntil:'load'}),page.locator('#login button[type="submit"]').click()]);await require('./browser_mfa')(page,'Admin test password 123!');await page.waitForFunction(()=>typeof formSubmit==='function'); pass('Browser login loads the application shell without script errors'); const safe=await page.evaluate(()=>{ const original=HTMLFormElement.prototype.submit;HTMLFormElement.prototype.submit=function(){}; @@ -32,18 +33,59 @@ const fs=require('node:fs/promises'); await page.route('**/*',failUsage);await page.locator('.btnDelete').click();await page.getByText('Deliberate usage-check failure',{exact:true}).waitFor();assert(!await page.locator('#confirm-dialog').isVisible());pass('A failed deletion check shows an error and does not open confirmation');await page.unroute('**/*',failUsage); await page.locator('.btnDelete').click();await page.locator('#confirm-dialog').waitFor({state:'visible'});await page.locator('#confirm-dialog .btnConfirmDialogConfirm').click();await page.locator('.setupUsers').waitFor();assert(await page.locator('tr.user-row').filter({hasText:'browser_tester'}).count()===0);pass('Deleting an unused account succeeds through the browser'); await submit({action:'Dropdowns.setupDropdowntypes'});await page.locator('.setupDropdowntypes').waitFor();await page.locator('.btnAdd').click();await page.locator('#addDropdowntype').waitFor();await page.locator('#dropdowntype_name').fill('browser_type');await page.locator('#dropdowntype_title').fill('Browser type');await page.locator('.btnSave').click();await page.locator('.setupDropdowntypes').waitFor();pass('Dropdown type form works with restricted usage metadata'); - await submit({action:'Alerts.addAlert'});await page.locator('.ck-editor').waitFor();pass('Alert editor initializes with updated jQuery and the security policy'); - await submit({action:'Popovers.addPopover'});await page.locator('.ck-editor').waitFor();pass('Popover editor initializes with updated jQuery and the security policy'); - await page.goto(process.env.HCR_TEST_URL+'/main.php?Xaction=Roster.workspace'); + const richHtml='

    Legacy bold italic underline link font

    • Bullet
    Cell
    '; + for (const kind of ['Alert','Popover']) { + const isAlert=kind==='Alert',field=isAlert?'alert_message':'popover_text',prefix=isAlert?'alert':'popover',controller=kind+'s'; + await page.evaluate(({kind,controller})=>{const key=document.querySelector('#APPLICATION_MNEMONIC').value,state=JSON.parse(sessionStorage.getItem(key)||'{}');state['add'+kind]=state['edit'+kind]=controller+'.setup'+kind+'s';sessionStorage.setItem(key,JSON.stringify(state));},{kind,controller}); + await submit({action:controller+'.add'+kind}); + await page.waitForFunction(field=>!!document.getElementById(field).hcrEditor,field); + assert(await page.locator('.btnSave').isEnabled());pass(kind+' editor initializes locally under the security policy'); + await page.evaluate(({field,richHtml,kind,controller})=>{ + document.getElementById(field).hcrEditor.$.html.set(richHtml); + const key=document.querySelector('#APPLICATION_MNEMONIC').value,state=JSON.parse(sessionStorage.getItem(key)||'{}');state['add'+kind]=controller+'.setup'+kind+'s';sessionStorage.setItem(key,JSON.stringify(state)); + },{field,richHtml,kind,controller}); + await page.locator('#'+prefix+'_title').fill('Browser rich '+kind); + if(isAlert){ + await page.evaluate(()=>{$('#alert_starts_date').datepicker('update','2026-01-01');$('#alert_expires_date').datepicker('update','2027-12-31');$('#alert_starts_time').inputmask('setvalue','00:00');$('#alert_expires_time').inputmask('setvalue','23:59');}); + }else await page.locator('#popover_name').fill('browser_rich_popover'); + await page.locator('.btnSave').click();await page.locator('.setup'+kind+'s').waitFor(); + const richRow=page.locator('tr.'+prefix+'-row').filter({hasText:isAlert?'Browser rich Alert':'browser_rich_popover'}); + const serial=await richRow.getAttribute('data-'+prefix+'-serial');await richRow.click(); + await page.waitForFunction(field=>!!document.getElementById(field)?.hcrEditor,field); + const content=await page.evaluate(field=>document.getElementById(field).hcrEditor.$.html.get(),field); + assert.match(content,/Legacy bold<\/strong>/);assert.match(content,/italic<\/em>/);assert.match(content,/underline<\/u>/);assert.match(content,/Cell!!document.getElementById(field)?.hcrEditor,field); + assert((await page.locator('.sun-editor [contenteditable=true]').first().innerText()).includes('Browser edit')); + pass(kind+' edits made in the visible editor are persisted'); + } + await submit({action:'Popovers.addPopover'});await page.waitForFunction(()=>!!document.querySelector('#popover_text').hcrEditor); + const cleaned=await page.evaluate(()=>{const editor=document.querySelector('#popover_text').hcrEditor;editor.$.html.set('

    Safelink

    ');return editor.$.html.get();}); + assert(!/{const transfer=new DataTransfer();transfer.setData('text/html','

    Pasted formatting

    ');transfer.setData('text/plain','Pasted formatting');document.querySelector('.sun-editor [contenteditable=true]').dispatchEvent(new ClipboardEvent('paste',{clipboardData:transfer,bubbles:true,cancelable:true}));}); + await page.waitForFunction(()=>document.querySelector('#popover_text').hcrEditor.$.html.get().includes('Pasted formatting'));pass('Pasting formatted HTML retains bold text'); + await page.route('**/js/suneditor-3.3.3.min.js',route=>route.abort());await submit({action:'Alerts.addAlert'}); + await page.getByText('The text editor could not load. Reload this page before saving.',{exact:true}).waitFor();assert(await page.locator('.btnSave').isDisabled());pass('Editor load failure is visible and saving stays disabled');await page.unroute('**/js/suneditor-3.3.3.min.js'); + await page.goto(process.env.HCR_TEST_URL+'/main.php?Xaction=Roster.createClub'); let form=page.locator('form').filter({has:page.getByRole('button',{name:'Create club',exact:true})});await form.getByLabel('Club name',{exact:true}).fill('Browser Club');await form.getByRole('button',{name:'Create club',exact:true}).click();await page.getByRole('heading',{name:'Browser Club',exact:true}).waitFor();pass('Club creation works in the browser'); - form=page.locator('form').filter({has:page.getByRole('button',{name:'Add member',exact:true})});await form.getByLabel('Username or email').fill('testadmin');await form.getByRole('button',{name:'Add member',exact:true}).click();await page.getByRole('cell',{name:'Test Administrator',exact:true}).waitFor();pass('Membership assignment works in the browser'); - form=page.locator('form').filter({has:page.getByRole('button',{name:'Add season',exact:true})});await form.getByLabel('Season name').fill('Browser Season');await form.getByLabel('Starts on').fill('2026-01-01');await form.getByLabel('Ends on').fill('2026-12-31');await form.getByRole('button',{name:'Add season',exact:true}).click();await page.getByText('Browser Season (2026-01-01 to 2026-12-31)',{exact:true}).waitFor();pass('Season creation works in the browser'); - form=page.locator('form').filter({has:page.getByRole('button',{name:'Save dues',exact:true})});await form.getByLabel('Dues (USD)').fill('10.00');await form.getByRole('button',{name:'Save dues',exact:true}).click();await page.getByRole('button',{name:'Record payment',exact:true}).waitFor();pass('Dues entry works in the browser'); - form=page.locator('form').filter({has:page.getByRole('button',{name:'Record payment',exact:true})});await form.getByLabel('Payment (USD)').fill('5.00');await form.getByRole('button',{name:'Record payment',exact:true}).click();await page.getByRole('cell',{name:'$5.00',exact:true}).first().waitFor();pass('Recording a payment updates the displayed balance'); - await page.getByText('Correct dues',{exact:true}).click(); + assert.equal(await page.locator('.clubSummary input:visible,.clubSummary select:visible').count(),0);pass('Club summary hides all editing fields until an action is opened'); + await openClubModal('club');await page.locator('.club-action-modal.show').getByLabel('Club name',{exact:true}).fill('Unsaved name');await page.locator('.club-action-modal.show').getByRole('button',{name:'Cancel',exact:true}).click();await page.locator('.club-action-modal.show').waitFor({state:'hidden'});assert.equal(await page.locator('.clubSummary h1').textContent(),'Browser Club');pass('Canceling a club edit leaves the club unchanged'); + await openClubModal('club');await page.locator('.club-action-modal.show').getByLabel('Club name',{exact:true}).fill('Browser Club');await Promise.all([page.waitForNavigation(),page.locator('.club-action-modal.show').getByRole('button',{name:'Save club',exact:true}).click()]);assert.equal(await page.locator('.clubSummary h1').textContent(),'Browser Club');pass('Club edits save through their modal and return to the summary'); + await openClubModal('member');form=page.locator('form').filter({has:page.getByRole('button',{name:'Add member',exact:true})});await form.getByLabel('Username or email').fill('testadmin');await form.getByRole('button',{name:'Add member',exact:true}).click();await page.getByRole('cell',{name:'Test Administrator',exact:true}).waitFor();pass('Membership assignment works in the browser'); + await openClubModal('season');form=page.locator('form').filter({has:page.getByRole('button',{name:'Add season',exact:true})});await form.getByLabel('Season name').fill('Browser Season');await form.getByLabel('Starts on').fill('2026-01-01');await form.getByLabel('Ends on').fill('2025-12-31');await form.getByRole('button',{name:'Add season',exact:true}).click();await page.locator('.club-action-modal.show .club-modal-error:not([hidden])').waitFor();assert.equal(await form.getByLabel('Season name').inputValue(),'Browser Season');pass('Server validation stays inside the modal and preserves entered values');await form.getByLabel('Ends on').fill('2026-12-31');await form.getByRole('button',{name:'Add season',exact:true}).click();await page.getByText('Browser Season (2026-01-01 to 2026-12-31)',{exact:true}).waitFor();pass('Season creation works in the browser'); + await openClubModal('charge');form=page.locator('form').filter({has:page.getByRole('button',{name:'Save dues',exact:true})});await form.getByLabel('Dues (USD)').fill('10.00');await form.getByRole('button',{name:'Save dues',exact:true}).click();await page.getByRole('button',{name:'Record payment',exact:true}).waitFor();pass('Dues entry works in the browser'); + await openClubModal('payment');form=page.locator('form').filter({has:page.getByRole('button',{name:'Record payment',exact:true})});await form.getByLabel('Payment (USD)').fill('5.00');await form.getByRole('button',{name:'Record payment',exact:true}).click();await page.getByRole('cell',{name:'$5.00',exact:true}).first().waitFor();pass('Recording a payment updates the displayed balance'); + await openClubModal('adjust'); form=page.locator('form').filter({has:page.getByRole('button',{name:'Save correction',exact:true})});await form.getByLabel('Corrected total (USD)').fill('8.00');await form.getByLabel('Reason',{exact:true}).fill('Correct season rate');await form.getByRole('button',{name:'Save correction',exact:true}).click();await page.getByRole('cell',{name:'$8.00',exact:true}).waitFor();pass('Dues correction updates the balance and preserves history in the browser'); - await page.getByText('Reverse incorrect payment',{exact:true}).click(); + await openClubModal('reverse'); form=page.locator('form').filter({has:page.getByRole('button',{name:'Confirm reversal',exact:true})});await form.getByLabel('Reversal reason').fill('Wrong receipt');await form.getByRole('button',{name:'Confirm reversal',exact:true}).click();await page.getByText('Reversed: Wrong receipt',{exact:false}).waitFor();pass('Payment reversal is recorded visibly without deleting the original payment'); + await openClubModal('invite');await page.locator('.club-action-modal.show').getByLabel('Invitation email',{exact:true}).fill('revocation@example.test');await Promise.all([page.waitForNavigation(),page.locator('.club-action-modal.show').getByRole('button',{name:'Send club invitation',exact:true}).click()]);const invitation=page.locator('li').filter({hasText:'revocation@example.test'});await invitation.locator('[data-club-step=revokeInvitation]').click();await page.locator('.club-action-modal.show').getByRole('button',{name:'Cancel',exact:true}).click();await page.locator('.club-action-modal.show').waitFor({state:'hidden'});assert((await invitation.textContent()).includes('pending'));await invitation.locator('[data-club-step=revokeInvitation]').click();await Promise.all([page.waitForNavigation(),page.locator('.club-action-modal.show').getByRole('button',{name:'Revoke invitation',exact:true}).click()]);assert((await page.locator('li').filter({hasText:'revocation@example.test'}).textContent()).includes('revoked'));pass('Invitation revocation requires modal confirmation and Cancel preserves the invitation'); const ledgerDownload=page.waitForEvent('download');await page.getByRole('button',{name:'Export financial history (CSV)',exact:true}).click();assert.equal((await ledgerDownload).suggestedFilename(),'club-financial-history.csv');pass('Financial history can be downloaded from the browser'); await page.screenshot({path:path.join(__dirname,'.local','roster.png'),fullPage:true}); await submit({action:'Reports.selectReport'});await page.getByRole('heading',{name:'Roster reports'}).waitFor();const downloadEvent=page.waitForEvent('download');await page.getByRole('button',{name:'Download CSV'}).click();const download=await downloadEvent;assert.equal(download.suggestedFilename(),'club-roster.csv');pass('Report catalog downloads the roster CSV in the browser'); diff --git a/tests/browser_mfa.js b/tests/browser_mfa.js new file mode 100644 index 0000000..4ce4a00 --- /dev/null +++ b/tests/browser_mfa.js @@ -0,0 +1,17 @@ +const crypto=require('node:crypto'); +function totp(secret){ + const alphabet='ABCDEFGHIJKLMNOPQRSTUVWXYZ234567';let bits='';for(const c of secret)bits+=alphabet.indexOf(c).toString(2).padStart(5,'0'); + const bytes=[];for(let i=0;i+8<=bits.length;i+=8)bytes.push(parseInt(bits.slice(i,i+8),2)); + const counter=Buffer.alloc(8);counter.writeBigUInt64BE(BigInt(Math.floor(Date.now()/30000))); + const digest=crypto.createHmac('sha1',Buffer.from(bytes)).update(counter).digest(),offset=digest[19]&15; + return String((digest.readUInt32BE(offset)&0x7fffffff)%1000000).padStart(6,'0'); +} +module.exports=async function completeMfa(page,password){ + if(!await page.getByRole('heading',{name:'Account security',exact:true}).count())return; + const secret=(await page.locator('pre').textContent()).trim(); + await page.locator('[name=current_password]').fill(password);await page.locator('[name=mfa_code]').fill(totp(secret)); + await Promise.all([page.waitForNavigation(),page.getByRole('button',{name:'Verify',exact:true}).click()]); + await page.getByRole('heading',{name:'Save your recovery codes'}).waitFor(); + await Promise.all([page.waitForNavigation(),page.getByRole('link',{name:'I have saved my recovery codes'}).click()]); +}; +module.exports.totp=totp; diff --git a/tests/browser_runner.py b/tests/browser_runner.py index 6135485..e9f147e 100644 --- a/tests/browser_runner.py +++ b/tests/browser_runner.py @@ -4,7 +4,7 @@ from application_harness import Application,ROOT app=Application() try: - env=os.environ.copy();env['HCR_TEST_URL']=app.base + env=app.env.copy();env['HCR_TEST_URL']=app.base node=env.get('NODE_TEST_COMMAND','node') result=subprocess.run([node,'tests/browser.js'],cwd=ROOT,env=env) if result.returncode:raise SystemExit(result.returncode) diff --git a/tests/capacity_service.php b/tests/capacity_service.php new file mode 100644 index 0000000..8720546 --- /dev/null +++ b/tests/capacity_service.php @@ -0,0 +1,83 @@ +connect();$ids=json_decode(getenv('HCR_TENANT_IDS'),true,512,JSON_THROW_ON_ERROR);$checks=0; +function capacityCheck(bool $ok,string $message):void{global $checks;if(!$ok)throw new RuntimeException($message);$checks++;echo "PASS: $message\n";} +function capacityDenied(callable $work,int $status,string $message):void{try{$work();}catch(AppException $e){capacityCheck($e->status===$status,$message);return;}throw new RuntimeException($message.' was allowed');} +function capacityActor(int $id):void{$_SESSION=[Base::USER_SERIAL=>$id];} +$roster=new RosterService();$tickets=new ClubTickets();$resources=new ClubResources(); +capacityActor(1); +$hash=password_hash('Capacity test password!',PASSWORD_DEFAULT); +$user=$db->prepare("INSERT INTO users(user_name,user_email,user_first_name,user_last_name,user_password_hash,user_email_verified_at,user_role) VALUES(?,?,?, ?,?,UTC_TIMESTAMP(),'User')"); +$membership=$db->prepare("INSERT INTO club_memberships(club_serial,user_serial,joined_on) VALUES(?,?,'2026-01-01')"); +$season=$db->prepare("INSERT INTO club_seasons(club_serial,season_name,starts_on,ends_on) VALUES(?,?,'2026-01-01','2026-12-31')"); +$due=$db->prepare('INSERT INTO club_dues(club_serial,membership_serial,season_serial,amount_cents,recorded_by) VALUES(?,?,?,?,1)'); +$payment=$db->prepare("INSERT INTO club_payments(due_serial,amount_cents,paid_on,request_key,recorded_by) VALUES(?,1,'2026-01-01',?,1)"); +$adjustment=$db->prepare("INSERT INTO club_due_adjustments(due_serial,amount_cents,corrected_amount_cents,reason,recorded_by,request_key) VALUES(?,1,101,'test',1,?)"); +$invite=$db->prepare("INSERT INTO club_invitations(club_serial,invite_email,invited_by,expires_at,sent_at) VALUES(?,?,1,DATE_ADD(UTC_TIMESTAMP(),INTERVAL 1 DAY),UTC_TIMESTAMP())"); +for($i=1;$i<=76;$i++){ + $user->execute(['capacity'.$i,'capacity'.$i.'@example.test','Capacity','Member '.sprintf('%03d',$i),$hash]);$uid=(int)$db->lastInsertId();$membership->execute([$ids['clubA'],$uid]);$mid=(int)$db->lastInsertId(); + $season->execute([$ids['clubA'],'Capacity season '.sprintf('%03d',$i)]);$seasonid=(int)$db->lastInsertId(); + $due->execute([$ids['clubA'],$mid,$seasonid,100]);$did=(int)$db->lastInsertId();$payment->execute([$did,bin2hex(random_bytes(32))]);$adjustment->execute([$did,bin2hex(random_bytes(32))]); + $invite->execute([$ids['clubA'],'pending'.$i.'@example.test']); +} +$ticket=$db->prepare('INSERT INTO club_tickets(club_serial,user_serial,subject) VALUES(?,?,?)');$ticket->execute([$ids['clubA'],$ids['membera'],'Long conversation']);$tid=(int)$db->lastInsertId(); +$message=$db->prepare('INSERT INTO club_ticket_messages(ticket_serial,author_serial,message_text) VALUES(?,?,?)');for($i=1;$i<=76;$i++)$message->execute([$tid,$ids['membera'],'Message '.$i]); +capacityActor($ids['admina2']); +foreach(['members','seasons','dues'] as $kind){ + $rows=$roster->$kind($ids['clubA'],1);capacityCheck(count($rows)===25,"$kind page is bounded at 25 rows"); + $last=$roster->$kind($ids['clubA'],9999);capacityCheck(count($last)>0&&count($last)<=25&&BoundedList::$pages[$kind]['page']===BoundedList::$pages[$kind]['pages'],"$kind clamps high page to reachable final records"); +} +$history=(new LedgerService())->history($ids['clubA'],1,1);capacityCheck(count($history['payments'])===25&&count($history['adjustments'])===25,'Payment and correction histories have independent bounded pages'); +capacityCheck(count((new ClubInvitations())->forClub($ids['clubA'],1))===25,'Administrator invitation list is bounded'); +capacityCheck(count($tickets->messages($ids['clubA'],$tid,1))===25&&count($tickets->messages($ids['clubA'],$tid,4))===1,'Long conversation exposes all replies across bounded pages'); +capacityDenied(fn()=>$roster->members($ids['clubB'],1),403,'Paging cannot access another tenant'); +capacityActor($ids['membera']);capacityCheck(count($roster->members($ids['clubA'],1))===1&&BoundedList::$pages['members']['count']===1,'Member roster rows and total remain personal'); +capacityCheck(count($roster->dues($ids['clubA'],1))===0&&BoundedList::$pages['dues']['count']===0,'Member dues total excludes other members'); +capacityActor($ids['adminb']);capacityDenied(fn()=>$tickets->messages($ids['clubA'],$tid,1),403,'Conversation paging cannot expose foreign replies'); +capacityActor(1);putenv('HCR_EXPORT_MAX_ROWS=30'); +capacityDenied(fn()=>BoundedList::exportGuard($db,'SELECT COUNT(*) FROM club_memberships WHERE club_serial=?',[$ids['clubA']]),422,'Oversized export is rejected before loading its rows'); +BoundedList::$exporting=true;capacityDenied(fn()=>$roster->members($ids['clubA']),422,'Export query itself remains bounded if preflight count is bypassed');BoundedList::$exporting=false; +$_GET=['Xaction'=>'Roster.workspace','club_serial'=>(string)$ids['clubA'],'dues_page'=>'2'];$roster->members($ids['clubA'],2);$nav=BoundedList::navigation('members');capacityCheck(str_contains($nav,'members_page=3')&&str_contains($nav,'dues_page=2'),'Page navigation preserves independent list context'); +$_GET['members_page']='-1';capacityDenied(fn()=>BoundedList::page('members'),422,'Invalid list page is rejected');$_GET=[]; +foreach(['email','ticket','reply','export'] as $resource){ + putenv('HCR_CLUB_'.strtoupper($resource).'_HOURLY=2');capacityActor($ids['admina']);$resources->consume($ids['clubA'],$resource);capacityActor($ids['admina2']);$resources->consume($ids['clubA'],$resource); + capacityDenied(fn()=>$resources->consume($ids['clubA'],$resource),429,"$resource budget is shared across administrators"); + capacityActor($ids['adminb']);$resources->consume($ids['clubB'],$resource);capacityCheck(true,"$resource budget is independent for another tenant"); + $stmt=$db->prepare('UPDATE club_resource_usage SET window_started=DATE_SUB(UTC_TIMESTAMP(),INTERVAL 2 HOUR) WHERE club_serial=? AND resource_name=?');$stmt->execute([$ids['clubA'],$resource]); + capacityActor($ids['admina2']);$resources->consume($ids['clubA'],$resource);capacityCheck(true,"$resource budget resets after its window"); +} +capacityActor($ids['memberb']);capacityDenied(fn()=>$resources->consume($ids['clubA'],'email'),403,'Unauthorized resource request is denied before budget consumption'); +putenv('HCR_CLUB_TICKET_HOURLY=invalid');capacityActor($ids['membera']);try{$resources->consume($ids['clubA'],'ticket');throw new LogicException('Invalid limit accepted');}catch(RuntimeException $e){capacityCheck(str_contains($e->getMessage(),'Invalid club'),'Invalid budget configuration fails closed');} +putenv('HCR_CLUB_TICKET_HOURLY');putenv('HCR_EXPORT_MAX_ROWS'); +// Idempotent migration must preserve both factors and counters. +$before=$db->query('SELECT * FROM club_resource_usage ORDER BY club_serial,resource_name')->fetchAll();require __DIR__.'/../bin/migrate-security-capacity.php';capacityCheck($before===$db->query('SELECT * FROM club_resource_usage ORDER BY club_serial,resource_name')->fetchAll(),'Security-capacity migration is repeatable without resetting budgets'); +// Exercise the real factor service, including rollback and password reset. +capacityActor(1);$_SESSION['auth_version']=(int)$db->query('SELECT user_auth_version FROM users WHERE user_serial=1')->fetchColumn(); +$mfa=new MfaService();$secret=OTPHP\TOTP::generate(new MfaClock())->getSecret(); +$stmt=$db->prepare('INSERT INTO user_mfa(user_serial,secret_cipher) VALUES(1,?)');$stmt->execute([$mfa->sealSecret($secret,1)]); +$code=OTPHP\TOTP::createFromSecret($secret,new MfaClock())->now(); +capacityCheck($mfa->verify(1,$code,'Admin test password 123!'),'A fresh authenticator code verifies through the maintained library'); +capacityCheck(!$mfa->verify(1,$code,'Admin test password 123!'),'The same authenticator time step cannot be reused'); +$recovery=bin2hex(random_bytes(16));$stmt=$db->prepare('INSERT INTO mfa_recovery(user_serial,code_hash) VALUES(1,?)');$stmt->execute([hash('sha256',$recovery)]); +$db->exec("CREATE TRIGGER reject_mfa_audit BEFORE INSERT ON journal FOR EACH ROW SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='Test audit failure'"); +try{$mfa->verify(1,$recovery,'Admin test password 123!');throw new LogicException('Audit failure accepted');}catch(PDOException $e){capacityCheck((int)$db->query('SELECT COUNT(*) FROM mfa_recovery WHERE user_serial=1')->fetchColumn()===1,'Failed mandatory audit rolls back recovery-code consumption');} +$db->exec('DROP TRIGGER reject_mfa_audit');capacityCheck($mfa->verify(1,$recovery,'Admin test password 123!'),'Recovery code still works after a rolled-back attempt'); +capacityCheck(!$mfa->verify(1,$recovery,'Admin test password 123!'),'Recovery code is single use after commit'); +$cipher=$db->query('SELECT secret_cipher FROM user_mfa WHERE user_serial=1')->fetchColumn(); +$stmt=$db->prepare('INSERT INTO user_mfa(user_serial,secret_cipher) VALUES(?,?)');$stmt->execute([$ids['memberb'],$cipher]); +capacityActor($ids['memberb']);$stmt=$db->prepare('SELECT user_auth_version FROM users WHERE user_serial=?');$stmt->execute([$ids['memberb']]);$_SESSION['auth_version']=(int)$stmt->fetchColumn(); +try{$mfa->verify($ids['memberb'],$code,'Tenant test password 123!');throw new LogicException('Copied ciphertext accepted');}catch(RuntimeException $e){capacityCheck(str_contains($e->getMessage(),'unlock'),'Encrypted secret is bound to its owning account');} +class CapacityReset extends AuthService { + public string $token=''; + public function connect():PDO {return $GLOBALS['db'];} + public function getSettings(){return new SimpleXMLElement('https://example.test');} + protected function deliverResetEmail(array $user,string $url):bool{parse_str(parse_url($url,PHP_URL_QUERY),$query);$this->token=$query['token'];return true;} +} +$auth=new CapacityReset();$before=$db->query('SELECT * FROM user_mfa WHERE user_serial=1')->fetch();$auth->requestReset('admin@example.test'); +capacityCheck($auth->resetPassword($auth->token,'Reset preserves MFA 123!','Reset preserves MFA 123!'),'Password reset works for an MFA-enrolled account'); +capacityCheck($before===$db->query('SELECT * FROM user_mfa WHERE user_serial=1')->fetch(),'Password reset preserves the authenticator and replay counter'); +$_SESSION['mfa_user']=1;capacityCheck($auth->login('admin@example.test','Reset preserves MFA 123!')&&!$mfa->verified(1),'A password login clears any earlier MFA verification'); +echo "$checks capacity service checks passed.\n";ob_end_flush(); diff --git a/tests/club_onboarding_http.py b/tests/club_onboarding_http.py new file mode 100644 index 0000000..e849667 --- /dev/null +++ b/tests/club_onboarding_http.py @@ -0,0 +1,55 @@ +"""New-club signup must never grant administration of an existing tenant.""" +from application_harness import Application +app=Application();checks=0 +def check(ok,message): + global checks + assert ok,message + checks+=1;print('PASS:',message) +def signup(name='newowner',email='newowner@example.test',club='New owner club',kind='new_club',**extra): + app.fixture('clearTestAttempts') + _,body,_=app.request('/main.php?Xaction=signup') + return app.request(data={'action':'SignUp.createAccount','csrf_token':app.csrf(body),'user_first_name':'New','user_last_name':'Owner','user_email':email,'user_name':name,'user_password':'New owner password 123!','user_password_confirm':'New owner password 123!','registration_kind':kind,'club_name':club,**extra}) +try: + ids=app.fixture('tenantSeed');before=app.fixture('inspect') + status,body,_=app.request('/main.php?Xaction=signup') + check(status==200 and b'name="club_name"' in body and b'value="new_club"' in body,'Default signup asks for a new club') + status,body,_=signup(club='') + check(b'Enter your new club name' in body and app.fixture('inspect')==before,'Missing club name creates no account or club') + status,body,_=signup(club='X'*129) + check(b'Enter your new club name' in body and app.fixture('inspect')==before,'Server rejects overlong club names without partial records') + status,body,_=signup(kind='account') + check(b'Choose a valid signup option' in body and app.fixture('inspect')==before,'Public signup cannot use the internal account-only mode') + app.fixture('mfaTestAuditFailure','on') + status,body,_=signup() + app.fixture('mfaTestAuditFailure','off') + check(status==500 and app.fixture('inspect')==before,'Audit failure rolls back account, club and administrator membership') + status,body,_=signup(club='Tenant Alpha',user_role='Super System Administrator',club_serial=ids['clubA']) + state=app.fixture('inspect');owner=next(u for u in state['users'] if u['user_name']=='newowner');memberships=[m for m in state['club_memberships'] if m['user_serial']==owner['user_serial']];club=memberships[0]['club_serial'] + check(status==200 and b'Your account has been created' in body,'New-club signup succeeds') + check(owner['user_role']=='User' and owner['user_email_verified_at'] is None,'Signup keeps the global role unprivileged and email unverified') + check(len(memberships)==1 and memberships[0]['membership_role']=='administrator' and club!=ids['clubA'],'Matching an existing club name creates an independent tenant with its own administrator') + before=state;signup() + check(app.fixture('inspect')==before,'Duplicate account submission creates no orphan club') + app.login('newowner@example.test','New owner password 123!') + check(app.request('/main.php?Xaction=Roster.workspace&club_serial='+str(club))[0]==403,'Unverified club owner cannot open the club') + app.fixture('verifyEmail','newowner');app.logout() + # Real login helper enrolls MFA only when the application requires it. + app.login('newowner@example.test','New owner password 123!') + check(bool(app.fixture('mfaState','newowner@example.test')['factor']),'Verified new administrator must enroll an authenticator') + status,body,_=app.request() + check(status==200 and b'class="container-fluid py-3 clubSummary"' in body and b'

    Tenant Alpha

    ' in body,'Verified owner lands directly in the summary-style club page') + check(b'>Create club' not in body and b'Xaction=Roster.createClub' not in body,'Club administrator sees no global club-creation controls') + check(app.request('/main.php?Xaction=Roster.workspace&club_serial='+str(ids['clubA']))[0]==403,'New administrator cannot open the pre-existing club with the same name') + check(app.request('/main.php?Xaction=Roster.createClub')[0]==403,'Dedicated creation page rejects club administrators') + app.logout();before=app.fixture('inspect');status,body,_=signup('notinvited','notinvited@example.test',kind='invited') + check(b'Ask your club administrator' in body and app.fixture('inspect')==before,'Member signup requires a current invitation to the submitted email') + app.fixture('seedTenantInvitation',str(ids['clubA']),'1','newmember@example.test');before=app.fixture('inspect') + status,body,_=signup('newmember','newmember@example.test',kind='invited') + after=app.fixture('inspect');member=next(u for u in after['users'] if u['user_name']=='newmember') + check(status==200 and b'Your account has been created' in body and len(after['clubs'])==len(before['clubs']),'Invited signup creates an account without creating another club') + check(not any(m['user_serial']==member['user_serial'] for m in after['club_memberships']),'Invitation signup does not skip email verification or invitation acceptance') + app.login();status,body,_=app.request('/main.php?Xaction=Roster.createClub') + check(status==200 and b'>Create club' in body,'Super Administrator retains a separate Create club page') + print(checks,'club onboarding HTTP checks passed.') +finally: + app.fixture('mfaTestAuditFailure','off');app.close() diff --git a/tests/concurrency.py b/tests/concurrency.py index 5bc5ac4..8cb2b95 100644 --- a/tests/concurrency.py +++ b/tests/concurrency.py @@ -50,15 +50,27 @@ try: assert all(row['ok'] for row in result),result assert len(app.fixture('inspect')['club_due_adjustments'])==1 print('PASS: Concurrent dues correction retries create only one adjustment.') - response=app.post('Users.addUser',step='add',user_name='second_admin',user_first_name='Second',user_last_name='Administrator',user_email='second@example.test',user_role='Administrator') + response=app.post('Users.addUser',step='add',user_name='second_admin',user_first_name='Second',user_last_name='Administrator',user_email='second@example.test',user_role='Super System Administrator') assert response[0]==200,response[1] - ids=[row['user_serial'] for row in app.fixture('inspect')['users'] if row['user_role']=='Administrator'] + ids=[row['user_serial'] for row in app.fixture('inspect')['users'] if row['user_role']=='Super System Administrator'] result=race('disable',ids) assert sorted(item['ok'] for item in result)==[False,True],result - assert next(item for item in result if not item['ok'])['status']==409,result - assert sum(row['user_role']=='Administrator' and row['user_status']=='active' for row in app.fixture('inspect')['users'])==1 + assert next(item for item in result if not item['ok'])['status'] in [403,409],result + assert sum(row['user_role']=='Super System Administrator' and row['user_status']=='active' for row in app.fixture('inspect')['users'])==1 print('PASS: Concurrent administrator changes cannot disable the final administrator.') - print('5 concurrency scenarios passed.') + tenant=app.fixture('tenantSeed') + invitation=app.fixture('seedTenantInvitation',str(tenant['clubA']),str(tenant['admina']),'invitee@example.test')['invitation'] + result=race('accept',[invitation,invitation],[tenant['invitee']]) + assert sorted(item['ok'] for item in result)==[False,True],result + assert sum(row['user_serial']==tenant['invitee'] and row['club_serial']==tenant['clubA'] for row in app.fixture('inspect')['club_memberships'])==1 + print('PASS: Concurrent invitation acceptance grants exactly one membership.') + # Restore the worker actor after the previous last-super race, for this isolated fixture only. + app.fixture('restoreTestSuper') + result=race('membership',[tenant['clubA_admina'],tenant['clubA_admina2']],[tenant['clubA']]) + assert sorted(item['ok'] for item in result)==[False,True],result + assert sum(row['club_serial']==tenant['clubA'] and row['membership_role']=='administrator' and row['membership_status']=='active' for row in app.fixture('inspect')['club_memberships'])==1 + print('PASS: Concurrent membership changes preserve the last club administrator.') + print('7 concurrency scenarios passed.') finally: for process in workers: if process.poll() is None:process.terminate();process.wait(timeout=10) diff --git a/tests/deployment_tools.py b/tests/deployment_tools.py index fbe4f86..51d895e 100644 --- a/tests/deployment_tools.py +++ b/tests/deployment_tools.py @@ -19,6 +19,7 @@ try: names=archive.namelist();manifest=json.loads(archive.read('release-manifest.json')) check(not any(name.startswith(('.tools/','.git/','tests/','nbproject/')) or name.endswith('settings.local.xml') for name in names),'Release excludes local credentials, backups, Git metadata, and tests') check(all(name in names for name in ['classes/LedgerService.php','classes/EmailVerification.php','bin/migrate-production.php','migrations/003_production.sql','js/jquery-3.7.1.min.js']),'Release includes new classes, migration, and updated jQuery') + check(all(name in names for name in ['classes/MemberSummary.php','classes/ClubFormModals.php','js/club-modals.js','classes/MfaSecurityNotifications.php','classes/MfaSetupQr.php','classes/MfaService.php','classes/MfaClock.php','classes/BoundedList.php','classes/ClubResources.php','bin/migrate-security-capacity.php','migrations/005_security_capacity.sql','classes/DatabaseTransaction.php','js/tickets.js','classes/TenantAccess.php','classes/ClubInvitations.php','classes/ClubTickets.php','bin/migrate-tenants.php','migrations/004_tenants.sql','classes/MaintenanceValidation.php','classes/BackupValidation.php','js/rich-text.js','js/suneditor-3.3.3.min.js','css/suneditor-3.3.3.min.css','THIRD-PARTY-NOTICES.md','browser-dependencies.json']) and 'js/ckeditor.js' not in names,'Release includes replacement editor, license, integrity metadata, and new validators') check(all(hashlib.sha256(archive.read(name)).hexdigest()==digest for name,digest in manifest.items()),'Release manifest verifies every packaged file') binary=os.environ.get('HCR_DUMP_BINARY') or shutil.which('mariadb-dump') if not binary: @@ -33,6 +34,11 @@ try: check(not list(Path(temporary).glob('hcr-connection-*')),'Backup credentials file is removed after completion') result=subprocess.run(PHP+['bin/backup-database.php',str(ROOT/'.tools')],cwd=ROOT,env=env,capture_output=True) check(result.returncode!=0,'Backup tool rejects storage within the application tree') + failed_directory=Path(temporary)/'failed-job';failed_directory.mkdir() + env['HCR_DUMP_BINARY']=PHP[0] # A real executable that rejects dump arguments. + result=subprocess.run(PHP+['bin/backup-database.php',str(failed_directory)],cwd=ROOT,env=env,capture_output=True) + check(result.returncode!=0,'Dump process failure produces a failing job exit status') + check(not list(failed_directory.iterdir()),'Failed backup leaves no credentials, partial dump, or success metadata') for path in ['/.tools/backups/probe.sql','/migrations/003_production.sql','/bin/check-health.php','/xml/settings.xml','/release-manifest.json']: check(app.request(path)[0] in [403,404],'Development router denies '+path) finally:app.close() diff --git a/tests/http_fixture.php b/tests/http_fixture.php index 8eec1bb..9d3c94f 100644 --- a/tests/http_fixture.php +++ b/tests/http_fixture.php @@ -4,6 +4,7 @@ require_once __DIR__ . '/../classes/Base.php'; $dsn = getenv('HCR_TEST_DSN'); if (!$dsn) throw new RuntimeException('Set HCR_TEST_DSN to an isolated test server.'); $db = new PDO($dsn, getenv('HCR_TEST_USER') ?: 'root', getenv('HCR_TEST_PASSWORD') ?: '', [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]); +$db->exec('SET NAMES utf8mb4'); $action = $argv[1] ?? ''; $name = $argv[2] ?? ('hcr_http_test_' . bin2hex(random_bytes(6))); if (!preg_match('/\Ahcr_http_test_[a-f0-9]{12}\z/', $name)) throw new RuntimeException('Only generated test databases may be used.'); @@ -22,11 +23,60 @@ if ($action === 'create') { putenv('HCR_DB_NAME=' . $name); require __DIR__ . '/../bin/migrate-auth.php'; require __DIR__.'/../bin/migrate-production.php'; + putenv('HCR_SUPER_ADMIN_EMAIL=admin@example.test'); + require __DIR__.'/../bin/migrate-tenants.php'; + putenv('HCR_SUPER_ADMIN_EMAIL'); + require __DIR__.'/../bin/migrate-security-capacity.php'; // Idempotent migration is verified separately by the HTTP test runner. echo json_encode(['database' => $name]); exit; } $db->exec("USE `{$name}`"); +if($action==='memberSummarySeed'){ + $a=(int)$argv[3];$b=(int)$argv[4];$own=(int)$argv[5];$neighbor=(int)$argv[6];$foreign=(int)$argv[7];$first=0; + $season=$db->prepare('INSERT INTO club_seasons(club_serial,season_name,starts_on,ends_on) VALUES(?,?,?,?)'); + $due=$db->prepare('INSERT INTO club_dues(club_serial,membership_serial,season_serial,amount_cents,recorded_by) VALUES(?,?,?,?,1)'); + for($i=1;$i<=31;$i++){$season->execute([$a,'Member season '.sprintf('%02d',$i),'2026-01-01','2026-12-31']);$due->execute([$a,$own,(int)$db->lastInsertId(),10000]);if(!$first)$first=(int)$db->lastInsertId();} + $pay=$db->prepare("INSERT INTO club_payments(due_serial,amount_cents,paid_on,request_key,payment_method,payment_reference,recorded_by) VALUES(?,100,'2026-01-01',?,'cash',?,1)"); + for($i=1;$i<=32;$i++)$pay->execute([$first,bin2hex(random_bytes(32)),'OWN-RECEIPT-'.sprintf('%02d',$i)]); + $reversed=(int)$db->lastInsertId(); + $stmt=$db->prepare('INSERT INTO club_payment_reversals(payment_serial,reason,request_key,recorded_by) VALUES(?,?,?,1)');$stmt->execute([$reversed,'Own reversed receipt',bin2hex(random_bytes(32))]); + $stmt=$db->prepare('INSERT INTO club_due_adjustments(due_serial,amount_cents,corrected_amount_cents,reason,request_key,recorded_by) VALUES(?,5000,15000,?,?,1)');$stmt->execute([$first,'Own correction ',bin2hex(random_bytes(32))]); + foreach([[$a,$neighbor,'NEIGHBOR-PRIVATE'],[$b,$foreign,'FOREIGN-PRIVATE']] as [$club,$membership,$marker]){$season->execute([$club,'Additional season '.$membership,'2026-01-01','2026-12-31']);$due->execute([$club,$membership,(int)$db->lastInsertId(),99999]);$pay->execute([(int)$db->lastInsertId(),bin2hex(random_bytes(32)),$marker]);} + $season->execute([$a,'Available new season','2026-01-01','2026-12-31']); + echo '{}';exit; +} +if($action==='sessionAge'){ + $id=$argv[3]??'';if(!preg_match('/\A[a-zA-Z0-9,-]{16,128}\z/',$id))throw new RuntimeException('Invalid test session.'); + session_name('HUNTINGCLUBROSTER');session_id($id);session_start(); + if(!isset($_SESSION[Base::USER_SERIAL]))throw new RuntimeException('Missing test session.'); + foreach(['authenticated_at','last_activity','recent_auth'] as $index=>$field){$age=$argv[4+$index]??'';if($age!=='')$_SESSION[$field]=time()-(int)$age;} + session_write_close();echo '{}';exit; +} +if($action==='clearTestAttempts'){$db->exec('DELETE FROM auth_attempts');echo '{}';exit;} +if($action==='mfaTestSession'){ + $id=$argv[3]??'';if(!preg_match('/\A[a-zA-Z0-9,-]{16,128}\z/',$id))throw new RuntimeException('Invalid test session.'); + session_name('HUNTINGCLUBROSTER');session_id($id);session_start(); + $user=(int)($_SESSION[Base::USER_SERIAL]??0);$stmt=$db->prepare('SELECT 1 FROM users WHERE user_serial=?');$stmt->execute([$user]);if(!$stmt->fetchColumn())throw new RuntimeException('Owned test account required.'); + if(($argv[4]??'')==='expire'&&isset($_SESSION['mfa_replacement']))$_SESSION['mfa_replacement']['expires']=time()-1; + $state=$_SESSION;session_write_close();echo json_encode($state);exit; +} +if($action==='mfaTestAuditFailure'){ + if(($argv[3]??'')==='on')$db->exec("CREATE TRIGGER reject_mfa_test_audit BEFORE INSERT ON journal FOR EACH ROW SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='Test audit failure'"); + else $db->exec('DROP TRIGGER IF EXISTS reject_mfa_test_audit');echo '{}';exit; +} +if($action==='mfaResetToken'){ + $token=bin2hex(random_bytes(32));$stmt=$db->prepare('INSERT INTO password_resets(token_hash,user_serial,expires_at) VALUES(?,1,DATE_ADD(UTC_TIMESTAMP(),INTERVAL 1 HOUR))');$stmt->execute([hash('sha256',$token)]);echo json_encode(['token'=>$token]);exit; +} +if($action==='mfaState'){ + $stmt=$db->prepare('SELECT user_serial FROM users WHERE user_email=?');$stmt->execute([$argv[3]]);$user=(int)$stmt->fetchColumn(); + $stmt=$db->prepare('SELECT * FROM user_mfa WHERE user_serial=?');$stmt->execute([$user]);$factor=$stmt->fetch(); + $stmt=$db->prepare('SELECT code_hash FROM mfa_recovery WHERE user_serial=?');$stmt->execute([$user]);echo json_encode(['factor'=>$factor,'recovery'=>$stmt->fetchAll(PDO::FETCH_COLUMN)]);exit; +} +if($action==='mfaCode'){ + $stmt=$db->prepare('SELECT user_serial FROM users WHERE user_email=?');$stmt->execute([$argv[3]]);$user=(int)$stmt->fetchColumn(); + $code=bin2hex(random_bytes(16));$stmt=$db->prepare('INSERT INTO mfa_recovery(user_serial,code_hash) VALUES(?,?)');$stmt->execute([$user,hash('sha256',$code)]);echo json_encode(['code'=>$code]);exit; +} if($action==='fingerprints'){ $result=[];foreach($db->query('SHOW FULL TABLES WHERE Table_type="BASE TABLE"')->fetchAll(PDO::FETCH_COLUMN) as $table){ $rows=array_map(static fn($row)=>json_encode($row,JSON_THROW_ON_ERROR),$db->query('SELECT * FROM `'.str_replace('`','``',$table).'`')->fetchAll(PDO::FETCH_ASSOC));sort($rows,SORT_STRING);$result[$table]=hash('sha256',implode("\n",$rows)); @@ -36,11 +86,46 @@ if($action==='verifyEmail'){ $stmt=$db->prepare('UPDATE users SET user_email_verified_at=UTC_TIMESTAMP() WHERE user_name=?');$stmt->execute([$argv[3]??'']);echo json_encode(['verified'=>true]);exit; } if($action==='inspect'){ - $tables=['users','dropdowntypes','dropdowns','statuses','notes','journal','clubs','club_memberships','club_seasons','club_dues','club_payments','club_due_adjustments','club_payment_reversals'];$result=[]; + $tables=['users','dropdowntypes','dropdowns','statuses','notes','journal','clubs','club_memberships','club_seasons','club_dues','club_payments','club_due_adjustments','club_payment_reversals','club_invitations','club_tickets','club_ticket_messages'];$result=[]; foreach($tables as $table)$result[$table]=$db->query('SELECT * FROM '.$table)->fetchAll(PDO::FETCH_ASSOC); foreach($result['users'] as &$user)unset($user['user_password_hash']);unset($user); echo json_encode($result);exit; } +if($action==='legacyTenantSchema'){$db->exec('ALTER TABLE club_memberships DROP COLUMN membership_role');$db->exec('ALTER TABLE clubs DROP INDEX club_name, ADD UNIQUE KEY club_name (club_name)');echo '{}';exit;} +if($action==='restoreTestSuper'){$db->exec("UPDATE users SET user_status='active' WHERE user_serial=1");echo '{}';exit;} +if($action==='seedTenantInvitation'){ + $stmt=$db->prepare("INSERT INTO club_invitations(club_serial,invited_by,invite_email,expires_at,sent_at) VALUES(?,?,?,DATE_ADD(UTC_TIMESTAMP(),INTERVAL 1 DAY),UTC_TIMESTAMP())");$stmt->execute([(int)$argv[3],(int)$argv[4],$argv[5]]);echo json_encode(['invitation'=>(int)$db->lastInsertId()]);exit; +} +if($action==='demoteTenantAdmin'){ + $stmt=$db->prepare("UPDATE club_memberships SET membership_role='member' WHERE membership_serial=?");$stmt->execute([(int)($argv[3]??0)]);echo '{}';exit; +} +if($action==='repairConcurrencySeed'){ + $club=(int)$argv[3];$user=(int)$argv[4];$inviter=(int)$argv[5]; + $stmt=$db->prepare("INSERT INTO club_memberships(club_serial,user_serial,membership_status,joined_on) VALUES(?,?,'inactive','2026-01-01')");$stmt->execute([$club,$user]);$membership=(int)$db->lastInsertId(); + $stmt=$db->prepare("INSERT INTO club_invitations(club_serial,invite_email,invited_by,expires_at,sent_at) SELECT ?,user_email,?,DATE_ADD(UTC_TIMESTAMP(),INTERVAL 1 DAY),UTC_TIMESTAMP() FROM users WHERE user_serial=?");$stmt->execute([$club,$inviter,$user]);echo json_encode(['membership'=>$membership,'invitation'=>(int)$db->lastInsertId()]);exit; +} +if($action==='ticketPagingSeed'){ + $a=(int)$argv[3];$b=(int)$argv[4];$owner=(int)$argv[5];$neighbor=(int)$argv[6];$foreign=(int)$argv[7];$oldest=0; + $stmt=$db->prepare('INSERT INTO club_tickets(club_serial,user_serial,subject) VALUES(?,?,?)'); + for($n=1;$n<=101;$n++){$stmt->execute([$a,$owner,'Archive ticket '.sprintf('%03d',$n)]);if($n===1)$oldest=(int)$db->lastInsertId();} + $stmt->execute([$a,$owner,'Literal %_! needle']);$literal=(int)$db->lastInsertId(); + $stmt->execute([$a,$neighbor,'Private neighbor ticket']);$private=(int)$db->lastInsertId(); + $stmt->execute([$b,$foreign,'Archive foreign club ticket']);$foreignTicket=(int)$db->lastInsertId(); + echo json_encode(['oldest'=>$oldest,'literal'=>$literal,'private'=>$private,'foreign'=>$foreignTicket]);exit; +} +if($action==='tenantSeed'){ + $ids=[];$hash=password_hash('Tenant test password 123!',PASSWORD_DEFAULT); + $insert=$db->prepare("INSERT INTO users(user_name,user_first_name,user_last_name,user_email,user_password_hash,user_role,user_email_verified_at) VALUES(?,?,?,?,?,?,UTC_TIMESTAMP())"); + foreach(['admina','admina2','adminb','membera','memberb','shared','invitee','unverified'] as $label){$insert->execute(['tenant'.$label,'Tenant',ucfirst($label),$label.'@example.test',$hash,in_array($label,['admina','adminb'],true)?'Administrator':'User']);$ids[$label]=(int)$db->lastInsertId();} + $db->exec("UPDATE users SET user_email_verified_at=NULL WHERE user_name='tenantunverified'"); + $db->exec("INSERT INTO clubs(club_name) VALUES('Tenant Alpha')");$ids['clubA']=(int)$db->lastInsertId();$db->exec("INSERT INTO clubs(club_name) VALUES('Tenant Beta')");$ids['clubB']=(int)$db->lastInsertId(); + $stmt=$db->prepare("INSERT INTO club_memberships(club_serial,user_serial,membership_role,joined_on) VALUES(?,?,?,'2026-01-01')"); + foreach([['clubA','admina','administrator'],['clubA','admina2','administrator'],['clubB','adminb','administrator'],['clubA','membera','member'],['clubB','memberb','member'],['clubA','shared','member'],['clubB','shared','member'],['clubB','admina','member']] as [$club,$who,$role]){$stmt->execute([$ids[$club],$ids[$who],$role]);$ids[$club.'_'.$who]=(int)$db->lastInsertId();} + echo json_encode($ids);exit; +} +if($action==='maintenance'){ + $out=[];foreach(['alerts','popovers'] as $table)$out[$table]=$db->query('SELECT * FROM '.$table.' ORDER BY 1')->fetchAll(PDO::FETCH_ASSOC);echo json_encode($out);exit; +} if($action==='unsafeRule'){ $db->exec("INSERT INTO dropdowntypes(dropdowntype_name,dropdowntype_title,dropdowntype_table,dropdowntype_column) VALUES('Unsafe legacy','Unsafe legacy','*function','getSettings')");$type=(int)$db->lastInsertId(); $stmt=$db->prepare("INSERT INTO dropdowns(dropdown_dropdowntype,dropdown_value) VALUES(?,'Legacy')");$stmt->execute([$type]);echo json_encode(['dropdown'=>(int)$db->lastInsertId()]);exit; diff --git a/tests/maintenance_http.py b/tests/maintenance_http.py new file mode 100644 index 0000000..91eee25 --- /dev/null +++ b/tests/maintenance_http.py @@ -0,0 +1,36 @@ +from application_harness import Application + +app=Application();checks=[] +def check(value,message): + if not value:raise AssertionError(message) + checks.append(message);print('PASS: '+message) +def valid(action,**fields): + result=app.post(action,**fields);check(result[0]==200,'Valid '+action+' succeeds: '+str(result[0]));return result +def invalid(action,fields,message): + before=app.fixture('fingerprints');response=app.post(action,**fields) + check(response[0]==422,message+' returns validation status') + check(app.fixture('fingerprints')==before,message+' leaves stored data unchanged') +try: + app.login() + alert=dict(step='add',alert_title='Valid alert',alert_starts_date='2026-10-20',alert_starts_time='12:00',alert_expires_date='2026-10-21',alert_expires_time='12:00',alert_message='

    Valid text

    ') + for change,label in [({'alert_title':' '},'Blank alert title'),({'alert_title':'x'*101},'Oversized alert title'),({'alert_message':'x'*1001},'Oversized alert HTML'),({'alert_starts_date':'2026-02-30'},'Invalid calendar date'),({'alert_starts_time':'25:00'},'Invalid hour'),({'alert_starts_date':'10/20/2026'},'Ambiguous date format'),({'alert_expires_date':'2026-10-19'},'Reversed alert interval'),({'alert_title':'Line\nBreak'},'Multiline title'),({'alert_starts_date':'2026-03-08','alert_starts_time':'02:30'},'Nonexistent daylight-saving time')]: + invalid('Alerts.addAlert',{**alert,**change},label) + valid('Alerts.addAlert',**alert);ident=app.fixture('maintenance')['alerts'][0]['alert_serial'] + invalid('Alerts.editAlert',{**alert,'step':'update','alert_serial':ident,'alert_title':''},'Invalid alert edit') + invalid('Alerts.editAlert',{**alert,'step':'update','alert_serial':'1 OR 1=1'},'Malformed alert edit ID') + valid('Alerts.editAlert',**{**alert,'step':'update','alert_serial':ident,'alert_title':'Updated alert','alert_message':'
    Preserved
    '}) + stored=app.fixture('maintenance')['alerts'][0];check(stored['alert_title']=='Updated alert' and '' in stored['alert_message'],'Valid edit preserves rich HTML without truncation') + valid('Alerts.addAlert',**{**alert,'alert_title':'界'*100,'alert_starts_date':'2028-02-29','alert_expires_date':'2028-03-01'}) + stored_title=app.fixture('maintenance')['alerts'][-1]['alert_title'] + check(stored_title=='界'*100,'Unicode limit counts characters rather than bytes') + popover=dict(step='add',popover_name='Valid popover',popover_title='Title',popover_placeholder='Optional hint',popover_text='

    Text

    ') + for change,label in [({'popover_name':''},'Blank popover name'),({'popover_title':' '},'Blank popover title'),({'popover_name':'x'*101},'Oversized popover name'),({'popover_title':'x'*101},'Oversized popover title'),({'popover_placeholder':'x'*101},'Oversized placeholder'),({'popover_text':'x'*1001},'Oversized popover HTML')]: + invalid('Popovers.addPopover',{**popover,**change},label) + valid('Popovers.addPopover',**popover);ident=app.fixture('maintenance')['popovers'][0]['popover_serial'] + invalid('Popovers.editPopover',{**popover,'step':'update','popover_serial':ident,'popover_title':''},'Invalid popover edit') + invalid('Popovers.editPopover',{**popover,'step':'update','popover_serial':'1 OR 1=1'},'Malformed popover edit ID') + valid('Popovers.editPopover',**{**popover,'step':'update','popover_serial':ident,'popover_title':'Updated title','popover_text':'

    Updated

    '}) + check(app.fixture('maintenance')['popovers'][0]['popover_text']=='

    Updated

    ','Popover editing retains formatting') + response=app.post('Popovers.popoverExists',popover_serial=0,popover_name='Valid popover');check(response[0]==200 and response[1]==b'true','Create-form uniqueness check still accepts its zero exclusion ID') +finally:app.close() +print(str(len(checks))+' maintenance HTTP checks passed.') diff --git a/tests/maintenance_worker.php b/tests/maintenance_worker.php index d7e7610..0a3c212 100644 --- a/tests/maintenance_worker.php +++ b/tests/maintenance_worker.php @@ -3,11 +3,13 @@ if(PHP_SAPI!=='cli')exit; require __DIR__.'/../classes/Base.php'; $settings=(new Base())->getSettings();$name=$argv[2]??''; if(!preg_match('/\Ahcr_http_test_[a-f0-9]{12}\z/',$name)||(string)$settings->DatabaseName!==$name||!in_array((string)$settings->DatabaseServer,['127.0.0.1','localhost','::1'],true))throw new RuntimeException('Concurrency workers require an isolated local test database.'); -$_SESSION=[Base::USER_AUTHENTICATED=>true,Base::USER_ROLE=>'Administrator',Base::USER_SERIAL=>1,Base::USER_NAME=>'Test worker']; +$_SESSION=[Base::USER_AUTHENTICATED=>true,Base::USER_ROLE=>TenantAccess::SUPER,Base::USER_SERIAL=>1,Base::USER_NAME=>'Test worker']; echo "READY\n";flush();fgets(STDIN); try{ $service=new MaintenanceService(); - if(($argv[1]??'')==='disable')$service->setUserActive((int)$argv[3],false); + if(($argv[1]??'')==='accept'){$_SESSION[Base::USER_SERIAL]=(int)$argv[4];(new ClubInvitations())->accept((int)$argv[3]);} + elseif(($argv[1]??'')==='membership')(new RosterService())->saveMember((int)$argv[4],(int)$argv[3],'','inactive','2026-01-01'); + elseif(($argv[1]??'')==='disable')$service->setUserActive((int)$argv[3],false); elseif(($argv[1]??'')==='default')$service->setDropdownDefault((int)$argv[3],(int)$argv[4],true); elseif(($argv[1]??'')==='payment')(new LedgerService())->payment((int)$argv[4],(int)$argv[3],$argv[5],'2026-01-01',bin2hex(random_bytes(32))); elseif(($argv[1]??'')==='reverse')(new LedgerService())->reverse((int)$argv[4],(int)$argv[3],'Concurrent reversal',$argv[5]); diff --git a/tests/member_actions_http.py b/tests/member_actions_http.py new file mode 100644 index 0000000..f802bde --- /dev/null +++ b/tests/member_actions_http.py @@ -0,0 +1,64 @@ +import json,secrets,urllib.request,urllib.parse,urllib.error +from application_harness import Application +app=Application();checks=0 +def check(ok,message): + global checks + assert ok,message + checks+=1;print('PASS:',message) +def url(club,member):return '/main.php?Xaction=Roster.memberSummary&club_serial='+str(club)+'&membership_serial='+str(member) +def save(step,club,member,**extra): + data={'action':'Roster.memberSummary','csrf_token':app.token,'step':step,'club_serial':club,'membership_serial':member,**extra} + request=urllib.request.Request(app.base+url(club,member),data=urllib.parse.urlencode(data).encode(),headers={'X-Requested-With':'XMLHttpRequest','X-HCR-Modal':'1'}) + try: + with app.client.open(request) as response:return response.status,json.loads(response.read()) + except urllib.error.HTTPError as error: + body=error.read() + try:result=json.loads(body) + except json.JSONDecodeError:result={'error':body.decode(errors='replace')} + return error.code,result +try: + ids=app.fixture('tenantSeed');a=ids['clubA'];b=ids['clubB'];member=ids['clubA_membera'];neighbor=ids['clubA_shared'];foreign=ids['clubB_shared'] + app.login() + for club,name in [(a,'New season'),(a,'Other season'),(b,'Foreign season')]:app.post('Roster.workspace',step='season',club_serial=club,season_name=name,starts_on='2026-01-01',ends_on='2026-12-31') + state=app.fixture('inspect');season=next(s['season_serial'] for s in state['club_seasons'] if s['season_name']=='New season');foreignseason=next(s['season_serial'] for s in state['club_seasons'] if s['season_name']=='Foreign season') + app.post('Roster.workspace',step='charge',club_serial=a,membership_serial=neighbor,season_serial=season,amount='100.00') + app.post('Roster.workspace',step='charge',club_serial=b,membership_serial=foreign,season_serial=foreignseason,amount='100.00') + state=app.fixture('inspect');neighbor_due=state['club_dues'][0]['due_serial'];foreign_due=state['club_dues'][1]['due_serial'] + app.logout();app.login('admina@example.test','Tenant test password 123!') + _,body,_=app.request(url(a,member)) + check(b'data-club-step="member"' in body and b'data-club-step="charge"' in body,'Club administrator gets member edit and dues dialogs') + check(save('charge',a,member,csrf_token='invalid',season_serial=season,amount='100.00')[0]==403,'Member summary writes require a valid CSRF token') + check(save('charge',a,member,membership_serial=neighbor,season_serial=season,amount='100.00')[0]==409,'Posted membership cannot differ from the selected summary') + status,result=save('charge',a,member,season_serial=season,amount='100.00') + check(status==200 and result['ok'] and 'Roster.memberSummary' in result['redirect'] and 'membership_serial='+str(member) in result['redirect'],'Dues save returns a same-member summary redirect') + state=app.fixture('inspect');due=next(d['due_serial'] for d in state['club_dues'] if d['membership_serial']==member) + check(save('charge',a,member,season_serial=season,amount='100.00')[0]==409,'Duplicate season dues remain rejected') + check(save('charge',a,member,season_serial=foreignseason,amount='10.00')[0]==409,'Dues cannot use another club season') + check(save('payment',a,member,due_serial=neighbor_due,amount='1.00',paid_on='2026-01-01',request_key=secrets.token_hex(32))[0]==404,'Payment cannot target a different member in the same club') + check(save('payment',a,member,due_serial=foreign_due,amount='1.00',paid_on='2026-01-01',request_key=secrets.token_hex(32))[0]==404,'Payment cannot target another club dues') + key=secrets.token_hex(32) + check(save('payment',a,member,due_serial=due,amount='25.00',paid_on='2026-01-01',request_key=key,payment_method='cash',payment_reference='Member summary receipt')[0]==200,'Payment is recorded for the selected membership') + check(save('payment',a,member,due_serial=due,amount='25.00',paid_on='2026-01-01',request_key=key,payment_method='cash',payment_reference='Member summary receipt')[0]==200 and len(app.fixture('inspect')['club_payments'])==1,'Payment retry remains idempotent') + app.fixture('mfaTestAuditFailure','on') + status,_=save('payment',a,member,due_serial=due,amount='1.00',paid_on='2026-01-01',request_key=secrets.token_hex(32)) + app.fixture('mfaTestAuditFailure','off') + check(status==500 and len(app.fixture('inspect')['club_payments'])==1,'Failed mandatory audit rolls back a summary payment completely') + check(save('payment',a,member,due_serial=due,amount='76.00',paid_on='2026-01-01',request_key=secrets.token_hex(32))[0]==409,'Overpayments remain rejected') + status,result=save('member',a,member,membership_status='active',membership_role='member',joined_on='2026-02-01') + check(status==200 and next(m for m in app.fixture('inspect')['club_memberships'] if m['membership_serial']==member)['joined_on']=='2026-02-01','Membership information saves from the summary') + check(save('member',a,member,membership_status='active',membership_role='administrator',joined_on='2026-02-01')[0]==403,'Club administrator cannot promote members to administrator') + check(save('member',a,ids['clubA_admina2'],membership_status='inactive',membership_role='member',joined_on='2026-02-01')[0]==403,'Club administrator cannot edit protected administrator memberships') + sid=next(c.value for h in app.client.handlers if hasattr(h,'cookiejar') for c in h.cookiejar if c.name=='HUNTINGCLUBROSTER');app.fixture('sessionAge',sid,'','','301') + check(save('member',a,member,membership_status='active',membership_role='member',joined_on='2026-03-01')[0]==403,'Membership edits require recent MFA on the new endpoint') + app.logout();app.login('membera@example.test','Tenant test password 123!') + _,body,_=app.request(url(a,member));check(b'club-action-modal' not in body,'Ordinary member receives no action dialogs') + check(save('payment',a,member,due_serial=due,amount='1.00',paid_on='2026-01-01',request_key=secrets.token_hex(32))[0]==403,'Ordinary member cannot forge a summary payment request') + check(save('charge',a,member,season_serial=season,amount='1.00')[0]==403,'Ordinary member cannot forge a dues request') + app.logout();app.login('adminb@example.test','Tenant test password 123!') + check(save('member',a,member,membership_status='active',membership_role='member',joined_on='2026-03-01')[0]==403,'Other club administrator cannot modify the membership') + app.logout();app.login();app.post('Roster.workspace',step='club',club_serial=a,club_name='Tenant Alpha',club_status='archived') + _,body,_=app.request(url(a,member));check(b'club-action-modal' not in body,'Archived club summary exposes no write dialogs') + check(save('charge',a,member,season_serial=season,amount='10.00')[0]==409,'Archived club rejects forged member summary writes') + print(checks,'member action HTTP checks passed.') +finally: + app.fixture('mfaTestAuditFailure','off');app.close() diff --git a/tests/member_summary_http.py b/tests/member_summary_http.py new file mode 100644 index 0000000..96b6657 --- /dev/null +++ b/tests/member_summary_http.py @@ -0,0 +1,48 @@ +import re +from application_harness import Application +app=Application();checks=0 +def check(ok,message): + global checks + assert ok,message + checks+=1;print('PASS:',message) +def summary(club,membership,extra=''): + return app.request('/main.php?Xaction=Roster.memberSummary&club_serial='+str(club)+'&membership_serial='+str(membership)+extra) +try: + ids=app.fixture('tenantSeed');app.fixture('memberSummarySeed',str(ids['clubA']),str(ids['clubB']),str(ids['clubA_membera']),str(ids['clubA_shared']),str(ids['clubB_shared'])) + _,login,_=app.request() + app.request(data={'action':'SignIn.login','csrf_token':app.csrf(login),'user_email':'admin@example.test','user_password':'Admin test password 123!'}) + status,body,_=summary(ids['clubA'],ids['clubA_membera']) + check(status==200 and b'

    Account security

    ' in body and b'

    Tenant Membera

    ' not in body,'Member summary cannot bypass mandatory administrator MFA') + check(app.request('/main.php?Xaction=Roster.memberSummary&club_serial='+str(ids['clubA'])+'&membership_serial='+str(ids['clubA_membera']),ajax=True)[0]==403,'AJAX member summary also requires completed administrator MFA') + app.login();before=app.fixture('fingerprints') + status,body,_=summary(ids['clubA'],ids['clubA_membera']) + check(status==200 and b'

    Tenant Membera

    ' in body and b'membera@example.test' in body,'Super Administrator opens a club member summary') + check(b'$3,150.00' in body and b'$31.00' in body and b'$3,119.00' in body,'Totals include all dues corrections and exclude reversed payments across every page') + check(b'Own reversed receipt' in body and b'OWN-RECEIPT-32' in body,'Payment history preserves reversed receipts and their reasons') + check(b'<script>unsafe</script>' in body and b'' not in body,'Correction reasons are escaped safely') + check(b'NEIGHBOR-PRIVATE' not in body and b'FOREIGN-PRIVATE' not in body,'Selected member summary excludes neighboring members and other clubs') + check(body.count(b'OWN-RECEIPT-')==25 and b'31 records.' in body and b'32 records.' in body,'Member dues and payment histories are bounded and counted independently') + links=re.findall(rb'href="([^"]+)"',body) + check(any(b'payments_page=2' in link and b'membership_serial='+str(ids['clubA_membera']).encode() in link and b'Roster.memberSummary' in link for link in links),'History pager links retain both club and membership scope') + status,last,_=summary(ids['clubA'],ids['clubA_membera'],'&payments_page=9999&dues_page=9999') + check(status==200 and last.count(b'OWN-RECEIPT-')==7 and b'Page 2 of 2' in last,'Final history pages are clamped and show only remaining records') + check(b'$3,150.00' in last and b'$31.00' in last and b'$3,119.00' in last,'Summary totals remain identical on later history pages') + check(summary(ids['clubB'],ids['clubA_membera'])[0]==404,'Membership IDs cannot be paired with another club') + check(summary(ids['clubA'],'invalid')[0]==422,'Invalid membership identifiers are rejected') + check(summary(ids['clubA'],ids['clubA_membera'],'&payments_page=0')[0]==422,'Invalid history pages are rejected') + check(app.fixture('fingerprints')==before,'Opening summaries and changing pages perform no database writes beyond authentication bookkeeping') + app.logout();app.login('admina@example.test','Tenant test password 123!') + check(summary(ids['clubA'],ids['clubA_membera'])[0]==200,'Club administrator can view a member in the administered club') + check(summary(ids['clubB'],ids['clubB_shared'])[0]==404,'Administrator cannot view another member where they are only an ordinary member') + app.logout();app.login('adminb@example.test','Tenant test password 123!') + check(summary(ids['clubA'],ids['clubA_membera'])[0]==403,'Other club administrator is denied access to the club summary') + app.logout();app.login('membera@example.test','Tenant test password 123!') + status,body,_=summary(ids['clubA'],ids['clubA_membera']) + check(status==200 and b'$3,119.00' in body and b'club-action-modal' not in body,'Member can read their own finances without administrator actions') + check(summary(ids['clubA'],ids['clubA_shared'])[0]==404,'Member cannot read another member summary in the same club') + check(summary(ids['clubB'],ids['clubB_shared'])[0]==403,'Member cannot read another club summary') + app.logout();app.login('shared@example.test','Tenant test password 123!') + _,a,_=summary(ids['clubA'],ids['clubA_shared']);_,b,_=summary(ids['clubB'],ids['clubB_shared']) + check(b'NEIGHBOR-PRIVATE' in a and b'FOREIGN-PRIVATE' not in a and b'FOREIGN-PRIVATE' in b and b'NEIGHBOR-PRIVATE' not in b,'A member of two clubs sees separate membership histories') + print(checks,'member summary HTTP checks passed.') +finally:app.close() diff --git a/tests/mfa_concurrency.py b/tests/mfa_concurrency.py new file mode 100644 index 0000000..8b77e13 --- /dev/null +++ b/tests/mfa_concurrency.py @@ -0,0 +1,34 @@ +import json,subprocess +from application_harness import Application,ROOT,PHP +app=Application();workers=[] +def race(operation,seed): + group=[] + for state in seed['states']: + p=subprocess.Popen(PHP+['tests/mfa_worker.php',operation],cwd=ROOT,env=app.env,stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.PIPE,text=True) + workers.append(p);group.append(p) + p.stdin.write(json.dumps({'state':state,'recovery':seed['recovery']})+'\n');p.stdin.flush() + for p in group:assert p.stdout.readline().strip()=='READY' + for p in group:p.stdin.write('go\n');p.stdin.flush() + result=[] + for p in group: + out,err=p.communicate(timeout=30) + assert p.returncode==0,err + result.append(json.loads(out)) + return result +try: + seed=json.loads(subprocess.check_output(PHP+['tests/mfa_worker.php','seed'],cwd=ROOT,env=app.env,text=True)) + before=app.fixture('mfaState','admin@example.test') + result=race('verify',seed) + after=app.fixture('mfaState','admin@example.test') + assert sorted(r['ok'] for r in result)==[False,True] and len(after['recovery'])==len(before['recovery'])-1,result + print('PASS: Concurrent recovery attempts consume a single-use code exactly once.') + result=race('replace',seed) + after=app.fixture('mfaState','admin@example.test') + assert sorted(r['ok'] for r in result)==[False,True],result + assert len(after['recovery'])==10 and after['factor']['secret_cipher']!=before['factor']['secret_cipher'] + print('PASS: Competing authorized replacements commit exactly one complete factor swap.') + print('2 MFA concurrency checks passed.') +finally: + for p in workers: + if p.poll() is None:p.kill();p.wait() + app.close() diff --git a/tests/mfa_key_configuration.php b/tests/mfa_key_configuration.php new file mode 100644 index 0000000..25701c1 --- /dev/null +++ b/tests/mfa_key_configuration.php @@ -0,0 +1,33 @@ +');$settings->Environment=$this->environment;$settings->MfaKeyFile=$this->file;return $settings; + } +} +$old=getenv('HCR_MFA_KEY');$oldFile=getenv('HCR_MFA_KEY_FILE');putenv('HCR_MFA_KEY');putenv('HCR_MFA_KEY_FILE');$checks=0;$file=tempnam(sys_get_temp_dir(),'hcr-mfa-key-');$inside=__DIR__.'/.local/key-path-test-'.bin2hex(random_bytes(6)); +function keyCheck(bool $ok,string $message):void{global $checks;if(!$ok)throw new RuntimeException($message);$checks++;echo "PASS: $message\n";} +function keyDenied(callable $work,string $message):void{try{$work();}catch(RuntimeException $e){keyCheck(true,$message);return;}throw new LogicException($message.' was allowed');} +try{ + $service=new FileKeyMfa();$service->file=$file;file_put_contents($file,base64_encode(random_bytes(32))); + keyCheck($service->sealSecret('test',1)!=='','Development loads a persistent key outside the application'); + $service->file=$file.'.missing';putenv('HCR_MFA_KEY_FILE='.$file); + keyCheck($service->sealSecret('test',1)!=='','Server key-file configuration overrides workstation settings'); + $service->environment='Production';keyDenied(fn()=>$service->sealSecret('test',1),'Production cannot use the development key-file fallback'); + putenv('HCR_MFA_KEY_FILE');$service->file=$file; + putenv('HCR_MFA_KEY='.base64_encode(random_bytes(32)));keyCheck($service->sealSecret('test',1)!=='','Explicit production environment key remains supported'); + putenv('HCR_MFA_KEY=invalid');$service->environment='Development';keyDenied(fn()=>$service->sealSecret('test',1),'Invalid explicit key is not silently replaced by a file');putenv('HCR_MFA_KEY'); + if(!is_dir(dirname($inside)))mkdir(dirname($inside),0700,true);file_put_contents($inside,base64_encode(random_bytes(32)));$service->file=$inside; + keyDenied(fn()=>$service->sealSecret('test',1),'Development key inside the application tree is rejected'); + $service->file=$file;file_put_contents($file,str_repeat('A',129));keyDenied(fn()=>$service->sealSecret('test',1),'Oversized key file is rejected'); + file_put_contents($file,'invalid');keyDenied(fn()=>$service->sealSecret('test',1),'Malformed file key is rejected'); + $service->file=$file.'.missing';keyDenied(fn()=>$service->sealSecret('test',1),'Missing development key file is rejected'); + echo "$checks MFA key configuration checks passed.\n"; +}finally{ + if(is_file($file))unlink($file);if(is_file($inside))unlink($inside); + if($old===false)putenv('HCR_MFA_KEY');else putenv('HCR_MFA_KEY='.$old); + if($oldFile===false)putenv('HCR_MFA_KEY_FILE');else putenv('HCR_MFA_KEY_FILE='.$oldFile); +} diff --git a/tests/mfa_lifecycle_http.py b/tests/mfa_lifecycle_http.py new file mode 100644 index 0000000..040df23 --- /dev/null +++ b/tests/mfa_lifecycle_http.py @@ -0,0 +1,86 @@ +"""Competing password-only sessions must never inherit replacement permission.""" +import http.cookiejar,re,time,urllib.error,urllib.parse,urllib.request +from application_harness import Application +app=Application();checks=0;password='Admin test password 123!' +def check(ok,message): + global checks + if not ok:raise AssertionError(message) + checks+=1;print('PASS:',message) +class Client: + def __init__(self): + self.jar=http.cookiejar.CookieJar();self.client=urllib.request.build_opener(urllib.request.HTTPCookieProcessor(self.jar));self.body=b'' + self.login() + def request(self,path='/',data=None,ajax=False): + req=urllib.request.Request(app.base+path,data=urllib.parse.urlencode(data).encode() if data is not None else None,headers={'X-Requested-With':'XMLHttpRequest'} if ajax else {}) + try: + with self.client.open(req,timeout=30) as r:status,body=r.status,r.read() + except urllib.error.HTTPError as e:status,body=e.code,e.read() + if b'csrf' in body:self.body=body + return status,body + def login(self,pwd=password): + _,body=self.request();return self.request(data={'action':'SignIn.login','csrf_token':app.csrf(body),'user_email':'admin@example.test','user_password':pwd}) + def security(self,code='',pwd=password,**extra): + return self.request(data={'action':'security','csrf_token':app.csrf(self.body),'current_password':pwd,'mfa_code':code,**extra}) + def post(self,action,**extra):return self.request(data={'action':action,'csrf_token':app.csrf(self.body),**extra},ajax=True) + def state(self,operation='snapshot'): + sid=next(c.value for c in self.jar if c.name=='HUNTINGCLUBROSTER');return app.fixture('mfaTestSession',sid,operation) +def factor():return app.fixture('mfaState','admin@example.test') +def secret(body):return re.search(rb'
    ([A-Z2-7]+)
    ',body).group(1).decode() +try: + victim=Client();original_secret=secret(victim.body) + status,body=victim.security(app.totp(original_secret));codes=[v.decode() for v in re.findall(rb'\b[a-f0-9]{32}\b',body)] + check(status==200 and len(codes)==10,'Initial enrollment succeeds') + check(b'notification email could not be sent' in body,'Failed security email is visibly reported without undoing enrollment') + victim.request('/main.php?Xaction=security');before=factor() + status,_=victim.security(codes[0],pwd='incorrect') + check(status==403 and factor()==before,'Wrong password preserves the recovery code and factor counter') + status,_=victim.security(codes[0]);check(status==200 and len(factor()['recovery'])==9,'Recovery code remains usable with the correct password') + victim.request('/main.php?Xaction=security');before=factor();next_code=app.totp(original_secret,time.time()+30) + status,_=victim.security(next_code,pwd='incorrect');check(status==403 and factor()==before,'Wrong password cannot consume an authenticator time step') + status,_=victim.security(next_code);check(status==200,'Authenticator time step still verifies with the correct password') + victim.request('/main.php?Xaction=security');before=factor();version=victim.state()['auth_version'] + status,body=victim.security(codes[1],factor_action='replace');replacement_secret=secret(body) + check(status==200 and factor()['factor']==before['factor'] and len(factor()['recovery'])==8,'Starting replacement keeps the old factor and unused recovery codes') + check(victim.state()['auth_version']==version,'Starting replacement does not revoke other sessions prematurely') + attacker=Client();check(b'setup key' not in attacker.body and b'Authentication code' in attacker.body,'A separate password-only session still faces the existing MFA challenge') + status,_=attacker.security(app.totp(replacement_secret),factor_action='confirmReplacement') + check(status==409 and factor()['factor']==before['factor'],'Password-only session cannot confirm another session\'s pending replacement') + check(attacker.post('Users.setupUsers')[0]==403,'Password-only session cannot access Super Administrator pages') + victim.security(factor_action='cancelReplacement') + check(factor()['factor']==before['factor'] and len(factor()['recovery'])==8,'Canceling replacement preserves the existing factor and remaining codes') + victim.security(codes[2],factor_action='replace');expired_secret=secret(victim.body);victim.state('expire');before=factor() + status,_=victim.security(app.totp(expired_secret),factor_action='confirmReplacement') + check(status==409 and factor()==before,'Expired replacement cannot change either factor or recovery codes') + app.fixture('clearTestAttempts') + victim.security(codes[3],factor_action='replace');replacement_secret=secret(victim.body);before=factor() + status,_=victim.security(app.totp(replacement_secret),pwd='incorrect',factor_action='confirmReplacement') + check(status==403 and factor()==before,'Replacement confirmation with wrong password is non-mutating') + app.fixture('clearTestAttempts') + status,_=victim.security('not-a-code',factor_action='confirmReplacement') + check(status==422 and factor()==before,'Invalid new authenticator code leaves existing protection intact') + app.fixture('mfaTestAuditFailure','on') + status,_=victim.security(app.totp(replacement_secret),factor_action='confirmReplacement') + app.fixture('mfaTestAuditFailure','off') + check(status==500 and factor()==before,'Failed mandatory audit rolls back the entire factor swap') + victim.request('/main.php?Xaction=security') + confirmed_code=app.totp(replacement_secret) + status,body=victim.security(confirmed_code,factor_action='confirmReplacement');newcodes=[v.decode() for v in re.findall(rb'\b[a-f0-9]{32}\b',body)] + check(status==200 and len(newcodes)==10 and factor()['factor']['secret_cipher']!=before['factor']['secret_cipher'],'Successful confirmation swaps the factor and creates ten fresh recovery codes') + check(not set(before['recovery'])&set(factor()['recovery']),'Confirmation revokes every old recovery code') + check(attacker.post('Users.setupUsers')[0]==401,'Successful replacement revokes the competing session') + victim.request('/main.php?Xaction=security');before=factor();status,_=victim.security(confirmed_code) + check(status==403 and factor()==before,'New authenticator confirmation code cannot be replayed') + status,_=victim.security(newcodes[0]);check(status==200,'New recovery codes authenticate successfully') + app.fixture('clearTestAttempts');victim.request('/main.php?Xaction=security');victim.security(newcodes[1],factor_action='replace');before=factor() + token=app.fixture('mfaResetToken')['token'];newpwd='Changed with MFA still active 123!' + _,reset=victim.request('/main.php?Xaction=resetpassword&token='+token) + status,_=victim.request(data={'action':'resetpassword','step':'reset','csrf_token':app.csrf(reset),'token':token,'user_password':newpwd,'user_password_confirm':newpwd}) + check(status==200 and factor()==before,'Password reset preserves the active factor during pending replacement') + check(victim.post('security',factor_action='confirmReplacement',current_password=newpwd,mfa_code='000000')[0]==401,'Password reset invalidates the old replacement session') + fresh=Client();fresh.login(newpwd) + check(b'Authentication code' in fresh.body and b'setup key' not in fresh.body,'Password reset never reopens password-only MFA enrollment') + print(checks,'MFA lifecycle HTTP checks passed.') +except Exception: + app.log.seek(0);print(app.log.read().decode(errors='replace')[-4500:]);raise +finally: + app.fixture('mfaTestAuditFailure','off');app.close() diff --git a/tests/mfa_notifications.php b/tests/mfa_notifications.php new file mode 100644 index 0000000..c6336b2 --- /dev/null +++ b/tests/mfa_notifications.php @@ -0,0 +1,45 @@ +connect();$checks=0; +function notificationCheck(bool $ok,string $message):void{global $checks;if(!$ok)throw new RuntimeException($message);$checks++;echo "PASS: $message\n";} +class CapturedMfaNotice extends MfaSecurityNotifications { + public array $messages=[];public bool $works=true;public bool $throws=false; + protected function deliver(string $to,string $subject,string $body):bool { + if($this->throws)throw new RuntimeException('Test delivery failure'); + $this->messages[]=compact('to','subject','body');return $this->works; + } +} +$notice=new CapturedMfaNotice();$account=['user_serial'=>1,'user_email'=>'admin+security@example.test']; +foreach(['enrolled','replacement_started','replacement_started_recovery','replaced','recovery_used'] as $event){ + notificationCheck($notice->send($account,$event),'Security notice supports event '.$event); + $message=end($notice->messages);notificationCheck($message['to']===$account['user_email']&&str_contains($message['body'],'Time (UTC)')&&str_contains($message['body'],'did not authorize'),'Notice uses stored address, time and unauthorized-activity instructions'); +} +notificationCheck(!str_contains(implode('',array_column($notice->messages,'body')),'otpauth://')&&!str_contains(implode('',array_column($notice->messages,'body')),'secret='),'Security notices contain no provisioning links or setup secrets'); +$notice->send(['user_serial'=>1,'user_email'=>''],'enrolled');notificationCheck(!str_contains(end($notice->messages)['body'],'works=false;notificationCheck(!$notice->send($account,'enrolled'),'Delivery failure is reported to the caller');$notice->throws=true;notificationCheck(!$notice->send($account,'replaced'),'Provider exceptions cannot undo committed security actions'); +try{$notice->send($account,'untrusted-event');throw new RuntimeException('Unknown event accepted');}catch(LogicException $e){notificationCheck(true,'Only reviewed security event types can be sent');} +$_SESSION['mfa_notification_warning']=true;notificationCheck(str_contains(MfaSecurityNotifications::notice(),'notification email could not be sent')&&MfaSecurityNotifications::notice()==='','Notification failure warning is visible and consumed once'); +class CapturedMfaEvents extends MfaService { + public array $events=[]; + protected function notify(array $account,string $event):void { + if($this->connect()->inTransaction())throw new RuntimeException('Notification attempted before commit'); + $this->events[]=$event; + } +} +$auth=new AuthService();$auth->login('admin@example.test','Admin test password 123!');$mfa=new CapturedMfaEvents();$user=1; +$secret=OTPHP\TOTP::generate(new MfaClock())->getSecret();$_SESSION['mfa_pending']=['user'=>1,'secret'=>$secret,'expires'=>time()+600]; +$codes=$mfa->enroll($user,$secret,OTPHP\TOTP::createFromSecret($secret,new MfaClock())->now(),'Admin test password 123!'); +notificationCheck($mfa->events===['enrolled'],'Enrollment notification runs once after transaction commit'); +$before=$mfa->events;notificationCheck(!$mfa->verify(1,$codes[0],'wrong')&&$before===$mfa->events,'Failed password creates no recovery notification'); +$db->exec("CREATE TRIGGER reject_notice_audit BEFORE INSERT ON journal FOR EACH ROW SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='Test audit failure'"); +try{$mfa->verify(1,$codes[0],'Admin test password 123!');throw new RuntimeException('Audit failure accepted');}catch(PDOException $e){notificationCheck($mfa->events===$before,'Rolled-back recovery does not send a false security notice');}$db->exec('DROP TRIGGER reject_notice_audit'); +notificationCheck($mfa->verify(1,$codes[0],'Admin test password 123!')&&$mfa->events===['enrolled','recovery_used'],'Committed recovery sends exactly one notice'); +$before=$mfa->events;notificationCheck(!$mfa->verify(1,$codes[0],'Admin test password 123!')&&$mfa->events===$before,'Replayed recovery sends no duplicate notice'); +$mfa->beginReplacement(1,$codes[1],'Admin test password 123!');notificationCheck(end($mfa->events)==='replacement_started_recovery','Recovery-authorized replacement sends one combined security notice'); +$secret=$_SESSION['mfa_replacement']['secret'];$before=$mfa->events; +$db->exec("CREATE TRIGGER reject_notice_audit BEFORE INSERT ON journal FOR EACH ROW SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='Test audit failure'"); +try{$mfa->completeReplacement(1,OTPHP\TOTP::createFromSecret($secret,new MfaClock())->now(),'Admin test password 123!');throw new RuntimeException('Audit failure accepted');}catch(PDOException $e){notificationCheck($mfa->events===$before,'Rolled-back replacement sends no completion notice');}$db->exec('DROP TRIGGER reject_notice_audit'); +$mfa->completeReplacement(1,OTPHP\TOTP::createFromSecret($secret,new MfaClock())->now(),'Admin test password 123!');notificationCheck(count($mfa->events)===4&&end($mfa->events)==='replaced','Successful replacement sends one completion notice after commit'); +echo "$checks MFA notification checks passed.\n";ob_end_flush(); diff --git a/tests/mfa_notifications_runner.py b/tests/mfa_notifications_runner.py new file mode 100644 index 0000000..3390b36 --- /dev/null +++ b/tests/mfa_notifications_runner.py @@ -0,0 +1,5 @@ +import subprocess +from application_harness import Application,PHP,ROOT +app=Application() +try:subprocess.run(PHP+['tests/mfa_notifications.php'],cwd=ROOT,env=app.env,check=True) +finally:app.close() diff --git a/tests/mfa_qr_browser.js b/tests/mfa_qr_browser.js new file mode 100644 index 0000000..4b138cb --- /dev/null +++ b/tests/mfa_qr_browser.js @@ -0,0 +1,38 @@ +const {chromium}=require('playwright'); +const assert=require('node:assert/strict'); +const jsQR=require('jsqr'); +const {totp}=require('./browser_mfa'); +(async()=>{ + const browser=await chromium.launch({executablePath:process.env.HCR_TEST_CHROME||'C:/Program Files/Google/Chrome/Application/chrome.exe',headless:true}); + const page=await browser.newPage({viewport:{width:390,height:844}}),errors=[],requests=[];let checks=0; + page.on('pageerror',e=>errors.push(e.message));page.on('request',r=>requests.push(r.url())); + const pass=message=>{checks++;console.log('PASS:',message);}; + const click=async button=>{await Promise.all([page.waitForNavigation(),button.click()]);}; + async function scan(){ + const image=page.locator('.mfa-setup-qr');await image.waitFor({state:'visible'}); + const pixels=await image.evaluate(async img=>{ + await img.decode();const canvas=document.createElement('canvas');canvas.width=canvas.height=320; + const ctx=canvas.getContext('2d');ctx.drawImage(img,0,0,320,320); + return Array.from(ctx.getImageData(0,0,320,320).data); + }); + const decoded=jsQR(new Uint8ClampedArray(pixels),320,320,{inversionAttempts:'dontInvert'}); + assert(decoded,'QR image did not decode');return new URL(decoded.data); + } + try{ + await page.goto(process.env.HCR_TEST_URL+'/main.php');await page.locator('#user_email').fill('admin@example.test');await page.locator('#user_password').fill('Admin test password 123!');await click(page.locator('#login button[type=submit]')); + const image=page.locator('.mfa-setup-qr');assert.match(await image.getAttribute('src'),/^data:image\/svg\+xml;base64,/);pass('Setup renders a locally generated QR image under the security policy'); + const uri=await scan(),secret=uri.searchParams.get('secret');assert.equal(uri.protocol,'otpauth:');assert.equal(uri.host,'totp');assert.equal(uri.searchParams.get('issuer'),'My Hunting Club Roster');assert(decodeURIComponent(uri.pathname).includes('admin@example.test'));pass('Independent decoder reads the correct authenticator type, issuer and account'); + assert.equal(secret,(await page.locator('pre').textContent()).trim());assert.equal(uri.searchParams.get('period')||'30','30');assert.equal(uri.searchParams.get('digits')||'6','6');assert.equal((uri.searchParams.get('algorithm')||'SHA1').toUpperCase(),'SHA1');pass('QR and manual key configure the same secret and verification settings'); + await page.reload();assert((await scan()).href===uri.href,'Refreshing setup changed its provisioning details');pass('Refreshing pending setup preserves its QR details and manual key'); + const box=await image.boundingBox();assert(box.width<=390&&box.height===box.width);pass('QR image fits a phone-width browser without distortion'); + await page.locator('[name=current_password]').fill('Admin test password 123!');await page.locator('[name=mfa_code]').fill(totp(secret));await click(page.getByRole('button',{name:'Verify',exact:true})); + await page.getByRole('heading',{name:'Save your recovery codes'}).waitFor();const codes=(await page.locator('pre').textContent()).trim().split(/\s+/);assert.equal(codes.length,10);pass('A code generated from the scanned QR completes MFA enrollment'); + assert.equal(await page.locator('.mfa-setup-qr').count(),0);await click(page.getByRole('link',{name:'I have saved my recovery codes'}));await page.goto(process.env.HCR_TEST_URL+'/main.php?Xaction=security');assert.equal(await page.locator('.mfa-setup-qr').count(),0);pass('Enrolled accounts and recovery-code pages do not display the setup QR'); + await page.locator('[name=current_password]').fill('Admin test password 123!');await page.locator('[name=mfa_code]').fill(codes[0]);await click(page.getByRole('button',{name:'Replace lost authenticator',exact:true})); + const replacement=await scan();assert.notEqual(replacement.searchParams.get('secret'),secret);assert.equal(replacement.searchParams.get('secret'),(await page.locator('pre').textContent()).trim());pass('Authenticator replacement gets a fresh QR matching the new manual key'); + await page.locator('[name=current_password]').fill('Admin test password 123!');await page.locator('[name=mfa_code]').fill(totp(replacement.searchParams.get('secret')));await click(page.getByRole('button',{name:'Confirm replacement',exact:true}));await page.getByRole('heading',{name:'Save your recovery codes'}).waitFor();pass('Scanned replacement code confirms the atomic factor swap'); + assert(requests.every(url=>url.startsWith(process.env.HCR_TEST_URL)||url.startsWith('data:')));assert(!requests.some(url=>url.includes(secret)));pass('Setup makes no external QR requests and puts no secret in request URLs'); + assert.deepEqual(errors,[]);pass('QR enrollment and replacement produce no browser script errors'); + console.log(checks,'MFA QR browser checks passed.'); + }finally{await browser.close();} +})().catch(e=>{console.error(e);process.exit(1);}); diff --git a/tests/mfa_qr_browser_runner.py b/tests/mfa_qr_browser_runner.py new file mode 100644 index 0000000..15981e5 --- /dev/null +++ b/tests/mfa_qr_browser_runner.py @@ -0,0 +1,8 @@ +import os,subprocess +from application_harness import Application,ROOT +app=Application() +try: + env=app.env.copy();env['HCR_TEST_URL']=app.base + env['NODE_PATH']=str(ROOT/'.tools/qr-test/node_modules')+os.pathsep+env.get('NODE_PATH','') + subprocess.run([env.get('NODE_TEST_COMMAND','node'),'tests/mfa_qr_browser.js'],cwd=ROOT,env=env,check=True) +finally:app.close() diff --git a/tests/mfa_worker.php b/tests/mfa_worker.php new file mode 100644 index 0000000..28049ff --- /dev/null +++ b/tests/mfa_worker.php @@ -0,0 +1,27 @@ +login('admin@example.test',$password); + $secret=OTPHP\TOTP::generate(new MfaClock())->getSecret(); + $_SESSION['mfa_pending']=['user'=>1,'secret'=>$secret,'expires'=>time()+600]; + $codes=$mfa->enroll(1,$secret,OTPHP\TOTP::createFromSecret($secret,new MfaClock())->now(),$password); + $base=$_SESSION;$states=[]; + foreach([$codes[0],$codes[1]] as $code){$_SESSION=$base;$mfa->beginReplacement(1,$code,$password);$states[]=$_SESSION;} + ob_clean();echo json_encode(['states'=>$states,'recovery'=>$codes[2]]);ob_end_flush();exit; +} +$payload=json_decode(trim(fgets(STDIN)),true,512,JSON_THROW_ON_ERROR);$_SESSION=$payload['state']; +ob_clean();fwrite(STDOUT,"READY\n");fflush(STDOUT);fgets(STDIN); +try{ + if($argv[1]==='replace'){ + $secret=$_SESSION['mfa_replacement']['secret']; + $codes=$mfa->completeReplacement(1,OTPHP\TOTP::createFromSecret($secret,new MfaClock())->now(),$password); + $ok=count($codes)===10; + }else $ok=$mfa->verify(1,$payload['recovery'],$password); + $result=['ok'=>$ok]; +}catch(AppException $error){$result=['ok'=>false,'status'=>$error->status];} +ob_clean();echo json_encode($result);ob_end_flush(); diff --git a/tests/production_security.php b/tests/production_security.php index 88ea591..a9185a2 100644 --- a/tests/production_security.php +++ b/tests/production_security.php @@ -2,7 +2,7 @@ if(PHP_SAPI!=='cli')exit; if(!preg_match('/\Ahcr_http_test_[a-f0-9]{12}\z/',getenv('HCR_DB_NAME')?:''))throw new RuntimeException('A disposable test database is required.'); require __DIR__.'/../classes/Base.php';ob_start();session_start(); -$db=(new Base())->connect();$_SESSION[Base::USER_ROLE]='Administrator';$_SESSION[Base::USER_SERIAL]=1; +$db=(new Base())->connect();$_SESSION[Base::USER_ROLE]=TenantAccess::SUPER;$_SESSION[Base::USER_SERIAL]=1; $checks=0; function verify(bool $value,string $message): void {global $checks;if(!$value)throw new RuntimeException('FAILED: '.$message);$checks++;echo 'PASS: '.$message."\n";} function rejects(callable $call,string $message): void {try{$call();}catch(AppException $e){verify(true,$message);return;}throw new RuntimeException('FAILED: '.$message);} @@ -52,9 +52,9 @@ $db->exec('DELETE FROM auth_attempts');$verification->mailWorks=false;try{$verif verify((int)$db->query('SELECT COUNT(*) FROM email_verifications')->fetchColumn()===0,'Undelivered verification token is removed'); $db->exec('DELETE FROM auth_attempts');$auth->requestReset('securitymember');verify($auth->resetPassword($auth->token(),$password,$password),'Password setup/reset can also prove mailbox ownership'); verify((bool)$auth->findUser('securitymember')['user_email_verified_at'],'Mailbox ownership is verified after successful password reset'); -$edit['user_email']='stillunverified@example.test';$service->updateUser($id,$edit);$db->exec('DELETE FROM auth_attempts');ob_start();$auth->login('securitymember',$password);$_SESSION[Base::USER_ROLE]='Administrator';$_SESSION[Base::USER_SERIAL]=1;$_SESSION['auth_version']=(int)$auth->findUser('securitymember')['user_auth_version'];$auth->changePassword($id,$password,$password,$password);ob_end_clean(); +$edit['user_email']='stillunverified@example.test';$service->updateUser($id,$edit);$db->exec('DELETE FROM auth_attempts');ob_start();$auth->login('securitymember',$password);$_SESSION[Base::USER_ROLE]=TenantAccess::SUPER;$_SESSION[Base::USER_SERIAL]=1;$_SESSION['auth_version']=(int)$auth->findUser('securitymember')['user_auth_version'];$auth->changePassword($id,$password,$password,$password);ob_end_clean(); verify(!$auth->findUser('securitymember')['user_email_verified_at'],'Changing a known password does not falsely verify mailbox ownership'); -$_SESSION[Base::USER_ROLE]='Administrator';$_SESSION[Base::USER_SERIAL]=1; +$_SESSION[Base::USER_ROLE]=TenantAccess::SUPER;$_SESSION[Base::USER_SERIAL]=1; $roster=new RosterService();$club=$roster->saveClub(0,'Security Club'); rejects(fn()=>$roster->saveMember($club,0,'securitymember','active','2026-01-01'),'Unverified email cannot receive active club membership'); $db->exec('DELETE FROM auth_attempts');$verification->mailWorks=true;$verification->request('securitymember');$verification->confirm($verification->token(),$password); diff --git a/tests/project_http.py b/tests/project_http.py index a7dab23..f6eb3e6 100644 --- a/tests/project_http.py +++ b/tests/project_http.py @@ -97,8 +97,9 @@ try: # Set a known member password in this disposable fixture via the real reset flow. # Fixture token generation is intentionally scoped to httpuser, so create that # account through signup and assign it separately for isolation tests. - app.logout();_,signup,_=app.request('/?Xaction=signup') - expect(app.request(data={'action':'SignUp.createAccount','csrf_token':app.csrf(signup),'user_first_name':'Regular','user_last_name':'Member','user_email':'http@example.test','user_name':'httpuser','user_password':'HTTP long password!','user_password_confirm':'HTTP long password!'}),200,'Regular member account can sign up') + app.fixture('seedTenantInvitation',str(club_a),'1','http@example.test') + app.logout();_,signup,_=app.request('/?Xaction=signup&membership=invited') + expect(app.request(data={'action':'SignUp.createAccount','registration_kind':'invited','csrf_token':app.csrf(signup),'user_first_name':'Regular','user_last_name':'Member','user_email':'http@example.test','user_name':'httpuser','user_password':'HTTP long password!','user_password_confirm':'HTTP long password!'}),200,'Regular member account can sign up') app.login();csrf=app.token app.fixture('verifyEmail','httpuser') app.post('Roster.workspace',step='member',club_serial=club_a,identifier='httpuser',membership_status='active',joined_on='2026-01-01') diff --git a/tests/resource_concurrency.py b/tests/resource_concurrency.py new file mode 100644 index 0000000..cff6809 --- /dev/null +++ b/tests/resource_concurrency.py @@ -0,0 +1,20 @@ +import os,subprocess,time +from application_harness import Application,PHP,ROOT +app=Application() +workers=[] +try: + ids=app.fixture('tenantSeed');env=app.env.copy();env['HCR_CLUB_EXPORT_HOURLY']='5';start=str(time.time()+2) + for n in range(12): + workers.append(subprocess.Popen(PHP+['tests/resource_worker.php',str(ids['admina' if n%2 else 'admina2']),str(ids['clubA']),start],cwd=ROOT,env=env,stdout=subprocess.PIPE,stderr=subprocess.PIPE,text=True)) + outputs=[] + for worker in workers: + out,err=worker.communicate(timeout=20) + if worker.returncode:raise RuntimeError(err+out) + outputs.append(out) + assert outputs.count('allowed')==5 and outputs.count('limited')==7,outputs + print('PASS: Twelve simultaneous requests from two administrators share exactly five export slots') + print('1 resource concurrency scenario passed.') +finally: + for worker in workers: + if worker.poll() is None:worker.kill();worker.wait() + app.close() diff --git a/tests/resource_http.py b/tests/resource_http.py new file mode 100644 index 0000000..0e9deda --- /dev/null +++ b/tests/resource_http.py @@ -0,0 +1,32 @@ +import os +from application_harness import Application +for resource in ['EMAIL','TICKET','REPLY','EXPORT']:os.environ['HCR_CLUB_'+resource+'_HOURLY']='2' +app=Application();checks=0 +def check(ok,message): + global checks + if not ok:raise AssertionError(message) + checks+=1;print('PASS:',message) +def tickets():return app.fixture('inspect')['club_tickets'] +try: + ids=app.fixture('tenantSeed');a=ids['clubA'];b=ids['clubB'] + app.login('membera@example.test','Tenant test password 123!') + check(app.post('Roster.tickets',step='openTicket',club_serial=a,subject='First',message='Body')[0]==200,'First member can submit within the shared ticket budget');tid=tickets()[0]['ticket_serial'] + app.logout();app.login('shared@example.test','Tenant test password 123!') + check(app.post('Roster.tickets',step='openTicket',club_serial=a,subject='Second',message='Body')[0]==200,'Another member shares the same ticket budget') + check(app.post('Roster.tickets',step='openTicket',club_serial=a,subject='Limited',message='Body')[0]==429 and len(tickets())==2,'Club ticket limit rejects further work without partial records') + app.logout();app.login('admina2@example.test','Tenant test password 123!') + for n in range(2):check(app.post('Roster.tickets',step='reply',club_serial=a,ticket_serial=tid,message='Reply '+str(n))[0]==200,'Club reply budget permits an authorized reply') + check(app.post('Roster.tickets',step='reply',club_serial=a,ticket_serial=tid,message='Limited')[0]==429,'Club reply limit is enforced through HTTP') + check(app.post('Roster.workspace',step='invite',club_serial=a,invite_email='one@example.test')[0]==200,'Invitation email uses the shared club budget') + check(app.post('RosterReports.csv',club_serial=a)[0]==200,'Roster export uses the shared export budget') + app.logout();app.login('admina@example.test','Tenant test password 123!') + check(app.post('Roster.workspace',step='invite',club_serial=a,invite_email='two@example.test')[0]==200,'Another administrator shares the email budget') + check(app.post('Roster.workspace',step='invite',club_serial=a,invite_email='three@example.test')[0]==429,'Club email limit rejects additional invitations') + check(app.post('RosterReports.ledger',club_serial=a)[0]==200,'Different export formats share one club budget') + check(app.post('RosterReports.excel',club_serial=a)[0]==429,'Export budget applies across administrators and formats') + check(app.post('RosterReports.csv',club_serial=b)[0]==403,'An ordinary member cannot consume a foreign export budget') + app.logout();app.login('adminb@example.test','Tenant test password 123!') + check(app.post('RosterReports.csv',club_serial=b)[0]==200,'Other club exports remain available after the first club reaches its limit') + check(app.post('Roster.workspace',step='invite',club_serial=b,invite_email='beta@example.test')[0]==200,'Other club email remains available after the first club reaches its limit') + print(checks,'resource HTTP checks passed.') +finally:app.close() diff --git a/tests/resource_worker.php b/tests/resource_worker.php new file mode 100644 index 0000000..5625a46 --- /dev/null +++ b/tests/resource_worker.php @@ -0,0 +1,9 @@ +(int)$argv[1]]; +$start=(float)$argv[3];if($start>microtime(true)+5)throw new RuntimeException('Invalid start time.'); +while(microtime(true)<$start)usleep(1000); +try{(new ClubResources())->consume((int)$argv[2],'export');echo 'allowed';} +catch(AppException $e){if($e->status!==429)throw $e;echo 'limited';} diff --git a/tests/run.py b/tests/run.py index 69c9541..7cfc286 100644 --- a/tests/run.py +++ b/tests/run.py @@ -3,5 +3,5 @@ from pathlib import Path ROOT=Path(__file__).resolve().parents[1] php=json.loads(os.environ.get('PHP_TEST_COMMAND','["php"]')) if not os.environ.get('HCR_TEST_DSN'):raise SystemExit('Configure an isolated HCR_TEST_DSN before running integration tests.') -for suite in ['tests/source_checks.py','tests/auth_integration.php','tests/maintenance_unit.php','tests/auth_http.py','tests/project_http.py','tests/production_runner.py','tests/concurrency.py','tests/browser_runner.py','tests/deployment_tools.py']: +for suite in ['tests/source_checks.py','tests/mfa_key_configuration.php','tests/mfa_qr_browser_runner.py','tests/mfa_lifecycle_http.py','tests/mfa_notifications_runner.py','tests/mfa_concurrency.py','tests/auth_integration.php','tests/maintenance_unit.php','tests/auth_http.py','tests/club_onboarding_http.py','tests/member_summary_http.py','tests/member_actions_http.py','tests/project_http.py','tests/maintenance_http.py','tests/production_runner.py','tests/concurrency.py','tests/tenants_migration.py','tests/tenant_repairs_runner.py','tests/tenant_repair_concurrency.py','tests/ticket_repairs_http.py','tests/ticket_paging_http.py','tests/tenants_runner.py','tests/tenants_http.py','tests/browser_runner.py','tests/tenants_browser_runner.py','tests/ticket_repairs_browser_runner.py','tests/backup_runner.py','tests/deployment_tools.py','tests/security_capacity_http.py','tests/security_capacity_runner.py','tests/resource_http.py','tests/resource_concurrency.py']: subprocess.run((php if suite.endswith('.php') else [sys.executable])+[suite],cwd=ROOT,check=True) diff --git a/tests/security_capacity_http.py b/tests/security_capacity_http.py new file mode 100644 index 0000000..e6eeed2 --- /dev/null +++ b/tests/security_capacity_http.py @@ -0,0 +1,73 @@ +"""Real HTTP MFA, recovery, privilege and session-expiration boundaries.""" +import re +from application_harness import Application +app=Application();checks=0 +def check(ok,message): + global checks + if not ok:raise AssertionError(message) + checks+=1;print('PASS:',message) +def sign_password(email='admin@example.test',password='Admin test password 123!'): + _,body,_=app.request() + return app.request(data={'action':'SignIn.login','csrf_token':app.csrf(body),'user_email':email,'user_password':password}) +def security(body,code,password='Admin test password 123!',**extra): + return app.request(data={'action':'security','csrf_token':app.csrf(body),'mfa_code':code,'current_password':password,**extra}) +def sid():return next(c.value for c in app.client.handlers[0].cookiejar if c.name=='HUNTINGCLUBROSTER') +def age(**values): + # Find the cookie processor without assuming handler ordering. + jar=next(h.cookiejar for h in app.client.handlers if hasattr(h,'cookiejar')) + cookie=next(c.value for c in jar if c.name=='HUNTINGCLUBROSTER') + app.fixture('sessionAge',cookie,str(values.get('absolute','')),str(values.get('idle','')),str(values.get('recent',''))) +try: + ids=app.fixture('tenantSeed') + status,body,_=sign_password() + check(status==200 and b'setup key' in body,'Password alone exposes setup and no administrator workspace') + token=app.csrf(body) + check(app.request(data={'action':'Users.deleteUser','csrf_token':token,'user_serial':str(ids['membera'])},ajax=True)[0]==403,'AJAX cannot bypass mandatory enrollment') + check(app.request('/main.php?Xaction=Roster.workspace&club_serial='+str(ids['clubA']))[1].find(b'setup key')>=0,'Direct club URLs cannot bypass enrollment') + check(app.request(data={'action':'security','mfa_code':'000000','current_password':'Admin test password 123!'})[0]==403,'MFA enrollment requires CSRF') + secret=re.search(rb'
    ([A-Z2-7]+)
    ',body).group(1).decode();code=app.totp(secret) + _,bad,_=security(body,code,'incorrect password') + check(b'Current password is incorrect' in bad and not app.fixture('mfaState','admin@example.test')['factor'],'Setup requires the current password and commits no partial factor') + status,body,_=security(bad,code) + codes=[c.decode() for c in re.findall(rb'\b[a-f0-9]{32}\b',body)] + check(status==200 and len(codes)==10 and b'Save your recovery codes' in body,'Valid setup shows ten recovery codes once') + state=app.fixture('mfaState','admin@example.test') + check(secret not in state['factor']['secret_cipher'] and all(c not in state['recovery'] for c in codes),'Database stores encrypted secret and hashed recovery codes') + _,body,_=app.request();app.token=app.csrf(body) + check(b'Save your recovery codes' not in body,'Recovery code plaintext is absent on subsequent pages') + app.logout();_,body,_=sign_password() + check(b'setup key' not in body and b'Authentication code' in body,'Enrolled administrator must supply a second factor on a new login') + _,body,_=security(body,code) + check(b'Password or authentication code is incorrect' in body,'An authenticator code already used during setup cannot be replayed') + _,body,_=security(body,codes[0]);app.token=app.csrf(body) + check(b'Club workspace' in body and len(app.fixture('mfaState','admin@example.test')['recovery'])==9,'Recovery code completes login and is consumed') + app.logout();_,body,_=sign_password();_,body,_=security(body,codes[0]) + check(b'Password or authentication code is incorrect' in body,'Consumed recovery code cannot be reused') + _,body,_=security(body,codes[1]);app.token=app.csrf(body) + age(recent=301) + check(app.post('Users.changePassword')[0]==403,'Administrator password changes also require recent second-factor confirmation') + check(app.post('Roster.workspace',step='member',club_serial=ids['clubA'],membership_serial=ids['clubA_shared'],membership_status='active',joined_on='2026-01-01',membership_role='administrator')[0]==403,'Privilege changes reject stale recent authentication') + _,body,_=app.request('/main.php?Xaction=security');_,body,_=security(body,codes[2]);app.token=app.csrf(body) + check(app.post('Roster.workspace',step='member',club_serial=ids['clubA'],membership_serial=ids['clubA_shared'],membership_status='active',joined_on='2026-01-01',membership_role='administrator')[0]==200,'Privilege change succeeds after fresh password and second factor') + age(absolute=28800,idle=0) + check(app.post('toggleTheme')[0]==401,'Active session still expires at the eight-hour absolute boundary') + _,body,_=sign_password();_,body,_=security(body,codes[3]);app.token=app.csrf(body);age(absolute=28799,idle=1801) + check(app.post('toggleTheme')[0]==401,'Idle timeout remains enforced independently') + _,body,_=sign_password();_,body,_=security(body,codes[4]);app.token=app.csrf(body) + _,body,_=app.request('/main.php?Xaction=security');_,body,_=security(body,codes[5],factor_action='replace') + check(b'setup key' in body and app.fixture('mfaState','admin@example.test')['factor'] and len(app.fixture('mfaState','admin@example.test')['recovery'])==4,'Pending replacement preserves the old factor and remaining recovery codes') + check(b'Club workspace' in app.request('/main.php?Xaction=Roster.workspace')[1],'Authorized session retains its existing MFA access during replacement') + newsecret=re.search(rb'
    ([A-Z2-7]+)
    ',body).group(1).decode() + check(newsecret!=secret,'Replacement generates a fresh authenticator secret') + status,limited,_=security(body,app.totp(newsecret),factor_action='confirmReplacement') + check(status==429 and b'Too many authentication attempts' in limited,'Repeated MFA attempts enforce a persistent account budget') + app.fixture('clearTestAttempts') + _,body,_=security(limited,app.totp(newsecret),factor_action='confirmReplacement');check(b'Save your recovery codes' in body,'Replacement authenticator can be enrolled with fresh recovery codes') + _,body,_=app.request();app.token=app.csrf(body);app.logout();app.login('membera@example.test','Tenant test password 123!') + check(b'Club workspace' in app.request()[1],'Ordinary unenrolled members retain password login') + app.logout();_,body,_=sign_password('shared@example.test','Tenant test password 123!') + check(b'setup key' in body,'Newly promoted administrator must enroll despite an ordinary global account role') + print(checks,'security capacity HTTP checks passed.') +except Exception: + app.log.seek(0);print(app.log.read().decode(errors='replace'));raise +finally:app.close() diff --git a/tests/security_capacity_runner.py b/tests/security_capacity_runner.py new file mode 100644 index 0000000..07e1ba8 --- /dev/null +++ b/tests/security_capacity_runner.py @@ -0,0 +1,20 @@ +import json,os,subprocess +from application_harness import Application,PHP,ROOT +os.environ['HCR_EXPORT_MAX_ROWS']='30' +app=Application() +try: + ids=app.fixture('tenantSeed');app.env['HCR_TENANT_IDS']=json.dumps(ids) + subprocess.run(PHP+['tests/capacity_service.php'],cwd=ROOT,env=app.env,check=True) + app.login('admina2@example.test','Tenant test password 123!');checks=0 + for scope in ['members','seasons','dues','payments','adjustments','invitations']: + status,body,_=app.request('/main.php?Xaction=Roster.workspace&club_serial='+str(ids['clubA'])+'&'+scope+'_page=9999') + assert status==200 and ('aria-label="'+scope+' pages"').encode() in body,(scope,status,body[:500]) + checks+=1;print('PASS:',scope,'pager opens the final page through HTTP') + status,body,_=app.request('/main.php?Xaction=RosterReports.catalog&clubs_page=9999') + assert status==200 and b'Tenant Alpha' in body and b'Tenant Beta' not in body + checks+=1;print('PASS: Read-only report catalog paging retains managed-club scope') + for route in ['csv','excel','pdf','ledger']: + assert app.post('RosterReports.'+route,club_serial=ids['clubA'])[0]==422 + checks+=1;print('PASS:',route,'export rejects the oversized selection through HTTP') + print(checks,'capacity page HTTP checks passed.') +finally:app.close() diff --git a/tests/source_checks.py b/tests/source_checks.py index 8e66d56..d891581 100644 --- a/tests/source_checks.py +++ b/tests/source_checks.py @@ -18,3 +18,9 @@ assert base64.b64encode(hashlib.sha256((ROOT/dependency['file']).read_bytes()).d assert not (ROOT/'js/jquery-3.2.0.min.js').exists() assert all('jquery-3.2.0' not in file.read_text(encoding='utf-8-sig') for file in styles) print(f'Source checks passed: {len(files)} PHP files, {len(scripts)} JavaScript files, {len(styles)} XSL stylesheets, and jQuery integrity.') + +editor=json.loads((ROOT/'browser-dependencies.json').read_text())['suneditor'] +for name,digest in editor['files'].items():assert hashlib.sha256((ROOT/name).read_bytes()).hexdigest()==digest +assert not (ROOT/'js/ckeditor.js').exists() +assert all('ckeditor.js' not in file.read_text(encoding='utf-8-sig') for file in styles) +print('SunEditor asset integrity and obsolete editor removal passed.') diff --git a/tests/tenant_repair_concurrency.py b/tests/tenant_repair_concurrency.py new file mode 100644 index 0000000..b4ed0fd --- /dev/null +++ b/tests/tenant_repair_concurrency.py @@ -0,0 +1,26 @@ +import json,subprocess +from application_harness import Application,PHP,ROOT +for operation in ['activate','deactivate']: + app=Application();workers=[] + try: + ids=app.fixture('tenantSeed');env=app.env.copy();env['HCR_TENANT_IDS']=json.dumps(ids) + record=app.fixture('repairConcurrencySeed',str(ids['clubA']),str(ids['invitee']),str(ids['admina'])) + for mode,ident,ready in [(operation,record['membership'],'LOCKED'),('accept',record['invitation'],'WAITING')]: + p=subprocess.Popen(PHP+['tests/tenant_repair_worker.php',mode,str(ident)],cwd=ROOT,env=env,stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.PIPE,text=True);workers.append(p) + assert p.stdout.readline().strip()==ready,p.stderr.read() + workers[0].stdin.write('go\n');workers[0].stdin.flush();results=[] + for p in workers: + output,error=p.communicate(timeout=20);assert p.returncode==0,error+output;results.append(json.loads(output)) + if operation=='activate': + assert all(x['ok'] for x in results),results + assert sum(x['user_serial']==ids['invitee'] and x['club_serial']==ids['clubA'] for x in app.fixture('inspect')['club_memberships'])==1 + print('PASS: Invitation acceptance racing membership activation completes both requests without duplicate membership.') + else: + assert results[0]['ok'] and not results[1]['ok'] and results[1]['status']==404,results + member=next(x for x in app.fixture('inspect')['club_memberships'] if x['membership_serial']==record['membership']);assert member['membership_status']=='inactive' + print('PASS: Membership deactivation racing acceptance revokes the invitation and preserves denied access.') + finally: + for p in workers: + if p.poll() is None:p.terminate();p.wait(timeout=10) + app.close() +print('2 tenant repair concurrency scenarios passed.') diff --git a/tests/tenant_repair_worker.php b/tests/tenant_repair_worker.php new file mode 100644 index 0000000..e43e56c --- /dev/null +++ b/tests/tenant_repair_worker.php @@ -0,0 +1,24 @@ +getSettings(); +if(!preg_match('/\Ahcr_http_test_[a-f0-9]{12}\z/',(string)$settings->DatabaseName)||!in_array((string)$settings->DatabaseServer,['127.0.0.1','localhost'],true))throw new RuntimeException('Disposable local database required.'); +$ids=json_decode(getenv('HCR_TENANT_IDS'),true,512,JSON_THROW_ON_ERROR);$operation=$argv[1]; +class RepairLockStatement extends PDOStatement { + protected function __construct(private string $operation){} + public function execute(?array $params=null):bool{ + if($this->operation==='accept'&&str_starts_with($this->queryString,'SELECT user_serial,user_email,user_email_verified_at,user_status')){echo "WAITING\n";flush();} + $ok=parent::execute($params); + if($this->operation!=='accept'&&str_starts_with($this->queryString,'SELECT user_serial,user_status,user_email_verified_at')){echo "LOCKED\n";flush();fgets(STDIN);} + return $ok; + } +} +$db=new PDO('mysql:host='.$settings->DatabaseServer.';port='.$settings->DatabasePort.';dbname='.$settings->DatabaseName.';charset=utf8mb4',(string)$settings->DatabaseUser,(string)$settings->DatabasePassword,[PDO::ATTR_ERRMODE=>PDO::ERRMODE_EXCEPTION,PDO::ATTR_DEFAULT_FETCH_MODE=>PDO::FETCH_ASSOC,PDO::ATTR_EMULATE_PREPARES=>false,PDO::ATTR_STATEMENT_CLASS=>[RepairLockStatement::class,[$operation]]]);$db->exec('SET innodb_lock_wait_timeout=5'); +class LockedRepairInvitations extends ClubInvitations {public function __construct(private PDO $db){}public function connect():PDO{return $this->db;}} +class LockedRepairMembers extends RosterService {public function __construct(private PDO $db){}public function connect():PDO{return $this->db;}} +$_SESSION=[Base::USER_SERIAL=>$operation==='accept'?$ids['invitee']:1,Base::USER_NAME=>'Concurrency tester']; +try{ + if($operation==='accept')(new LockedRepairInvitations($db))->accept((int)$argv[2]); + else (new LockedRepairMembers($db))->saveMember($ids['clubA'],(int)$argv[2],'',$operation==='deactivate'?'inactive':'active','2026-01-01'); + echo json_encode(['ok'=>true]),"\n"; +}catch(AppException $e){echo json_encode(['ok'=>false,'status'=>$e->status]),"\n";} diff --git a/tests/tenant_repairs.php b/tests/tenant_repairs.php new file mode 100644 index 0000000..c3f78be --- /dev/null +++ b/tests/tenant_repairs.php @@ -0,0 +1,32 @@ +connect();$ids=json_decode(getenv('HCR_TENANT_IDS'),true,512,JSON_THROW_ON_ERROR);$checks=0; +function repairCheck(bool $ok,string $message):void{global $checks;if(!$ok)throw new RuntimeException($message);$checks++;echo 'PASS: '.$message."\n";} +function repairActor(int $id):void{global $db;$s=$db->prepare('SELECT * FROM users WHERE user_serial=?');$s->execute([$id]);$u=$s->fetch();$_SESSION=[Base::USER_SERIAL=>$id,Base::USER_NAME=>$u['user_name'],Base::USER_ROLE=>$u['user_role']];} +class RepairInvitations extends ClubInvitations {protected function deliver(string $email,string $club):bool{return true;}} +$roster=new RosterService();$invites=new RepairInvitations();$access=new TenantAccess(); +function invitationId(int $club,string $email):int{global $db;$s=$db->prepare('SELECT invitation_serial FROM club_invitations WHERE club_serial=? AND invite_email=?');$s->execute([$club,$email]);return (int)$s->fetchColumn();} +function ageInvitations():void{global $db;$db->exec('UPDATE club_invitations SET sent_at=DATE_SUB(UTC_TIMESTAMP(),INTERVAL 2 MINUTE)');} +repairActor(1);$roster->saveMember($ids['clubA'],$ids['clubA_admina'],'','inactive','2026-01-01','administrator'); +repairActor($ids['admina2']);$invites->invite($ids['clubA'],'admina@example.test','member'); +repairActor($ids['admina']);$invites->accept(invitationId($ids['clubA'],'admina@example.test')); +repairCheck(!$access->canManage($ids['clubA']),'Member invitation cannot restore an inactive administrator role'); +$row=$db->query('SELECT membership_role,membership_status FROM club_memberships WHERE membership_serial='.$ids['clubA_admina'])->fetch(); +repairCheck($row['membership_role']==='member'&&$row['membership_status']==='active','Former administrator rejoins as the newly approved member role'); +repairCheck(!$access->canManage($ids['clubB']),'Rejoining cannot change an ordinary membership in another club'); +repairActor(1);ageInvitations();$invites->invite($ids['clubA'],'admina@example.test','administrator'); +repairActor($ids['admina']);$invites->accept(invitationId($ids['clubA'],'admina@example.test')); +repairCheck($access->canManage($ids['clubA']),'Fresh Super System Administrator invitation can explicitly restore administrator access'); +repairActor($ids['admina2']);$invites->invite($ids['clubA'],'admina2@example.test','member');$invites->accept(invitationId($ids['clubA'],'admina2@example.test')); +repairCheck($access->canManage($ids['clubA']),'Member invitation does not accidentally demote an already active administrator'); +repairActor(1);$invites->invite($ids['clubA'],'membera@example.test','administrator'); +$pending=invitationId($ids['clubA'],'membera@example.test');$roster->saveMember($ids['clubA'],$ids['clubA_membera'],'','active','2026-01-01','administrator'); +repairCheck($db->query('SELECT invitation_status FROM club_invitations WHERE invitation_serial='.$pending)->fetchColumn()==='revoked','Explicit role changes revoke outstanding invitations for that membership'); +ageInvitations();$invites->invite($ids['clubA'],'membera@example.test','administrator');$pending=invitationId($ids['clubA'],'membera@example.test');$roster->saveMember($ids['clubA'],$ids['clubA_membera'],'','active','2026-01-01','member'); +repairActor($ids['membera']);try{$invites->accept($pending);throw new RuntimeException('Stale invitation was accepted');}catch(AppException $e){repairCheck($e->status===404,'A pending administrator invitation cannot undo a later explicit demotion');} +ageInvitations();repairActor($ids['admina2']);$invites->invite($ids['clubA'],'shared@example.test','member');repairActor(1);$roster->saveMember($ids['clubA'],$ids['clubA_shared'],'','inactive','2026-01-01'); +repairActor($ids['shared']);try{$invites->accept(invitationId($ids['clubA'],'shared@example.test'));throw new RuntimeException('Deactivation invitation accepted');}catch(AppException $e){repairCheck($e->status===404,'Membership deactivation still invalidates outstanding invitations');} +repairCheck(count($roster->clubs())===1&&(int)$roster->clubs()[0]['club_serial']===$ids['clubB'],'Deactivation leaves access to the other club intact'); +echo "$checks tenant repair service checks passed.\n"; diff --git a/tests/tenant_repairs_runner.py b/tests/tenant_repairs_runner.py new file mode 100644 index 0000000..1ea303e --- /dev/null +++ b/tests/tenant_repairs_runner.py @@ -0,0 +1,8 @@ +import json,subprocess +from application_harness import Application,PHP,ROOT +app=Application() +try: + env=app.env.copy();env['HCR_TENANT_IDS']=json.dumps(app.fixture('tenantSeed')) + subprocess.run(PHP+['tests/tenant_repairs.php'],cwd=ROOT,env=env,check=True) + subprocess.run(PHP+['tests/transaction_retries.php'],cwd=ROOT,env=env,check=True) +finally:app.close() diff --git a/tests/tenants_browser.js b/tests/tenants_browser.js new file mode 100644 index 0000000..c7a108b --- /dev/null +++ b/tests/tenants_browser.js @@ -0,0 +1,46 @@ +const {chromium}=require('playwright'); +const assert=require('node:assert/strict'); +(async()=>{ + const browser=await chromium.launch({executablePath:process.env.HCR_TEST_CHROME||'C:/Program Files/Google/Chrome/Application/chrome.exe',headless:true}); + const adminContext=await browser.newContext(),memberContext=await browser.newContext(); + const admin=await adminContext.newPage(),member=await memberContext.newPage(),errors=[];let checks=0; + for(const page of [admin,member])page.on('pageerror',e=>errors.push(e.message)); + const pass=message=>{checks++;console.log('PASS: '+message);}; + const base=process.env.HCR_TEST_URL,ids=JSON.parse(process.env.HCR_TENANT_IDS); + async function login(page,email,password='Tenant test password 123!'){await page.goto(base+'/main.php');await page.locator('#user_email').fill(email);await page.locator('#user_password').fill(password);await Promise.all([page.waitForNavigation(),page.locator('#login button[type=submit]').click()]);await require('./browser_mfa')(page,password);} + try{ + const ownerContext=await browser.newContext(),owner=await ownerContext.newPage();owner.on('pageerror',e=>errors.push(e.message)); + await login(owner,'admin@example.test','Admin test password 123!'); + const cards=owner.locator('.card').filter({has:owner.getByRole('link',{name:'Open club',exact:true})});assert.equal(await cards.count(),2); + const first=await cards.nth(0).boundingBox(),second=await cards.nth(1).boundingBox();assert(Math.abs(first.y-second.y)<2 && second.x>first.x);pass('Multiple accessible clubs appear side by side after login'); + await owner.setViewportSize({width:390,height:844});const mobileFirst=await cards.nth(0).boundingBox(),mobileSecond=await cards.nth(1).boundingBox();assert(mobileSecond.y>=mobileFirst.y+mobileFirst.height && mobileSecond.x===mobileFirst.x);assert(await owner.evaluate(()=>document.documentElement.scrollWidth<=window.innerWidth));pass('Club cards stack without horizontal overflow on phones');await owner.setViewportSize({width:1280,height:720}); + const singleContext=await browser.newContext(),single=await singleContext.newPage();await login(single,'membera@example.test');assert(new URL(single.url()).searchParams.get('club_serial')===String(ids.clubA));assert.equal(await single.getByRole('heading',{name:'Tenant Alpha',exact:true}).count(),1);assert.equal(await single.locator('.club-action-modal').count(),0);await singleContext.close();pass('A member with one club lands directly in its read-only workspace'); + await owner.goto(base+'/main.php?Xaction=Roster.workspace&club_serial='+ids.clubA); + assert.equal(await owner.locator('.clubSummary h1').textContent(),'Tenant Alpha');assert.equal(await owner.locator('.clubSummary').getByRole('button',{name:'Create club',exact:true}).count(),0);assert(await owner.locator('.clubSummary header').getByRole('link',{name:'Switch club',exact:true}).count());pass('Club summary starts with club identity and actions, without a creation form'); + await owner.getByRole('link',{name:'Create club',exact:true}).click();await owner.getByRole('heading',{name:'Create club',exact:true}).waitFor();pass('Super Administrator creates clubs from a separate page');await owner.goto(base+'/main.php?Xaction=Roster.workspace&club_serial='+ids.clubA); + await owner.locator('tr').filter({hasText:'shared@example.test'}).locator('[data-club-step=member]').click();const assignment=owner.locator('.club-action-modal.show form');await assignment.locator('select[name=membership_role]').selectOption('administrator');await Promise.all([owner.waitForNavigation(),assignment.getByRole('button',{name:'Save membership',exact:true}).click()]); + await owner.locator('tr').filter({hasText:'shared@example.test'}).locator('[data-club-step=member]').waitFor();assert((await owner.locator('tr').filter({hasText:'shared@example.test'}).textContent()).includes('administrator'));pass('Super System Administrator can appoint an administrator through the club membership form'); + await ownerContext.close(); + await login(admin,'admina2@example.test');assert(new URL(admin.url()).searchParams.get('club_serial')===String(ids.clubA));pass('An administrator with one club lands directly in the club after MFA');await admin.goto(base+'/main.php?Xaction=Roster.workspace&club_serial='+ids.clubA); + assert.equal(await admin.locator('.setup-users,.view-journal').count(),0);assert(!await admin.getByRole('link',{name:'Tenant Beta',exact:true}).count());pass('Club administrator browser navigation hides global controls and unrelated clubs'); + if(process.env.HCR_UI_SCREENSHOT)await admin.screenshot({path:process.env.HCR_UI_SCREENSHOT}); + await admin.setViewportSize({width:390,height:844});if(process.env.HCR_UI_SCREENSHOT)await admin.screenshot({path:process.env.HCR_UI_SCREENSHOT.replace('.png','-mobile.png')});assert(await admin.evaluate(()=>document.documentElement.scrollWidth<=window.innerWidth));pass('Club summary actions and tables fit a phone-width screen'); + await admin.locator('header [data-club-step=invite]').click();await admin.waitForFunction(()=>document.activeElement?.name==='invite_email');const mobileDialog=await admin.locator('.club-action-modal.show .modal-dialog').boundingBox();assert(mobileDialog.x>=0 && mobileDialog.x+mobileDialog.width<=390);await admin.keyboard.press('Escape');await admin.locator('.club-action-modal.show').waitFor({state:'hidden'});await admin.waitForFunction(()=>document.activeElement?.dataset.clubStep==='invite');pass('Phone dialog fits the screen, focuses its first field and restores focus after Escape');await admin.setViewportSize({width:1280,height:720}); + await admin.getByRole('link',{name:'Tenant Membera',exact:true}).click();await admin.getByRole('heading',{name:'Tenant Membera',exact:true}).waitFor();assert((await admin.locator('.memberSummary').textContent()).includes('$3,119.00'));assert.equal(await admin.locator('.memberSummary input:visible,.memberSummary select:visible').count(),0);pass('Roster name opens the selected member summary with corrected totals and hidden action forms'); + await admin.locator('nav[aria-label="dues pages"]').getByRole('link',{name:'Next',exact:true}).click();assert((await admin.locator('.memberSummary').textContent()).includes('$3,119.00'));assert(new URL(admin.url()).searchParams.get('membership_serial')===String(ids.clubA_membera));pass('Member summary paging retains the selected member and complete totals'); + if(process.env.HCR_UI_SCREENSHOT)await admin.screenshot({path:process.env.HCR_UI_SCREENSHOT.replace('.png','-member.png')});await admin.setViewportSize({width:390,height:844});assert(await admin.evaluate(()=>document.documentElement.scrollWidth<=window.innerWidth));pass('Member summary totals and history fit phone-width screens');await admin.setViewportSize({width:1280,height:720}); + await admin.locator('nav[aria-label="Member actions"] [data-club-step=member]').click();await admin.locator('.club-action-modal.show').getByLabel('Joined on',{exact:true}).fill('2026-02-01');await Promise.all([admin.waitForNavigation(),admin.locator('.club-action-modal.show').getByRole('button',{name:'Save membership',exact:true}).click()]);assert((await admin.locator('.memberSummary header').textContent()).includes('2026-02-01'));assert(new URL(admin.url()).searchParams.get('membership_serial')===String(ids.clubA_membera));pass('Administrator edits membership in a modal and remains on the same member summary'); + await admin.locator('[data-club-step=charge]').click();await admin.locator('.club-action-modal.show').getByLabel('Season',{exact:true}).selectOption({label:'Available new season'});await admin.locator('.club-action-modal.show').getByLabel('Dues (USD)',{exact:true}).fill('20.00');await Promise.all([admin.waitForNavigation(),admin.locator('.club-action-modal.show').getByRole('button',{name:'Save dues',exact:true}).click()]);assert((await admin.locator('.memberSummary').textContent()).includes('$3,170.00'));pass('Administrator adds dues for the preselected member without returning to the club'); + await admin.getByRole('row').filter({hasText:'Available new season'}).locator('[data-club-step=payment]').click();await admin.locator('.club-action-modal.show').getByLabel('Payment (USD)',{exact:true}).fill('10.00');await admin.locator('.club-action-modal.show').getByLabel('Reference (optional)',{exact:true}).fill('Summary modal payment');await Promise.all([admin.waitForNavigation(),admin.locator('.club-action-modal.show').getByRole('button',{name:'Record payment',exact:true}).click()]);assert((await admin.locator('.memberSummary').textContent()).includes('$3,129.00'));await admin.getByText('Summary modal payment',{exact:false}).waitFor();pass('Administrator records a selected season payment and sees updated totals on the member summary'); + await admin.getByRole('link',{name:'Back to club roster',exact:true}).click();await admin.getByRole('heading',{name:'Tenant Alpha',exact:true}).waitFor(); + await admin.locator('header [data-club-step=invite]').click();const invite=admin.locator('form').filter({has:admin.getByRole('button',{name:'Send club invitation',exact:true})});await invite.getByLabel('Invitation email').fill('invitee@example.test');await invite.getByRole('button',{name:'Send club invitation',exact:true}).click();await admin.getByText('The invitation email could not be sent.',{exact:false}).waitFor();pass('Administrator sends a club invitation and sees delivery failure clearly'); + await login(member,'invitee@example.test');assert(await member.getByText('You are not assigned to an active club yet.',{exact:false}).count());pass('Accounts without a club retain the empty workspace and invitation access');await member.goto(base+'/main.php?Xaction=Roster.invitations');await member.getByRole('heading',{name:'Tenant Alpha',exact:true}).waitFor();await member.getByRole('button',{name:'Accept invitation',exact:true}).click();await member.getByRole('heading',{name:'Tenant Alpha',exact:true}).waitFor();assert.equal(await member.getByRole('button',{name:'Send club invitation',exact:true}).count(),0);pass('Invited member accepts the club invitation and receives a read-only workspace'); + await member.getByRole('link',{name:'Tenant Invitee',exact:true}).click();await member.getByRole('heading',{name:'Tenant Invitee',exact:true}).waitFor();await member.getByText('No dues recorded for this membership.',{exact:true}).waitFor();await member.getByText('No payments recorded for this membership.',{exact:true}).waitFor();pass('Member opens their own summary and sees clear empty financial histories');await member.getByRole('link',{name:'Back to club roster',exact:true}).click(); + await member.getByRole('link',{name:'My tickets',exact:true}).click();const form=member.locator('form').filter({has:member.getByRole('button',{name:'Submit ticket',exact:true})});await form.getByLabel('Subject',{exact:true}).fill('Browser membership question');await form.getByLabel('Message',{exact:true}).fill('Please review my membership.');await form.getByRole('button',{name:'Submit ticket',exact:true}).click();await member.getByRole('heading',{name:'Browser membership question',exact:true}).waitFor();pass('Member submits a private club ticket through the browser'); + await admin.goto(base+'/main.php?Xaction=Roster.tickets&club_serial='+ids.clubA);await admin.getByRole('link',{name:/Browser membership question/}).click();const reply=admin.locator('form').filter({has:admin.getByRole('button',{name:'Send reply',exact:true})});await reply.getByLabel('Reply',{exact:true}).fill('Your membership is active.');await reply.getByLabel('Status',{exact:true}).selectOption('closed');await reply.getByRole('button',{name:'Send reply',exact:true}).click();await admin.getByText('Status: closed',{exact:true}).waitFor();pass('Assigned club administrator replies to and closes the member ticket'); + await member.reload();await member.getByText('Your membership is active.',{exact:true}).waitFor();assert.equal(await member.getByRole('button',{name:'Send reply',exact:true}).count(),0);pass('Member sees the response and cannot change a closed ticket'); + const signupContext=await browser.newContext(),signup=await signupContext.newPage();signup.on('pageerror',e=>errors.push(e.message));await signup.goto(base+'/main.php?Xaction=signup');await signup.getByLabel('New club name',{exact:true}).fill('Browser Signup Club');await signup.getByLabel('First name',{exact:true}).fill('Browser');await signup.getByLabel('Last name',{exact:true}).fill('Owner');await signup.getByLabel('Email address',{exact:true}).fill('browserowner@example.test');await signup.getByLabel('Username',{exact:true}).fill('browserowner');await signup.getByLabel('Password',{exact:true}).fill('Browser owner password 123!');await signup.getByLabel('Confirm password',{exact:true}).fill('Browser owner password 123!');await signup.getByRole('button',{name:'Create account',exact:true}).click();await signup.getByText('Your account has been created.',{exact:false}).waitFor();pass('Browser signup registers a new club and its administrator');await signup.goto(base+'/main.php?Xaction=signup&membership=invited');assert.equal(await signup.getByLabel('New club name',{exact:true}).count(),0);await signup.getByText('Use the email address your club administrator invited.',{exact:false}).waitFor();pass('Invited members have a separate account signup without a club creation field');await signupContext.close(); + assert.deepEqual(errors,[]);pass('Tenant invitation and ticket flows produce no browser script errors'); + }catch(error){console.error('OPEN DIALOG:',await admin.locator('.club-action-modal.show').textContent().catch(()=>''));if(process.env.HCR_UI_SCREENSHOT)await admin.screenshot({path:process.env.HCR_UI_SCREENSHOT.replace('.png','-failure.png')});throw error;}finally{await browser.close();} + console.log(checks+' tenant browser checks passed.'); +})().catch(e=>{console.error(e);process.exitCode=1;}); diff --git a/tests/tenants_browser_runner.py b/tests/tenants_browser_runner.py new file mode 100644 index 0000000..fe0699f --- /dev/null +++ b/tests/tenants_browser_runner.py @@ -0,0 +1,8 @@ +import json,os,subprocess +from application_harness import Application,ROOT +app=Application() +try: + env=app.env.copy();env['HCR_TEST_URL']=app.base;ids=app.fixture('tenantSeed');env['HCR_TENANT_IDS']=json.dumps(ids) + app.fixture('memberSummarySeed',str(ids['clubA']),str(ids['clubB']),str(ids['clubA_membera']),str(ids['clubA_shared']),str(ids['clubB_shared'])) + subprocess.run([env.get('NODE_TEST_COMMAND','node'),'tests/tenants_browser.js'],cwd=ROOT,env=env,check=True) +finally:app.close() diff --git a/tests/tenants_http.py b/tests/tenants_http.py new file mode 100644 index 0000000..897d2bf --- /dev/null +++ b/tests/tenants_http.py @@ -0,0 +1,64 @@ +import json,secrets,subprocess +from application_harness import Application,PHP,ROOT + +app=Application();checks=[] +def check(ok,message): + if not ok:raise AssertionError(message) + checks.append(message);print('PASS: '+message) +def expect(response,status,message): + check(response[0]==status,message+' (HTTP '+str(response[0])+')');return response[1] +def login(who):app.logout();app.login(who+'@example.test','Tenant test password 123!') +def workspace(club):return app.request('/main.php?Xaction=Roster.workspace&club_serial='+str(club)) +try: + ids=app.fixture('tenantSeed');a,b=ids['clubA'],ids['clubB'];app.login() + before=app.fixture('fingerprints');subprocess.run(PHP+['bin/migrate-tenants.php'],cwd=ROOT,env=app.env,check=True,capture_output=True);check(app.fixture('fingerprints')==before,'Tenant migration is idempotent without changing existing rows or promoting accounts') + for club,label,member in [(a,'Alpha',ids['clubA_membera']),(b,'Beta',ids['clubB_memberb'])]: + expect(app.post('Roster.workspace',step='season',club_serial=club,season_name=label+' Season',starts_on='2026-01-01',ends_on='2026-12-31'),200,'Super administrator adds '+label+' season') + season=app.fixture('inspect')['club_seasons'][-1]['season_serial'] + expect(app.post('Roster.workspace',step='charge',club_serial=club,membership_serial=member,season_serial=season,amount='100.00'),200,'Super administrator records '+label+' dues') + data=app.fixture('inspect');dueA=next(x for x in data['club_dues'] if x['club_serial']==a)['due_serial'];dueB=next(x for x in data['club_dues'] if x['club_serial']==b)['due_serial'];seasonB=next(x for x in data['club_seasons'] if x['club_serial']==b)['season_serial'] + login('admina2') + body=expect(workspace(a),200,'Assigned club administrator can open the club with global User role');check(b'membera@example.test' in body and b'shared@example.test' in body and b'memberb@example.test' not in body,'Club administrator sees all shared-club members and no unrelated tenant members') + home=app.request('/main.php?Xaction=Roster.workspace')[1];check(b'Tenant Beta' not in home and b'setup-users' not in home and b'view-journal' not in home,'Club administrator navigation hides other tenants and global administration') + for action,fields in [ + ('Users.setupUsers',{}),('Users.userSummary',{'user_serial':ids['memberb']}),('Users.editUser',{'step':'prompt','user_serial':ids['membera']}),('Users.editUser',{'step':'update','user_serial':ids['memberb'],'user_role':'Super System Administrator'}), + ('Users.addUser',{'step':'add','user_email':'probe@example.test'}),('Users.deleteUser',{'user_serial':ids['memberb']}),('Users.resetPassword',{'user_serial':ids['memberb']}),('Users.updateActiveStatus',{'user_serial':ids['memberb'],'user_active':'false'}),('Users.userExists',{'user_name':'tenantmemberb'}),('Users.getUser_AJAX',{'user_name':'tenantmemberb'}),('Users.userActive',{'user_serial':ids['memberb']}), + ('Notes.addNote',{'step':'add','note_type':'User','note_reference':ids['memberb'],'note_text':'Foreign note'}),('Journal.viewJournal',{}),('Alerts.setupAlerts',{}),('Popovers.setupPopovers',{}),('Statuses.setupStatuses',{}),('Dropdowns.setupDropdowntypes',{})]: + expect(app.post(action,**fields),403,'Club administrator cannot use global route '+action) + expect(workspace(b),403,'Changing the URL cannot open an unrelated tenant') + before=app.fixture('fingerprints') + for step,fields in [('club',{'club_name':'Stolen tenant'}),('member',{'membership_serial':ids['clubB_memberb'],'membership_status':'inactive','joined_on':'2026-01-01'}),('season',{'season_name':'Foreign season','starts_on':'2026-01-01','ends_on':'2026-12-31'}),('charge',{'membership_serial':ids['clubB_memberb'],'season_serial':seasonB,'amount':'10.00'}),('payment',{'due_serial':dueB,'amount':'10.00','paid_on':'2026-01-01','request_key':secrets.token_hex(32)}),('adjust',{'due_serial':dueB,'corrected_amount':'90.00','reason':'Foreign','request_key':secrets.token_hex(32)}),('invite',{'invite_email':'foreign@example.test'})]: + expect(app.post('Roster.workspace',step=step,club_serial=b,**fields),403,'Foreign tenant rejects '+step+' mutation') + check(app.fixture('fingerprints')==before,'Rejected cross-tenant writes leave all stored tables unchanged') + for export in ['csv','excel','pdf','ledger']:expect(app.post('RosterReports.'+export,club_serial=b),403,'Foreign tenant denies '+export+' export') + report=expect(app.post('Reports.selectReport'),200,'Club administrator can open scoped reports');check(b'Tenant Alpha' in report and b'Tenant Beta' not in report,'Report catalog includes only managed clubs') + csv=expect(app.post('RosterReports.csv',club_serial=a),200,'Club administrator can export the assigned club');check(b'membera@example.test' in csv and b'memberb@example.test' not in csv,'Roster export contains only the selected tenant') + expect(app.post('Roster.workspace',step='payment',club_serial=a,due_serial=dueB,amount='10.00',paid_on='2026-01-01',request_key=secrets.token_hex(32)),404,'A foreign dues ID cannot be paired with an allowed club') + expect(app.post('Roster.workspace',step='payment',club_serial=a,due_serial=dueA,amount='10.00',paid_on='2026-01-01',request_key=secrets.token_hex(32)),200,'Club administrator can record payment for an assigned-club member') + expect(app.post('Roster.workspace',step='invite',club_serial=a,invite_email='invitee@example.test',membership_role='administrator'),403,'Club administrator cannot forge an administrator invitation') + users_before=app.fixture('fingerprints')['users'];invite_body=expect(app.post('Roster.workspace',step='invite',club_serial=a,invite_email='invitee@example.test'),200,'Club administrator can invite a member by email');check(app.fixture('fingerprints')['users']==users_before,'Inviting an existing account does not change its login, email, role or password');check(b'could not be sent' in invite_body,'Invitation delivery failure remains visible in development') + invitation=app.fixture('inspect')['club_invitations'][0]['invitation_serial'] + expect(app.post('Roster.workspace',step='member',club_serial=a,membership_serial=ids['clubA_shared'],membership_status='inactive',joined_on='2026-01-01'),200,'Club administrator can deactivate a membership in their club') + changed=app.fixture('inspect');check(next(x for x in changed['club_memberships'] if x['membership_serial']==ids['clubB_shared'])['membership_status']=='active' and next(x for x in changed['users'] if x['user_serial']==ids['shared'])['user_status']=='active','Membership deactivation leaves the shared account and other club membership active') + expect(app.post('Roster.workspace',step='member',club_serial=a,membership_serial=ids['clubA_shared'],membership_status='active',joined_on='2026-01-01'),200,'Club administrator can reactivate their own club membership') + login('admina');check(b'invitee@example.test' in workspace(a)[1],'Another administrator of the shared club sees its invitation') + own=expect(workspace(b),200,'Administrator of Alpha can read Beta as an ordinary Beta member');check(b'memberb@example.test' not in own and b'Record received payment' not in own,'Administrator in one club has member-only visibility in another club') + expect(app.post('RosterReports.csv',club_serial=b),403,'Being an ordinary member does not permit exporting that club') + login('membera');expect(app.post('Roster.invitations',step='accept',invitation_serial=invitation),404,'Another signed-in member cannot steal an invitation') + login('invitee');pending=expect(app.request('/main.php?Xaction=Roster.invitations'),200,'Invited member can open pending invitations');check(b'Tenant Alpha' in pending,'Correct invited email sees the club offer');expect(app.post('Roster.invitations',step='accept',invitation_serial=invitation),200,'Verified invited member accepts through the HTTP handler') + login('membera');member=expect(workspace(a),200,'Member can read assigned club and own dues');check(b'My season dues' in member and b'$90.00' in member and b'admina2@example.test' not in member and b'shared@example.test' not in member,'Member sees personal membership/dues rather than other member records') + expect(app.post('Roster.workspace',step='payment',club_serial=a,due_serial=dueA,amount='1.00',paid_on='2026-01-01',request_key=secrets.token_hex(32)),403,'Members cannot mutate financial records') + expect(app.post('Roster.tickets',step='openTicket',club_serial=a,subject='My dues question',message=' Please explain my dues.'),200,'Member can submit a club ticket') + ticket=app.fixture('inspect')['club_tickets'][0]['ticket_serial'];page=expect(app.request(f'/main.php?Xaction=Roster.tickets&club_serial={a}&ticket_serial={ticket}'),200,'Member can read their submitted ticket');check(b'<script>' in page and b'' not in page,'Ticket content is escaped when displayed') + missing=app.request(data={'action':'Roster.tickets','step':'reply','club_serial':a,'ticket_serial':ticket,'message':'No token'},ajax=True);expect(missing,403,'Ticket replies require CSRF protection') + login('shared');expect(app.request(f'/main.php?Xaction=Roster.tickets&club_serial={a}&ticket_serial={ticket}'),404,'Another member in the same club cannot read a private ticket') + login('adminb');expect(app.request(f'/main.php?Xaction=Roster.tickets&club_serial={a}&ticket_serial={ticket}'),403,'Other tenant administrator cannot read a ticket') + login('admina2');expect(app.post('Roster.tickets',step='reply',club_serial=a,ticket_serial=ticket,message='Your payment was received.',ticket_status='closed'),200,'Assigned club administrator can answer and close the ticket') + login('membera');page=expect(app.request(f'/main.php?Xaction=Roster.tickets&club_serial={a}&ticket_serial={ticket}'),200,'Member can read the administrator response');check(b'Your payment was received.' in page and b'Status: closed' in page,'Ticket reply and closed status are visible to its author') + app.logout();app.login();all_data=expect(workspace(b),200,'Super System Administrator can open any tenant');check(b'memberb@example.test' in all_data,'Super System Administrator can see all associated member data') + expect(app.request(f'/main.php?Xaction=Roster.tickets&club_serial={a}&ticket_serial={ticket}'),200,'Super System Administrator can inspect tickets across tenants') + # Removing a club assignment takes effect in existing sessions on the next request. + login('admina2');app.fixture('demoteTenantAdmin',str(ids['clubA_admina2'])) + expect(app.post('Roster.workspace',step='season',club_serial=a,season_name='Revoked privilege',starts_on='2026-01-01',ends_on='2026-12-31'),403,'Club administrator demotion immediately removes management access without a new login') +finally:app.close() +print(str(len(checks))+' tenant HTTP checks passed.') diff --git a/tests/tenants_migration.py b/tests/tenants_migration.py new file mode 100644 index 0000000..c3f55eb --- /dev/null +++ b/tests/tenants_migration.py @@ -0,0 +1,20 @@ +import subprocess +from application_harness import Application,PHP,ROOT +app=Application();checks=[] +def check(ok,message): + if not ok:raise AssertionError(message) + checks.append(message);print('PASS: '+message) +try: + ids=app.fixture('tenantSeed');app.fixture('legacyTenantSchema') + before=app.fixture('inspect');env=app.env.copy();env['HCR_SUPER_ADMIN_EMAIL']='admina@example.test' + result=subprocess.run(PHP+['bin/migrate-tenants.php'],cwd=ROOT,env=env,capture_output=True,text=True);check(result.returncode==0,'Tenant migration upgrades the legacy membership schema') + after=app.fixture('inspect');selected=next(x for x in after['users'] if x['user_serial']==ids['admina']);old=next(x for x in before['users'] if x['user_serial']==ids['admina']) + check(selected['user_role']=='Super System Administrator' and selected['user_auth_version']==old['user_auth_version']+1,'Only the explicitly designated account is promoted and its sessions are revoked') + check(next(x for x in after['users'] if x['user_serial']==ids['adminb'])['user_role']=='Administrator','Another legacy Administrator is not promoted') + check(all(x['membership_role']=='member' for x in after['club_memberships']),'Migration never guesses club administrator assignments for legacy memberships') + check([{k:v for k,v in x.items() if k!='membership_role'} for x in after['club_memberships']]==before['club_memberships'] and after['clubs']==before['clubs'],'Club data and existing memberships are preserved') + fingerprints=app.fixture('fingerprints');subprocess.run(PHP+['bin/migrate-tenants.php'],cwd=ROOT,env=env,capture_output=True,check=True);check(app.fixture('fingerprints')==fingerprints,'Rerunning explicit promotion leaves rows, sessions and audit unchanged') + env['HCR_SUPER_ADMIN_EMAIL']='missing-owner@example.test';result=subprocess.run(PHP+['bin/migrate-tenants.php'],cwd=ROOT,env=env,capture_output=True);check(result.returncode!=0 and app.fixture('fingerprints')==fingerprints,'Missing designated account fails without promoting another account') + app.login();response=app.post('Roster.workspace',step='club',club_serial=0,club_name='Tenant Alpha');check(response[0]==200 and len(app.fixture('inspect')['clubs'])==3,'Independent clubs may use the same display name after migration') +finally:app.close() +print(str(len(checks))+' tenant migration checks passed.') diff --git a/tests/tenants_runner.py b/tests/tenants_runner.py new file mode 100644 index 0000000..b0ded45 --- /dev/null +++ b/tests/tenants_runner.py @@ -0,0 +1,7 @@ +import json,os,subprocess +from application_harness import Application,PHP,ROOT +app=Application() +try: + ids=app.fixture('tenantSeed');env=app.env.copy();env['HCR_TENANT_IDS']=json.dumps(ids) + subprocess.run(PHP+['tests/tenants_service.php'],cwd=ROOT,env=env,check=True) +finally:app.close() diff --git a/tests/tenants_service.php b/tests/tenants_service.php new file mode 100644 index 0000000..36616a8 --- /dev/null +++ b/tests/tenants_service.php @@ -0,0 +1,49 @@ +connect();$ids=json_decode(getenv('HCR_TENANT_IDS'),true,512,JSON_THROW_ON_ERROR);$checks=0; +function checkTenant(bool $ok,string $message):void{global $checks;if(!$ok)throw new RuntimeException($message);$checks++;echo 'PASS: '.$message."\n";} +function deniedTenant(callable $operation,int $status,string $message):void{try{$operation();}catch(AppException $e){checkTenant($e->status===$status,$message.' (status '.$e->status.')');return;}throw new RuntimeException($message.' was allowed');} +function acting(int $id):void{global $db;$stmt=$db->prepare('SELECT * FROM users WHERE user_serial=?');$stmt->execute([$id]);$u=$stmt->fetch();$_SESSION=[Base::USER_SERIAL=>$id,Base::USER_NAME=>$u['user_name'],Base::USER_ROLE=>$u['user_role'],Base::USER_EMAIL=>$u['user_email']];} +class CapturedClubInvitations extends ClubInvitations {public array $sent=[];public bool $works=true;protected function deliver(string $email,string $club):bool{$this->sent[]=[$email,$club];return $this->works;}} +$access=new TenantAccess();$roster=new RosterService();$invite=new CapturedClubInvitations();$tickets=new ClubTickets(); +acting($ids['admina']); +checkTenant(!$access->isSuper()&&$access->canManage($ids['clubA'])&&!$access->canManage($ids['clubB']),'A club administrator has no global or other-club management privilege'); +deniedTenant(fn()=>(new MaintenanceService())->updateUser($ids['membera'],[]),403,'Service layer rejects club administrator global account edits'); +deniedTenant(fn()=>(new AdminAccounts())->create([]),403,'Service layer rejects club administrator global account creation'); +deniedTenant(fn()=>$roster->saveClub(0,'Unauthorized tenant'),403,'Only the Super System Administrator can provision a new tenant'); +deniedTenant(fn()=>$roster->saveClub($ids['clubB'],'Renamed other club'),403,'Club administrator cannot rename a club where they are a member'); +deniedTenant(fn()=>$roster->saveMember($ids['clubA'],$ids['clubA_membera'],'','active','2026-01-01','administrator'),403,'Club administrator cannot promote a member to administrator'); +deniedTenant(fn()=>$roster->saveMember($ids['clubA'],0,'tenantmemberb','active','2026-01-01'),403,'Club administrator cannot look up and attach arbitrary global accounts'); +deniedTenant(fn()=>$invite->invite($ids['clubA'],'invitee@example.test','administrator'),403,'Administrator invitations require Super System Administrator authorization'); +$result=$invite->invite($ids['clubA'],'invitee@example.test');checkTenant($result['warning']===''&&count($invite->sent)===1,'Club invitation sends to the submitted email without exposing an existing account'); +$row=$db->query("SELECT * FROM club_invitations WHERE invite_email='invitee@example.test'")->fetch();$invitation=(int)$row['invitation_serial']; +checkTenant((int)$db->query('SELECT COUNT(*) FROM club_memberships WHERE user_serial='.$ids['invitee'])->fetchColumn()===0,'Invitation grants no membership before authenticated acceptance'); +acting($ids['admina2']);checkTenant(count($invite->forClub($ids['clubA']))===1&&$access->managesAny(),'Another administrator of the same club sees shared invitations even with global User role'); +acting($ids['adminb']);deniedTenant(fn()=>$invite->forClub($ids['clubA']),403,'Other tenant administrator cannot list invitations'); +deniedTenant(fn()=>$invite->revoke($ids['clubB'],$invitation),404,'Changing the club ID cannot revoke another club invitation'); +acting($ids['membera']);deniedTenant(fn()=>$invite->accept($invitation),404,'Another account cannot accept an invitation by guessing its ID'); +acting($ids['invitee']);checkTenant(count($invite->pending())===1,'Invited email sees its pending invitation');$invite->accept($invitation); +checkTenant(count($roster->clubs())===1&&$roster->clubs()[0]['club_name']==='Tenant Alpha','Accepted invitation grants only its club'); +deniedTenant(fn()=>$invite->accept($invitation),404,'Accepted invitation cannot be replayed'); +acting($ids['admina']);$invite->invite($ids['clubA'],'unverified@example.test');$unverified=(int)$db->query("SELECT invitation_serial FROM club_invitations WHERE invite_email='unverified@example.test'")->fetchColumn(); +acting($ids['unverified']);deniedTenant(fn()=>$invite->accept($unverified),403,'Unverified account cannot accept a club invitation'); +$db->exec("UPDATE users SET user_email_verified_at=UTC_TIMESTAMP() WHERE user_serial=".$ids['unverified']);$db->exec('UPDATE club_invitations SET expires_at=DATE_SUB(UTC_TIMESTAMP(),INTERVAL 1 SECOND) WHERE invitation_serial='.$unverified); +deniedTenant(fn()=>$invite->accept($unverified),404,'Expired invitation cannot be accepted'); +acting($ids['admina']);$invite->works=false;$warning=$invite->invite($ids['clubA'],'delivery@example.test');checkTenant($warning['warning']!==''&&$warning['ok'],'Email failure is visible and preserves the invitation for retry'); +$revoked=(int)$db->query("SELECT invitation_serial FROM club_invitations WHERE invite_email='delivery@example.test'")->fetchColumn();acting($ids['admina2']);$invite->revoke($ids['clubA'],$revoked);checkTenant($db->query('SELECT invitation_status FROM club_invitations WHERE invitation_serial='.$revoked)->fetchColumn()==='revoked','Shared club administrator can revoke a member invitation'); +acting($ids['admina']);$invite->works=true;$invite->invite($ids['clubA'],'shared@example.test');$stale=(int)$db->query("SELECT invitation_serial FROM club_invitations WHERE invite_email='shared@example.test'")->fetchColumn(); +$db->exec("UPDATE club_memberships SET membership_role='member' WHERE membership_serial=".$ids['clubA_admina']);acting($ids['shared']);deniedTenant(fn()=>$invite->accept($stale),409,'An invitation cannot grant access after its inviter loses administration');$db->exec("UPDATE club_memberships SET membership_role='administrator' WHERE membership_serial=".$ids['clubA_admina']); +acting(1);$invite->invite($ids['clubB'],'invitee@example.test','administrator');$elevated=(int)$db->query("SELECT invitation_serial FROM club_invitations WHERE club_serial=".$ids['clubB']." AND invite_email='invitee@example.test'")->fetchColumn();acting($ids['invitee']);$invite->accept($elevated);checkTenant($access->canManage($ids['clubB'])&&!$access->canManage($ids['clubA'])&&!$access->isSuper(),'Super-approved club administrator acceptance does not grant global or other-club privileges'); +acting($ids['membera']);$ticket=$tickets->createTicket($ids['clubA'],'Membership question',' My dues question'); +checkTenant(count($tickets->listing($ids['clubA']))===1,'Member can submit and view a personal club ticket'); +deniedTenant(fn()=>$tickets->createTicket($ids['clubB'],'Foreign ticket','Must fail'),403,'Member cannot submit a ticket to another tenant'); +acting($ids['shared']);deniedTenant(fn()=>$tickets->ticket($ids['clubA'],$ticket),404,'Another member of the same club cannot read a private ticket'); +acting($ids['adminb']);deniedTenant(fn()=>$tickets->reply($ids['clubA'],$ticket,'Foreign reply'),403,'Other club administrator cannot reply to a ticket'); +acting($ids['admina2']);$tickets->reply($ids['clubA'],$ticket,'We will review your dues.','closed');checkTenant(count($tickets->messages($ids['clubA'],$ticket))===2,'Assigned club administrator can reply and close a ticket'); +acting($ids['membera']);deniedTenant(fn()=>$tickets->reply($ids['clubA'],$ticket,'Reopen please','open'),403,'Member cannot change ticket status');deniedTenant(fn()=>$tickets->reply($ids['clubA'],$ticket,'Another reply'),409,'Closed ticket requires an administrator to reopen it'); +acting(1);checkTenant(count($roster->clubs())===2&&count($tickets->listing($ids['clubA']))===1,'Super System Administrator sees all clubs and their tickets'); +// Audit failures must roll back tenant data writes. +$db->exec('RENAME TABLE journal TO tenant_hidden_journal');try{$count=(int)$db->query('SELECT COUNT(*) FROM club_tickets')->fetchColumn();try{$tickets->createTicket($ids['clubA'],'Rollback','No audit means no ticket');throw new RuntimeException('Missing audit accepted');}catch(PDOException $e){}checkTenant((int)$db->query('SELECT COUNT(*) FROM club_tickets')->fetchColumn()===$count,'Ticket creation rolls back when its mandatory audit fails');}finally{$db->exec('RENAME TABLE tenant_hidden_journal TO journal');} +echo "$checks tenant service checks passed.\n"; diff --git a/tests/ticket_paging_http.py b/tests/ticket_paging_http.py new file mode 100644 index 0000000..fe281f3 --- /dev/null +++ b/tests/ticket_paging_http.py @@ -0,0 +1,43 @@ +import re,urllib.parse +from application_harness import Application +app=Application();checks=[] +def check(ok,message): + if not ok:raise AssertionError(message) + checks.append(message);print('PASS: '+message) +def get(club,**fields):return app.request('/main.php?'+urllib.parse.urlencode({'Xaction':'Roster.tickets','club_serial':club,**fields})) +def expect(response,status,message): + check(response[0]==status,message+' (HTTP '+str(response[0])+')');return response[1] +def listed(body): + part=re.search(rb'
      (.*?)
    ',body,re.S);return re.findall(rb'ticket_serial=([0-9]+)',part[1]) +try: + ids=app.fixture('tenantSeed');a,b=ids['clubA'],ids['clubB'];seed=app.fixture('ticketPagingSeed',str(a),str(b),str(ids['membera']),str(ids['shared']),str(ids['memberb'])) + app.login('membera@example.test','Tenant test password 123!') + body=expect(get(a),200,'Member opens first ticket page');check(len(listed(body))==25 and b'Tickets 1-25 of 102. Page 1 of 5.' in body,'First page is bounded and count includes only personal tickets') + seen=[] + for page in range(1,6): + body=expect(get(a,ticket_page=page),200,'Ticket page '+str(page)+' loads');seen+=listed(body) + check(b'Private neighbor ticket' not in body and b'Archive foreign club ticket' not in body,'Page '+str(page)+' excludes private and foreign tickets') + check(len(seen)==102 and len(set(seen))==102,'Paging returns every personal ticket once in stable serial order') + check(str(seed['oldest']).encode() in seen,'Ticket older than the previous 100-ticket ceiling is discoverable') + body=expect(get(a,ticket_page=9999),200,'Excessive page number is safely clamped');check(b'Page 5 of 5.' in body and len(listed(body))==2,'Last page shows the correct final two records') + for page in ['0','-1','1 OR 1=1','1.5']: + expect(get(a,ticket_page=page),422,'Malformed ticket page is rejected: '+page) + for literal in ['%','_','!']: + body=expect(get(a,ticket_search=literal),200,'Literal wildcard search works: '+literal);check(listed(body)==[str(seed['literal']).encode()],'Search treats '+literal+' as literal text rather than a wildcard') + body=expect(get(a,ticket_search='Archive ticket 001'),200,'Search finds an old ticket');check(listed(body)==[str(seed['oldest']).encode()] and b'Page 1 of 1.' in body,'Search count and rows use the same authorization filter') + body=expect(get(a,ticket_search='%'),200,'Stored HTML subject is safely searchable');check(b'<b>needle</b>' in body and b'needle' not in body,'Ticket subject markup is escaped in search results') + body=expect(get(a,ticket_search='">'),200,'Search handles HTML-shaped text');check(b'' not in body,'Search text cannot inject HTML into the form') + expect(get(a,ticket_search='x'*101),422,'Overlong search gets a validation error') + expect(get(b,ticket_page=2,ticket_search='Archive'),403,'Changing club ID during paging or search is denied') + expect(get(a,ticket_serial=seed['private'],ticket_page=5),404,'Paging cannot open another member private ticket by ID') + # A reply retains its old-ticket list context, while refreshing is a read-only GET. + response=app.post('Roster.tickets',step='reply',club_serial=a,ticket_serial=seed['oldest'],ticket_page=5,ticket_search='Archive',message='Reply to older ticket') + body=expect(response,200,'Replying to an older ticket preserves navigation');check(b'Page 5 of 5.' in body and b'value="Archive"' in body and b'Reply to older ticket' in body,'Reply redirect preserves search and page context') + app.logout();app.login('shared@example.test','Tenant test password 123!') + body=expect(get(a,ticket_page=5),200,'Other member has a separately scoped ticket list');check(b'of 1. Page 1 of 1.' in body and b'Archive ticket' not in body,'Other member counts do not expose personal ticket totals') + body=expect(get(a,ticket_search='Archive'),200,'Other member search stays private');check(b'Tickets 0-0 of 0.' in body,'Search counts do not reveal other member matches') + app.logout();app.login('admina2@example.test','Tenant test password 123!') + body=expect(get(a,ticket_page=5),200,'Club administrator can page through all club tickets');check(b'of 103. Page 5 of 5.' in body and str(seed['oldest']).encode() in listed(body),'Administrator can find older tickets from every club member') + expect(get(b,ticket_search='Archive'),403,'Administrator cannot search another tenant') +finally:app.close() +print(str(len(checks))+' ticket paging HTTP checks passed.') diff --git a/tests/ticket_repairs_browser.js b/tests/ticket_repairs_browser.js new file mode 100644 index 0000000..2ebcbb7 --- /dev/null +++ b/tests/ticket_repairs_browser.js @@ -0,0 +1,24 @@ +const {chromium}=require('playwright'); +const assert=require('node:assert/strict'); +(async()=>{ + const browser=await chromium.launch({executablePath:process.env.HCR_TEST_CHROME||'C:/Program Files/Google/Chrome/Application/chrome.exe',headless:true}); + const page=await browser.newPage(),errors=[];let checks=0; + page.on('pageerror',e=>errors.push(e.message)); + const pass=message=>{checks++;console.log('PASS: '+message);}; + const base=process.env.HCR_TEST_URL,ids=JSON.parse(process.env.HCR_TENANT_IDS); + const click=async locator=>Promise.all([page.waitForNavigation({waitUntil:'load'}),locator.click()]); + try{ + await page.goto(base+'/main.php');await page.locator('#user_email').fill('membera@example.test');await page.locator('#user_password').fill('Tenant test password 123!');await click(page.locator('#login button[type=submit]')); + await page.goto(base+'/main.php?Xaction=Roster.tickets&club_serial='+ids.clubA); + assert.equal(await page.locator('.ticket-list li').count(),25);assert((await page.locator('.ticket-page-status').innerText()).includes('of 102.'));pass('Browser shows a bounded personal ticket page with its own total'); + await click(page.getByRole('link',{name:'Last page',exact:true}));assert.equal(await page.locator('.ticket-list li').count(),2);await page.getByRole('link',{name:/Archive ticket 001$/}).waitFor();pass('Last-page navigation exposes tickets older than the former 100-ticket limit'); + const search=page.locator('form').filter({has:page.getByRole('button',{name:'Search tickets',exact:true})});await search.getByLabel('Search ticket subjects',{exact:true}).fill('Archive ticket 001');await click(search.getByRole('button',{name:'Search tickets',exact:true}));assert.equal(await page.locator('.ticket-list li').count(),1);assert((await page.locator('.ticket-page-status').innerText()).includes('Page 1 of 1.'));pass('Browser search resets paging and locates an older authorized ticket'); + await click(page.getByRole('link',{name:/Archive ticket 001$/}));await page.getByRole('heading',{name:'Archive ticket 001',exact:true}).waitFor();pass('An old ticket opens from its filtered list'); + const form=page.locator('form').filter({has:page.getByRole('button',{name:'Submit ticket',exact:true})}),body=form.getByLabel('Message',{exact:true}),subject=form.getByLabel('Subject',{exact:true}); + await subject.fill('😀'.repeat(200));assert(await subject.evaluate(e=>e.checkValidity()));await subject.fill('x'.repeat(201));assert(!await subject.evaluate(e=>e.checkValidity()));pass('Subject validation counts Unicode characters rather than UTF-16 units'); + await subject.fill('Unicode browser ticket');await body.fill('界'.repeat(8001));assert(!await body.evaluate(e=>e.checkValidity()));assert((await body.evaluate(e=>e.validationMessage)).includes('8000'));pass('Browser rejects an overlong Unicode message with a specific limit'); + await body.fill('😀'.repeat(8000));assert.equal(await body.getAttribute('maxlength'),'16000');assert(await body.evaluate(e=>e.checkValidity()));await click(form.getByRole('button',{name:'Submit ticket',exact:true}));await page.getByRole('heading',{name:'Unicode browser ticket',exact:true}).waitFor();assert((await page.locator('article.card').first().innerText()).includes('😀'.repeat(8000)));pass('An 8,000-character emoji message is accepted and preserved through the browser'); + assert.deepEqual(errors,[]);pass('Ticket paging, search and Unicode controls produce no browser script errors'); + }finally{await browser.close();} + console.log(checks+' ticket repair browser checks passed.'); +})().catch(e=>{console.error(e);process.exitCode=1;}); diff --git a/tests/ticket_repairs_browser_runner.py b/tests/ticket_repairs_browser_runner.py new file mode 100644 index 0000000..5a25db5 --- /dev/null +++ b/tests/ticket_repairs_browser_runner.py @@ -0,0 +1,8 @@ +import json,subprocess +from application_harness import Application,ROOT +app=Application() +try: + ids=app.fixture('tenantSeed');app.fixture('ticketPagingSeed',str(ids['clubA']),str(ids['clubB']),str(ids['membera']),str(ids['shared']),str(ids['memberb'])) + env=app.env.copy();env['HCR_TEST_URL']=app.base;env['HCR_TENANT_IDS']=json.dumps(ids) + subprocess.run([env.get('NODE_TEST_COMMAND','node'),'tests/ticket_repairs_browser.js'],cwd=ROOT,env=env,check=True) +finally:app.close() diff --git a/tests/ticket_repairs_http.py b/tests/ticket_repairs_http.py new file mode 100644 index 0000000..6bd9635 --- /dev/null +++ b/tests/ticket_repairs_http.py @@ -0,0 +1,29 @@ +from application_harness import Application +app=Application();checks=[] +def check(ok,message): + if not ok:raise AssertionError(message) + checks.append(message);print('PASS: '+message) +def expect(response,status,message): + check(response[0]==status,message+' (HTTP '+str(response[0])+')');return response[1] +try: + ids=app.fixture('tenantSeed');club=ids['clubA'];app.login('membera@example.test','Tenant test password 123!') + for text,label in [('界'*3000,'Three-thousand-character Unicode message'),('😀'*8000,'Eight-thousand-character four-byte message')]: + expect(app.post('Roster.tickets',step='openTicket',club_serial=club,subject=label,message=text),200,label+' can be submitted') + ticket=app.fixture('inspect')['club_tickets'][-1]['ticket_serial'];body=app.request(f'/main.php?Xaction=Roster.tickets&club_serial={club}&ticket_serial={ticket}')[1] + check(text.encode() in body,label+' is preserved without truncation') + ticket=app.fixture('inspect')['club_tickets'][-1]['ticket_serial'] + expect(app.post('Roster.tickets',step='reply',club_serial=club,ticket_serial=ticket,message='😀'*8000),200,'Unicode reply accepts the same character boundary') + for text,label in [('x'*8001,'Oversized ASCII message'),('😀'*8001,'Oversized Unicode message')]: + before=app.fixture('fingerprints');body=expect(app.post('Roster.tickets',step='openTicket',club_serial=club,subject='Too long',message=text),422,label+' gets a field validation error') + check(b'Message must be 8000 characters or fewer.' in body,label+' explains the supported limit') + after=app.fixture('fingerprints');check(after['club_tickets']==before['club_tickets'] and after['club_ticket_messages']==before['club_ticket_messages'],label+' creates no ticket or partial message') + before=app.fixture('fingerprints');expect(app.post('Roster.tickets',step='reply',club_serial=club,ticket_serial=ticket,message='😀'*8001),422,'Oversized Unicode reply is rejected') + check(app.fixture('fingerprints')['club_ticket_messages']==before['club_ticket_messages'],'Rejected reply leaves message history unchanged') + expect(app.post('Roster.tickets',step='openTicket',club_serial=club,subject='Hard limit',message='x'*65537),400,'Hard transport ceiling still rejects extreme ticket bodies') + expect(app.post('Roster.tickets',step='openTicket',club_serial=club,subject='Array',**{'message[]':'bad'}),400,'Array-shaped ticket body is rejected') + expect(app.post('Roster.tickets',step='openTicket',club_serial=club,subject='x'*8193,message='Normal'),400,'Larger message allowance does not widen other field byte limits') + expect(app.post('Roster.workspace',step='club',club_serial=club,club_name='x'*9000),400,'Larger message allowance does not widen other routes') + response=app.request('/main.php?Xaction=Roster.tickets&user_email%5B%5D=bad',data={'action':'Roster.tickets','csrf_token':app.token,'user_email':'valid@example.test'},ajax=True) + expect(response,400,'A POST field cannot hide an array-shaped query field') +finally:app.close() +print(str(len(checks))+' ticket repair HTTP checks passed.') diff --git a/tests/transaction_retries.php b/tests/transaction_retries.php new file mode 100644 index 0000000..1c32165 --- /dev/null +++ b/tests/transaction_retries.php @@ -0,0 +1,24 @@ +connect();$ids=json_decode(getenv('HCR_TENANT_IDS'),true,512,JSON_THROW_ON_ERROR);$checks=0; +function retryCheck(bool $ok,string $label):void{global $checks;if(!$ok)throw new RuntimeException($label);$checks++;echo 'PASS: '.$label."\n";} +$insert=static function(PDO $db,string $subject)use($ids):void{$s=$db->prepare('INSERT INTO club_tickets(club_serial,user_serial,subject) VALUES(?,?,?)');$s->execute([$ids['clubA'],$ids['membera'],$subject]);}; +$attempts=0;$value=DatabaseTransaction::run($db,function(PDO $db)use(&$attempts,$insert){$attempts++;$insert($db,'Retried transaction');if($attempts<3)$db->exec("SIGNAL SQLSTATE '40001' SET MYSQL_ERRNO=1213,MESSAGE_TEXT='Controlled deadlock'");return 'committed';}); +retryCheck($attempts===3&&$value==='committed','Deadlock retries return the successful whole-transaction result'); +retryCheck((int)$db->query("SELECT COUNT(*) FROM club_tickets WHERE subject='Retried transaction'")->fetchColumn()===1,'Retry rollbacks prevent duplicate ticket writes'); +$attempts=0;try{DatabaseTransaction::run($db,function(PDO $db)use(&$attempts,$insert){$attempts++;$insert($db,'Exhausted transaction');$db->exec("SIGNAL SQLSTATE 'HY000' SET MYSQL_ERRNO=1205,MESSAGE_TEXT='Controlled timeout'");});throw new RuntimeException('Expected timeout');}catch(PDOException $e){retryCheck($attempts===3&&(int)$e->errorInfo[1]===1205,'Lock timeout retries stop after three attempts');} +retryCheck(!$db->inTransaction()&&!(int)$db->query("SELECT COUNT(*) FROM club_tickets WHERE subject='Exhausted transaction'")->fetchColumn(),'Exhausted retries leave no open transaction or partial write'); +$attempts=0;try{DatabaseTransaction::run($db,function(PDO $db)use(&$attempts,$insert){$attempts++;$insert($db,'Rejected transaction');throw new AppException('Denied',403);});}catch(AppException $e){retryCheck($attempts===1&&$e->status===403,'Business and permission errors are never retried');} +retryCheck(!(int)$db->query("SELECT COUNT(*) FROM club_tickets WHERE subject='Rejected transaction'")->fetchColumn(),'Permission failure rolls back its writes'); +// Simulate a grant changing after the first attempt rolls back, before retry. +class RevocationPDO extends PDO { + public $afterRollback; + public function rollBack():bool{$ok=parent::rollBack();if($this->afterRollback){$call=$this->afterRollback;$this->afterRollback=null;$call();}return $ok;} +} +$settings=(new Base())->getSettings();$retryDb=new RevocationPDO('mysql:host='.$settings->DatabaseServer.';port='.$settings->DatabasePort.';dbname='.$settings->DatabaseName.';charset=utf8mb4',(string)$settings->DatabaseUser,(string)$settings->DatabasePassword,[PDO::ATTR_ERRMODE=>PDO::ERRMODE_EXCEPTION,PDO::ATTR_DEFAULT_FETCH_MODE=>PDO::FETCH_ASSOC]); +$_SESSION=[Base::USER_SERIAL=>$ids['admina2']];$retryDb->afterRollback=function()use($db,$ids){$db->exec("UPDATE club_memberships SET membership_role='member' WHERE membership_serial=".$ids['clubA_admina2']);};$attempts=0; +try{DatabaseTransaction::run($retryDb,function(PDO $db)use(&$attempts,$ids,$insert){$attempts++;(new TenantAccess())->requireManager($ids['clubA'],$db);$insert($db,'Revoked transaction');$db->exec("SIGNAL SQLSTATE '40001' SET MYSQL_ERRNO=1213,MESSAGE_TEXT='Controlled deadlock'");});throw new RuntimeException('Revoked write was allowed');}catch(AppException $e){retryCheck($attempts===2&&$e->status===403,'Authorization is checked again after a concurrent revocation');} +retryCheck(!(int)$db->query("SELECT COUNT(*) FROM club_tickets WHERE subject='Revoked transaction'")->fetchColumn(),'Revoked authority cannot commit a retried write'); +echo "$checks transaction retry checks passed.\n"; diff --git a/vendor/composer/autoload_files.php b/vendor/composer/autoload_files.php new file mode 100644 index 0000000..be8e1c3 --- /dev/null +++ b/vendor/composer/autoload_files.php @@ -0,0 +1,10 @@ + $vendorDir . '/symfony/deprecation-contracts/function.php', +); diff --git a/vendor/composer/autoload_psr4.php b/vendor/composer/autoload_psr4.php index 7d6469c..76b42ad 100644 --- a/vendor/composer/autoload_psr4.php +++ b/vendor/composer/autoload_psr4.php @@ -8,8 +8,11 @@ $baseDir = dirname($vendorDir); return array( 'ZipStream\\' => array($vendorDir . '/maennchen/zipstream-php/src'), 'Psr\\SimpleCache\\' => array($vendorDir . '/psr/simple-cache/src'), + 'Psr\\Clock\\' => array($vendorDir . '/psr/clock/src'), 'PhpOffice\\PhpSpreadsheet\\' => array($vendorDir . '/phpoffice/phpspreadsheet/src/PhpSpreadsheet'), + 'ParagonIE\\ConstantTime\\' => array($vendorDir . '/paragonie/constant_time_encoding/src'), 'PHPMailer\\PHPMailer\\' => array($vendorDir . '/phpmailer/phpmailer/src'), + 'OTPHP\\' => array($vendorDir . '/spomky-labs/otphp/src'), 'Matrix\\' => array($vendorDir . '/markbaker/matrix/classes/src'), 'Composer\\Pcre\\' => array($vendorDir . '/composer/pcre/src'), 'Complex\\' => array($vendorDir . '/markbaker/complex/classes/src'), diff --git a/vendor/composer/autoload_real.php b/vendor/composer/autoload_real.php index 5d08f72..38f491b 100644 --- a/vendor/composer/autoload_real.php +++ b/vendor/composer/autoload_real.php @@ -33,6 +33,18 @@ class ComposerAutoloaderInit6621356a0da1644f04f6f40bd0e0b948 $loader->register(true); + $filesToLoad = \Composer\Autoload\ComposerStaticInit6621356a0da1644f04f6f40bd0e0b948::$files; + $requireFile = \Closure::bind(static function ($fileIdentifier, $file) { + if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) { + $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true; + + require $file; + } + }, null, null); + foreach ($filesToLoad as $fileIdentifier => $file) { + $requireFile($fileIdentifier, $file); + } + return $loader; } } diff --git a/vendor/composer/autoload_static.php b/vendor/composer/autoload_static.php index 1f49c16..2f40bf0 100644 --- a/vendor/composer/autoload_static.php +++ b/vendor/composer/autoload_static.php @@ -6,6 +6,10 @@ namespace Composer\Autoload; class ComposerStaticInit6621356a0da1644f04f6f40bd0e0b948 { + public static $files = array ( + '6e3fae29631ef280660b3cdad06f25a8' => __DIR__ . '/..' . '/symfony/deprecation-contracts/function.php', + ); + public static $prefixLengthsPsr4 = array ( 'Z' => array ( @@ -14,9 +18,15 @@ class ComposerStaticInit6621356a0da1644f04f6f40bd0e0b948 'P' => array ( 'Psr\\SimpleCache\\' => 16, + 'Psr\\Clock\\' => 10, 'PhpOffice\\PhpSpreadsheet\\' => 25, + 'ParagonIE\\ConstantTime\\' => 23, 'PHPMailer\\PHPMailer\\' => 20, ), + 'O' => + array ( + 'OTPHP\\' => 6, + ), 'M' => array ( 'Matrix\\' => 7, @@ -37,14 +47,26 @@ class ComposerStaticInit6621356a0da1644f04f6f40bd0e0b948 array ( 0 => __DIR__ . '/..' . '/psr/simple-cache/src', ), + 'Psr\\Clock\\' => + array ( + 0 => __DIR__ . '/..' . '/psr/clock/src', + ), 'PhpOffice\\PhpSpreadsheet\\' => array ( 0 => __DIR__ . '/..' . '/phpoffice/phpspreadsheet/src/PhpSpreadsheet', ), + 'ParagonIE\\ConstantTime\\' => + array ( + 0 => __DIR__ . '/..' . '/paragonie/constant_time_encoding/src', + ), 'PHPMailer\\PHPMailer\\' => array ( 0 => __DIR__ . '/..' . '/phpmailer/phpmailer/src', ), + 'OTPHP\\' => + array ( + 0 => __DIR__ . '/..' . '/spomky-labs/otphp/src', + ), 'Matrix\\' => array ( 0 => __DIR__ . '/..' . '/markbaker/matrix/classes/src', diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json index 69458e6..a599084 100644 --- a/vendor/composer/installed.json +++ b/vendor/composer/installed.json @@ -273,6 +273,78 @@ }, "install-path": "../markbaker/matrix" }, + { + "name": "paragonie/constant_time_encoding", + "version": "v3.1.3", + "version_normalized": "3.1.3.0", + "source": { + "type": "git", + "url": "https://github.com/paragonie/constant_time_encoding.git", + "reference": "d5b01a39b3415c2cd581d3bd3a3575c1ebbd8e77" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/paragonie/constant_time_encoding/zipball/d5b01a39b3415c2cd581d3bd3a3575c1ebbd8e77", + "reference": "d5b01a39b3415c2cd581d3bd3a3575c1ebbd8e77", + "shasum": "" + }, + "require": { + "php": "^8" + }, + "require-dev": { + "infection/infection": "^0", + "nikic/php-fuzzer": "^0", + "phpunit/phpunit": "^9|^10|^11", + "vimeo/psalm": "^4|^5|^6" + }, + "time": "2025-09-24T15:06:41+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "ParagonIE\\ConstantTime\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Paragon Initiative Enterprises", + "email": "security@paragonie.com", + "homepage": "https://paragonie.com", + "role": "Maintainer" + }, + { + "name": "Steve 'Sc00bz' Thomas", + "email": "steve@tobtu.com", + "homepage": "https://www.tobtu.com", + "role": "Original Developer" + } + ], + "description": "Constant-time Implementations of RFC 4648 Encoding (Base-64, Base-32, Base-16)", + "keywords": [ + "base16", + "base32", + "base32_decode", + "base32_encode", + "base64", + "base64_decode", + "base64_encode", + "bin2hex", + "encoding", + "hex", + "hex2bin", + "rfc4648" + ], + "support": { + "email": "info@paragonie.com", + "issues": "https://github.com/paragonie/constant_time_encoding/issues", + "source": "https://github.com/paragonie/constant_time_encoding" + }, + "install-path": "../paragonie/constant_time_encoding" + }, { "name": "phpmailer/phpmailer", "version": "v7.0.0", @@ -472,6 +544,57 @@ }, "install-path": "../phpoffice/phpspreadsheet" }, + { + "name": "psr/clock", + "version": "1.0.0", + "version_normalized": "1.0.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/clock.git", + "reference": "e41a24703d4560fd0acb709162f73b8adfc3aa0d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/clock/zipball/e41a24703d4560fd0acb709162f73b8adfc3aa0d", + "reference": "e41a24703d4560fd0acb709162f73b8adfc3aa0d", + "shasum": "" + }, + "require": { + "php": "^7.0 || ^8.0" + }, + "time": "2022-11-25T14:36:26+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "Psr\\Clock\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for reading the clock.", + "homepage": "https://github.com/php-fig/clock", + "keywords": [ + "clock", + "now", + "psr", + "psr-20", + "time" + ], + "support": { + "issues": "https://github.com/php-fig/clock/issues", + "source": "https://github.com/php-fig/clock/tree/1.0.0" + }, + "install-path": "../psr/clock" + }, { "name": "psr/simple-cache", "version": "3.0.0", @@ -526,6 +649,153 @@ }, "install-path": "../psr/simple-cache" }, + { + "name": "spomky-labs/otphp", + "version": "11.5.0", + "version_normalized": "11.5.0.0", + "source": { + "type": "git", + "url": "https://github.com/Spomky-Labs/otphp.git", + "reference": "877683d6352b80cdc7020fd43a725629c2524435" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Spomky-Labs/otphp/zipball/877683d6352b80cdc7020fd43a725629c2524435", + "reference": "877683d6352b80cdc7020fd43a725629c2524435", + "shasum": "" + }, + "require": { + "paragonie/constant_time_encoding": "^2.0 || ^3.0", + "php": ">=8.1", + "psr/clock": "^1.0", + "symfony/deprecation-contracts": "^3.2" + }, + "require-dev": { + "symfony/error-handler": "^6.4|^7.0|^8.0" + }, + "time": "2026-06-06T23:41:24+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "OTPHP\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Florent Morselli", + "homepage": "https://github.com/Spomky" + }, + { + "name": "All contributors", + "homepage": "https://github.com/Spomky-Labs/otphp/contributors" + } + ], + "description": "A PHP library for generating one time passwords according to RFC 4226 (HOTP Algorithm) and the RFC 6238 (TOTP Algorithm) and compatible with Google Authenticator", + "homepage": "https://github.com/Spomky-Labs/otphp", + "keywords": [ + "FreeOTP", + "RFC 4226", + "RFC 6238", + "google authenticator", + "hotp", + "otp", + "totp" + ], + "support": { + "issues": "https://github.com/Spomky-Labs/otphp/issues", + "source": "https://github.com/Spomky-Labs/otphp/tree/11.5.0" + }, + "funding": [ + { + "url": "https://github.com/Spomky", + "type": "github" + }, + { + "url": "https://www.patreon.com/FlorentMorselli", + "type": "patreon" + } + ], + "install-path": "../spomky-labs/otphp" + }, + { + "name": "symfony/deprecation-contracts", + "version": "v3.7.1", + "version_normalized": "3.7.1.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/deprecation-contracts.git", + "reference": "f3202fa1b5097b0af062dc978b32ecf63404e31d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/f3202fa1b5097b0af062dc978b32ecf63404e31d", + "reference": "f3202fa1b5097b0af062dc978b32ecf63404e31d", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "time": "2026-06-05T06:23:12+00:00", + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.7-dev" + } + }, + "installation-source": "dist", + "autoload": { + "files": [ + "function.php" + ] + }, + "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": "A generic function and convention to trigger deprecation notices", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.7.1" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "install-path": "../symfony/deprecation-contracts" + }, { "name": "tecnickcom/tcpdf", "version": "6.10.0", diff --git a/vendor/composer/installed.php b/vendor/composer/installed.php index d19329e..75ddd1a 100644 --- a/vendor/composer/installed.php +++ b/vendor/composer/installed.php @@ -3,7 +3,7 @@ 'name' => '__root__', 'pretty_version' => 'dev-development', 'version' => 'dev-development', - 'reference' => 'a1643eb1b74d1dae0fda79a68b6f0672d4603a81', + 'reference' => '1e63076123398a86c77f1c3a53bd64563fe29543', 'type' => 'library', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), @@ -13,7 +13,7 @@ '__root__' => array( 'pretty_version' => 'dev-development', 'version' => 'dev-development', - 'reference' => 'a1643eb1b74d1dae0fda79a68b6f0672d4603a81', + 'reference' => '1e63076123398a86c77f1c3a53bd64563fe29543', 'type' => 'library', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), @@ -55,6 +55,15 @@ 'aliases' => array(), 'dev_requirement' => false, ), + 'paragonie/constant_time_encoding' => array( + 'pretty_version' => 'v3.1.3', + 'version' => '3.1.3.0', + 'reference' => 'd5b01a39b3415c2cd581d3bd3a3575c1ebbd8e77', + 'type' => 'library', + 'install_path' => __DIR__ . '/../paragonie/constant_time_encoding', + 'aliases' => array(), + 'dev_requirement' => false, + ), 'phpmailer/phpmailer' => array( 'pretty_version' => 'v7.0.0', 'version' => '7.0.0.0', @@ -73,6 +82,15 @@ 'aliases' => array(), 'dev_requirement' => false, ), + 'psr/clock' => array( + 'pretty_version' => '1.0.0', + 'version' => '1.0.0.0', + 'reference' => 'e41a24703d4560fd0acb709162f73b8adfc3aa0d', + 'type' => 'library', + 'install_path' => __DIR__ . '/../psr/clock', + 'aliases' => array(), + 'dev_requirement' => false, + ), 'psr/simple-cache' => array( 'pretty_version' => '3.0.0', 'version' => '3.0.0.0', @@ -82,6 +100,24 @@ 'aliases' => array(), 'dev_requirement' => false, ), + 'spomky-labs/otphp' => array( + 'pretty_version' => '11.5.0', + 'version' => '11.5.0.0', + 'reference' => '877683d6352b80cdc7020fd43a725629c2524435', + 'type' => 'library', + 'install_path' => __DIR__ . '/../spomky-labs/otphp', + 'aliases' => array(), + 'dev_requirement' => false, + ), + 'symfony/deprecation-contracts' => array( + 'pretty_version' => 'v3.7.1', + 'version' => '3.7.1.0', + 'reference' => 'f3202fa1b5097b0af062dc978b32ecf63404e31d', + 'type' => 'library', + 'install_path' => __DIR__ . '/../symfony/deprecation-contracts', + 'aliases' => array(), + 'dev_requirement' => false, + ), 'tecnickcom/tcpdf' => array( 'pretty_version' => '6.10.0', 'version' => '6.10.0.0', diff --git a/vendor/paragonie/constant_time_encoding/LICENSE.txt b/vendor/paragonie/constant_time_encoding/LICENSE.txt new file mode 100644 index 0000000..91acaca --- /dev/null +++ b/vendor/paragonie/constant_time_encoding/LICENSE.txt @@ -0,0 +1,48 @@ +The MIT License (MIT) + +Copyright (c) 2016 - 2022 Paragon Initiative Enterprises + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +------------------------------------------------------------------------------ +This library was based on the work of Steve "Sc00bz" Thomas. +------------------------------------------------------------------------------ + +The MIT License (MIT) + +Copyright (c) 2014 Steve Thomas + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + diff --git a/vendor/paragonie/constant_time_encoding/README.md b/vendor/paragonie/constant_time_encoding/README.md new file mode 100644 index 0000000..211f0dc --- /dev/null +++ b/vendor/paragonie/constant_time_encoding/README.md @@ -0,0 +1,88 @@ +# Constant-Time Encoding + +[![Build Status](https://github.com/paragonie/constant_time_encoding/actions/workflows/ci.yml/badge.svg)](https://github.com/paragonie/constant_time_encoding/actions) +[![Static Analysis](https://github.com/paragonie/constant_time_encoding/actions/workflows/psalm.yml/badge.svg)](https://github.com/paragonie/constant_time_encoding/actions) +[![Latest Stable Version](https://poser.pugx.org/paragonie/constant_time_encoding/v/stable)](https://packagist.org/packages/paragonie/constant_time_encoding) +[![Latest Unstable Version](https://poser.pugx.org/paragonie/constant_time_encoding/v/unstable)](https://packagist.org/packages/paragonie/constant_time_encoding) +[![License](https://poser.pugx.org/paragonie/constant_time_encoding/license)](https://packagist.org/packages/paragonie/constant_time_encoding) +[![Downloads](https://img.shields.io/packagist/dt/paragonie/constant_time_encoding.svg)](https://packagist.org/packages/paragonie/constant_time_encoding) + +Based on the [constant-time base64 implementation made by Steve "Sc00bz" Thomas](https://github.com/Sc00bz/ConstTimeEncoding), +this library aims to offer character encoding functions that do not leak +information about what you are encoding/decoding via processor cache +misses. Further reading on [cache-timing attacks](http://blog.ircmaxell.com/2014/11/its-all-about-time.html). + +Our fork offers the following enhancements: + +* `mbstring.func_overload` resistance +* Unit tests +* Composer- and Packagist-ready +* Base16 encoding +* Base32 encoding +* Uses `pack()` and `unpack()` instead of `chr()` and `ord()` + +## PHP Version Requirements + +Version 3 of this library should work on **PHP 8** or newer. + +Version 2 of this library should work on **PHP 7** or newer. See [the v2.x branch](https://github.com/paragonie/constant_time_encoding/tree/v2.x). + +For PHP 5 support, see [the v1.x branch](https://github.com/paragonie/constant_time_encoding/tree/v1.x). + +If you are adding this as a dependency to a project intended to work on PHP 5 through 8.4, please set the required version to `^1|^2|^3`. + +## How to Install + +```sh +composer require paragonie/constant_time_encoding +``` + +## How to Use + +```php +use ParagonIE\ConstantTime\Encoding; + +// possibly (if applicable): +// require 'vendor/autoload.php'; + +$data = random_bytes(32); +echo Encoding::base64Encode($data), "\n"; +echo Encoding::base32EncodeUpper($data), "\n"; +echo Encoding::base32Encode($data), "\n"; +echo Encoding::hexEncode($data), "\n"; +echo Encoding::hexEncodeUpper($data), "\n"; +``` + +Example output: + +``` +1VilPkeVqirlPifk5scbzcTTbMT2clp+Zkyv9VFFasE= +2VMKKPSHSWVCVZJ6E7SONRY3ZXCNG3GE6ZZFU7TGJSX7KUKFNLAQ==== +2vmkkpshswvcvzj6e7sonry3zxcng3ge6zzfu7tgjsx7kukfnlaq==== +d558a53e4795aa2ae53e27e4e6c71bcdc4d36cc4f6725a7e664caff551456ac1 +D558A53E4795AA2AE53E27E4E6C71BDCC4D36CC4F6725A7E664CAFF551456AC1 +``` + +If you only need a particular variant, you can just reference the +required class like so: + +```php +use ParagonIE\ConstantTime\Base64; +use ParagonIE\ConstantTime\Base32; + +$data = random_bytes(32); +echo Base64::encode($data), "\n"; +echo Base32::encode($data), "\n"; +``` + +Example output: + +``` +1VilPkeVqirlPifk5scbzcTTbMT2clp+Zkyv9VFFasE= +2vmkkpshswvcvzj6e7sonry3zxcng3ge6zzfu7tgjsx7kukfnlaq==== +``` + +## Support Contracts + +If your company uses this library in their products or services, you may be +interested in [purchasing a support contract from Paragon Initiative Enterprises](https://paragonie.com/enterprise). diff --git a/vendor/paragonie/constant_time_encoding/composer.json b/vendor/paragonie/constant_time_encoding/composer.json new file mode 100644 index 0000000..11fad5e --- /dev/null +++ b/vendor/paragonie/constant_time_encoding/composer.json @@ -0,0 +1,67 @@ +{ + "name": "paragonie/constant_time_encoding", + "description": "Constant-time Implementations of RFC 4648 Encoding (Base-64, Base-32, Base-16)", + "keywords": [ + "base64", + "encoding", + "rfc4648", + "base32", + "base16", + "hex", + "bin2hex", + "hex2bin", + "base64_encode", + "base64_decode", + "base32_encode", + "base32_decode" + ], + "license": "MIT", + "type": "library", + "authors": [ + { + "name": "Paragon Initiative Enterprises", + "email": "security@paragonie.com", + "homepage": "https://paragonie.com", + "role": "Maintainer" + }, + { + "name": "Steve 'Sc00bz' Thomas", + "email": "steve@tobtu.com", + "homepage": "https://www.tobtu.com", + "role": "Original Developer" + } + ], + "support": { + "issues": "https://github.com/paragonie/constant_time_encoding/issues", + "email": "info@paragonie.com", + "source": "https://github.com/paragonie/constant_time_encoding" + }, + "require": { + "php": "^8" + }, + "require-dev": { + "infection/infection": "^0", + "nikic/php-fuzzer": "^0", + "phpunit/phpunit": "^9|^10|^11", + "vimeo/psalm": "^4|^5|^6" + }, + "autoload": { + "psr-4": { + "ParagonIE\\ConstantTime\\": "src/" + } + }, + "autoload-dev": { + "psr-4": { + "ParagonIE\\ConstantTime\\Tests\\": "tests/" + } + }, + "scripts": { + "mutation-test": "infection" + }, + "config": { + "process-timeout": 0, + "allow-plugins": { + "infection/extension-installer": true + } + } +} diff --git a/vendor/paragonie/constant_time_encoding/src/Base32.php b/vendor/paragonie/constant_time_encoding/src/Base32.php new file mode 100644 index 0000000..379552a --- /dev/null +++ b/vendor/paragonie/constant_time_encoding/src/Base32.php @@ -0,0 +1,558 @@ + 96 && $src < 123) $ret += $src - 97 + 1; // -64 + $ret += (((0x60 - $src) & ($src - 0x7b)) >> 8) & ($src - 96); + + // if ($src > 0x31 && $src < 0x38) $ret += $src - 24 + 1; // -23 + $ret += (((0x31 - $src) & ($src - 0x38)) >> 8) & ($src - 23); + + return $ret; + } + + /** + * Uses bitwise operators instead of table-lookups to turn 5-bit integers + * into 8-bit integers. + * + * Uppercase variant. + * + * @param int $src + * @return int + * @api + */ + protected static function decode5BitsUpper(int $src): int + { + $ret = -1; + + // if ($src > 64 && $src < 91) $ret += $src - 65 + 1; // -64 + $ret += (((0x40 - $src) & ($src - 0x5b)) >> 8) & ($src - 64); + + // if ($src > 0x31 && $src < 0x38) $ret += $src - 24 + 1; // -23 + $ret += (((0x31 - $src) & ($src - 0x38)) >> 8) & ($src - 23); + + return $ret; + } + + /** + * Uses bitwise operators instead of table-lookups to turn 8-bit integers + * into 5-bit integers. + * + * @param int $src + * @return string + * @api + */ + protected static function encode5Bits(int $src): string + { + $diff = 0x61; + + // if ($src > 25) $ret -= 72; + $diff -= ((25 - $src) >> 8) & 73; + + return pack('C', $src + $diff); + } + + /** + * Uses bitwise operators instead of table-lookups to turn 8-bit integers + * into 5-bit integers. + * + * Uppercase variant. + * + * @param int $src + * @return string + * @api + */ + protected static function encode5BitsUpper(int $src): string + { + $diff = 0x41; + + // if ($src > 25) $ret -= 40; + $diff -= ((25 - $src) >> 8) & 41; + + return pack('C', $src + $diff); + } + + /** + * @param string $encodedString + * @param bool $upper + * @return string + * @api + */ + public static function decodeNoPadding( + #[SensitiveParameter] + string $encodedString, + bool $upper = false + ): string { + $srcLen = strlen($encodedString); + if ($srcLen === 0) { + return ''; + } + if (($srcLen & 7) === 0) { + for ($j = 0; $j < 7 && $j < $srcLen; ++$j) { + if ($encodedString[$srcLen - $j - 1] === '=') { + throw new InvalidArgumentException( + "decodeNoPadding() doesn't tolerate padding" + ); + } + } + } + return static::doDecode( + $encodedString, + $upper, + true + ); + } + + /** + * Base32 decoding + * + * @param string $src + * @param bool $upper + * @param bool $strictPadding + * @return string + * + * @throws TypeError + */ + protected static function doDecode( + #[SensitiveParameter] + string $src, + bool $upper = false, + bool $strictPadding = false + ): string { + // We do this to reduce code duplication: + $method = $upper + ? 'decode5BitsUpper' + : 'decode5Bits'; + + // Remove padding + $srcLen = strlen($src); + if ($srcLen === 0) { + return ''; + } + if ($strictPadding) { + if (($srcLen & 7) === 0) { + for ($j = 0; $j < 7; ++$j) { + if ($src[$srcLen - 1] === '=') { + $srcLen--; + } else { + break; + } + } + } + if (($srcLen & 7) === 1) { + throw new RangeException( + 'Incorrect padding' + ); + } + } else { + $src = rtrim($src, '='); + $srcLen = strlen($src); + } + + $err = 0; + $dest = ''; + // Main loop (no padding): + for ($i = 0; $i + 8 <= $srcLen; $i += 8) { + /** @var array $chunk */ + $chunk = unpack('C*', substr($src, $i, 8)); + /** @var int $c0 */ + $c0 = static::$method($chunk[1]); + /** @var int $c1 */ + $c1 = static::$method($chunk[2]); + /** @var int $c2 */ + $c2 = static::$method($chunk[3]); + /** @var int $c3 */ + $c3 = static::$method($chunk[4]); + /** @var int $c4 */ + $c4 = static::$method($chunk[5]); + /** @var int $c5 */ + $c5 = static::$method($chunk[6]); + /** @var int $c6 */ + $c6 = static::$method($chunk[7]); + /** @var int $c7 */ + $c7 = static::$method($chunk[8]); + + $dest .= pack( + 'CCCCC', + (($c0 << 3) | ($c1 >> 2) ) & 0xff, + (($c1 << 6) | ($c2 << 1) | ($c3 >> 4)) & 0xff, + (($c3 << 4) | ($c4 >> 1) ) & 0xff, + (($c4 << 7) | ($c5 << 2) | ($c6 >> 3)) & 0xff, + (($c6 << 5) | ($c7 ) ) & 0xff + ); + $err |= ($c0 | $c1 | $c2 | $c3 | $c4 | $c5 | $c6 | $c7) >> 8; + } + // The last chunk, which may have padding: + if ($i < $srcLen) { + /** @var array $chunk */ + $chunk = unpack('C*', substr($src, $i, $srcLen - $i)); + /** @var int $c0 */ + $c0 = static::$method($chunk[1]); + + if ($i + 6 < $srcLen) { + /** @var int $c1 */ + $c1 = static::$method($chunk[2]); + /** @var int $c2 */ + $c2 = static::$method($chunk[3]); + /** @var int $c3 */ + $c3 = static::$method($chunk[4]); + /** @var int $c4 */ + $c4 = static::$method($chunk[5]); + /** @var int $c5 */ + $c5 = static::$method($chunk[6]); + /** @var int $c6 */ + $c6 = static::$method($chunk[7]); + + $dest .= pack( + 'CCCC', + (($c0 << 3) | ($c1 >> 2) ) & 0xff, + (($c1 << 6) | ($c2 << 1) | ($c3 >> 4)) & 0xff, + (($c3 << 4) | ($c4 >> 1) ) & 0xff, + (($c4 << 7) | ($c5 << 2) | ($c6 >> 3)) & 0xff + ); + $err |= ($c0 | $c1 | $c2 | $c3 | $c4 | $c5 | $c6) >> 8; + if ($strictPadding) { + $err |= ($c6 << 5) & 0xff; + } + } elseif ($i + 5 < $srcLen) { + /** @var int $c1 */ + $c1 = static::$method($chunk[2]); + /** @var int $c2 */ + $c2 = static::$method($chunk[3]); + /** @var int $c3 */ + $c3 = static::$method($chunk[4]); + /** @var int $c4 */ + $c4 = static::$method($chunk[5]); + /** @var int $c5 */ + $c5 = static::$method($chunk[6]); + + $dest .= pack( + 'CCCC', + (($c0 << 3) | ($c1 >> 2) ) & 0xff, + (($c1 << 6) | ($c2 << 1) | ($c3 >> 4)) & 0xff, + (($c3 << 4) | ($c4 >> 1) ) & 0xff, + (($c4 << 7) | ($c5 << 2) ) & 0xff + ); + $err |= ($c0 | $c1 | $c2 | $c3 | $c4 | $c5) >> 8; + } elseif ($i + 4 < $srcLen) { + /** @var int $c1 */ + $c1 = static::$method($chunk[2]); + /** @var int $c2 */ + $c2 = static::$method($chunk[3]); + /** @var int $c3 */ + $c3 = static::$method($chunk[4]); + /** @var int $c4 */ + $c4 = static::$method($chunk[5]); + + $dest .= pack( + 'CCC', + (($c0 << 3) | ($c1 >> 2) ) & 0xff, + (($c1 << 6) | ($c2 << 1) | ($c3 >> 4)) & 0xff, + (($c3 << 4) | ($c4 >> 1) ) & 0xff + ); + $err |= ($c0 | $c1 | $c2 | $c3 | $c4) >> 8; + if ($strictPadding) { + $err |= ($c4 << 7) & 0xff; + } + } elseif ($i + 3 < $srcLen) { + /** @var int $c1 */ + $c1 = static::$method($chunk[2]); + /** @var int $c2 */ + $c2 = static::$method($chunk[3]); + /** @var int $c3 */ + $c3 = static::$method($chunk[4]); + + $dest .= pack( + 'CC', + (($c0 << 3) | ($c1 >> 2) ) & 0xff, + (($c1 << 6) | ($c2 << 1) | ($c3 >> 4)) & 0xff + ); + $err |= ($c0 | $c1 | $c2 | $c3) >> 8; + if ($strictPadding) { + $err |= ($c3 << 4) & 0xff; + } + } elseif ($i + 2 < $srcLen) { + /** @var int $c1 */ + $c1 = static::$method($chunk[2]); + /** @var int $c2 */ + $c2 = static::$method($chunk[3]); + + $dest .= pack( + 'CC', + (($c0 << 3) | ($c1 >> 2) ) & 0xff, + (($c1 << 6) | ($c2 << 1) ) & 0xff + ); + $err |= ($c0 | $c1 | $c2) >> 8; + if ($strictPadding) { + $err |= ($c2 << 6) & 0xff; + } + } elseif ($i + 1 < $srcLen) { + /** @var int $c1 */ + $c1 = static::$method($chunk[2]); + + $dest .= pack( + 'C', + (($c0 << 3) | ($c1 >> 2) ) & 0xff + ); + $err |= ($c0 | $c1) >> 8; + if ($strictPadding) { + $err |= ($c1 << 6) & 0xff; + } + } else { + $dest .= pack( + 'C', + (($c0 << 3) ) & 0xff + ); + $err |= ($c0) >> 8; + } + } + $check = ($err === 0); + if (!$check) { + throw new RangeException( + 'Base32::doDecode() only expects characters in the correct base32 alphabet' + ); + } + return $dest; + } + + /** + * Base32 Encoding + * + * @param string $src + * @param bool $upper + * @param bool $pad + * @return string + * @throws TypeError + */ + protected static function doEncode( + #[SensitiveParameter] + string $src, + bool $upper = false, + bool $pad = true + ): string { + // We do this to reduce code duplication: + $method = $upper + ? 'encode5BitsUpper' + : 'encode5Bits'; + + $dest = ''; + $srcLen = strlen($src); + + // Main loop (no padding): + for ($i = 0; $i + 5 <= $srcLen; $i += 5) { + /** @var array $chunk */ + $chunk = unpack('C*', substr($src, $i, 5)); + $b0 = $chunk[1]; + $b1 = $chunk[2]; + $b2 = $chunk[3]; + $b3 = $chunk[4]; + $b4 = $chunk[5]; + $dest .= + static::$method( ($b0 >> 3) & 31) . + static::$method((($b0 << 2) | ($b1 >> 6)) & 31) . + static::$method((($b1 >> 1) ) & 31) . + static::$method((($b1 << 4) | ($b2 >> 4)) & 31) . + static::$method((($b2 << 1) | ($b3 >> 7)) & 31) . + static::$method((($b3 >> 2) ) & 31) . + static::$method((($b3 << 3) | ($b4 >> 5)) & 31) . + static::$method( $b4 & 31); + } + // The last chunk, which may have padding: + if ($i < $srcLen) { + /** @var array $chunk */ + $chunk = unpack('C*', substr($src, $i, $srcLen - $i)); + $b0 = $chunk[1]; + if ($i + 3 < $srcLen) { + $b1 = $chunk[2]; + $b2 = $chunk[3]; + $b3 = $chunk[4]; + $dest .= + static::$method( ($b0 >> 3) & 31) . + static::$method((($b0 << 2) | ($b1 >> 6)) & 31) . + static::$method((($b1 >> 1) ) & 31) . + static::$method((($b1 << 4) | ($b2 >> 4)) & 31) . + static::$method((($b2 << 1) | ($b3 >> 7)) & 31) . + static::$method((($b3 >> 2) ) & 31) . + static::$method((($b3 << 3) ) & 31); + if ($pad) { + $dest .= '='; + } + } elseif ($i + 2 < $srcLen) { + $b1 = $chunk[2]; + $b2 = $chunk[3]; + $dest .= + static::$method( ($b0 >> 3) & 31) . + static::$method((($b0 << 2) | ($b1 >> 6)) & 31) . + static::$method((($b1 >> 1) ) & 31) . + static::$method((($b1 << 4) | ($b2 >> 4)) & 31) . + static::$method((($b2 << 1) ) & 31); + if ($pad) { + $dest .= '==='; + } + } elseif ($i + 1 < $srcLen) { + $b1 = $chunk[2]; + $dest .= + static::$method( ($b0 >> 3) & 31) . + static::$method((($b0 << 2) | ($b1 >> 6)) & 31) . + static::$method((($b1 >> 1) ) & 31) . + static::$method((($b1 << 4) ) & 31); + if ($pad) { + $dest .= '===='; + } + } else { + $dest .= + static::$method( ($b0 >> 3) & 31) . + static::$method( ($b0 << 2) & 31); + if ($pad) { + $dest .= '======'; + } + } + } + return $dest; + } +} diff --git a/vendor/paragonie/constant_time_encoding/src/Base32Hex.php b/vendor/paragonie/constant_time_encoding/src/Base32Hex.php new file mode 100644 index 0000000..4323a57 --- /dev/null +++ b/vendor/paragonie/constant_time_encoding/src/Base32Hex.php @@ -0,0 +1,118 @@ + 0x30 && $src < 0x3a) ret += $src - 0x2e + 1; // -47 + $ret += (((0x2f - $src) & ($src - 0x3a)) >> 8) & ($src - 47); + + // if ($src > 0x60 && $src < 0x77) ret += $src - 0x61 + 10 + 1; // -86 + $ret += (((0x60 - $src) & ($src - 0x77)) >> 8) & ($src - 86); + + return $ret; + } + + /** + * Uses bitwise operators instead of table-lookups to turn 5-bit integers + * into 8-bit integers. + * + * @param int $src + * @return int + */ + #[Override] + protected static function decode5BitsUpper(int $src): int + { + $ret = -1; + + // if ($src > 0x30 && $src < 0x3a) ret += $src - 0x2e + 1; // -47 + $ret += (((0x2f - $src) & ($src - 0x3a)) >> 8) & ($src - 47); + + // if ($src > 0x40 && $src < 0x57) ret += $src - 0x41 + 10 + 1; // -54 + $ret += (((0x40 - $src) & ($src - 0x57)) >> 8) & ($src - 54); + + return $ret; + } + + /** + * Uses bitwise operators instead of table-lookups to turn 8-bit integers + * into 5-bit integers. + * + * @param int $src + * @return string + */ + #[Override] + protected static function encode5Bits(int $src): string + { + $src += 0x30; + + // if ($src > 0x39) $src += 0x61 - 0x3a; // 39 + $src += ((0x39 - $src) >> 8) & 39; + + return pack('C', $src); + } + + /** + * Uses bitwise operators instead of table-lookups to turn 8-bit integers + * into 5-bit integers. + * + * Uppercase variant. + * + * @param int $src + * @return string + */ + #[Override] + protected static function encode5BitsUpper(int $src): string + { + $src += 0x30; + + // if ($src > 0x39) $src += 0x41 - 0x3a; // 7 + $src += ((0x39 - $src) >> 8) & 7; + + return pack('C', $src); + } +} \ No newline at end of file diff --git a/vendor/paragonie/constant_time_encoding/src/Base64.php b/vendor/paragonie/constant_time_encoding/src/Base64.php new file mode 100644 index 0000000..9679748 --- /dev/null +++ b/vendor/paragonie/constant_time_encoding/src/Base64.php @@ -0,0 +1,381 @@ + SODIUM_BASE64_VARIANT_ORIGINAL, + Base64UrlSafe::class => SODIUM_BASE64_VARIANT_URLSAFE, + default => 0, + }; + if ($variant > 0) { + try { + return sodium_bin2base64($binString, $variant); + } catch (SodiumException $ex) { + throw new RangeException($ex->getMessage(), $ex->getCode(), $ex); + } + } + } + return static::doEncode($binString, true); + } + + /** + * Encode into Base64, no = padding + * + * Base64 character set "[A-Z][a-z][0-9]+/" + * + * @param string $src + * @return string + * + * @throws TypeError + * @api + */ + public static function encodeUnpadded( + #[SensitiveParameter] + string $src + ): string { + if (extension_loaded('sodium')) { + $variant = match(static::class) { + Base64::class => SODIUM_BASE64_VARIANT_ORIGINAL_NO_PADDING, + Base64UrlSafe::class => SODIUM_BASE64_VARIANT_URLSAFE_NO_PADDING, + default => 0, + }; + if ($variant > 0) { + try { + return sodium_bin2base64($src, $variant); + } catch (SodiumException $ex) { + throw new RangeException($ex->getMessage(), $ex->getCode(), $ex); + } + } + } + return static::doEncode($src, false); + } + + /** + * @param string $src + * @param bool $pad Include = padding? + * @return string + * + * @throws TypeError + */ + protected static function doEncode( + #[SensitiveParameter] + string $src, + bool $pad = true + ): string { + $dest = ''; + $srcLen = strlen($src); + // Main loop (no padding): + for ($i = 0; $i + 3 <= $srcLen; $i += 3) { + /** @var array $chunk */ + $chunk = unpack('C*', substr($src, $i, 3)); + $b0 = $chunk[1]; + $b1 = $chunk[2]; + $b2 = $chunk[3]; + + $dest .= + static::encode6Bits( $b0 >> 2 ) . + static::encode6Bits((($b0 << 4) | ($b1 >> 4)) & 63) . + static::encode6Bits((($b1 << 2) | ($b2 >> 6)) & 63) . + static::encode6Bits( $b2 & 63); + } + // The last chunk, which may have padding: + if ($i < $srcLen) { + /** @var array $chunk */ + $chunk = unpack('C*', substr($src, $i, $srcLen - $i)); + $b0 = $chunk[1]; + if ($i + 1 < $srcLen) { + $b1 = $chunk[2]; + $dest .= + static::encode6Bits($b0 >> 2) . + static::encode6Bits((($b0 << 4) | ($b1 >> 4)) & 63) . + static::encode6Bits(($b1 << 2) & 63); + if ($pad) { + $dest .= '='; + } + } else { + $dest .= + static::encode6Bits( $b0 >> 2) . + static::encode6Bits(($b0 << 4) & 63); + if ($pad) { + $dest .= '=='; + } + } + } + return $dest; + } + + /** + * decode from base64 into binary + * + * Base64 character set "./[A-Z][a-z][0-9]" + * + * @param string $encodedString + * @param bool $strictPadding + * @return string + * + * @throws RangeException + * @throws TypeError + */ + #[Override] + public static function decode( + #[SensitiveParameter] + string $encodedString, + bool $strictPadding = false + ): string { + // Remove padding + $srcLen = strlen($encodedString); + if ($srcLen === 0) { + return ''; + } + + if ($strictPadding) { + if (($srcLen & 3) === 0) { + if ($encodedString[$srcLen - 1] === '=') { + $srcLen--; + if ($encodedString[$srcLen - 1] === '=') { + $srcLen--; + } + } + } + if (($srcLen & 3) === 1) { + throw new RangeException( + 'Incorrect padding' + ); + } + if ($encodedString[$srcLen - 1] === '=') { + throw new RangeException( + 'Incorrect padding' + ); + } + if (extension_loaded('sodium')) { + $variant = match(static::class) { + Base64::class => SODIUM_BASE64_VARIANT_ORIGINAL_NO_PADDING, + Base64UrlSafe::class => SODIUM_BASE64_VARIANT_URLSAFE_NO_PADDING, + default => 0, + }; + if ($variant > 0) { + try { + return sodium_base642bin(substr($encodedString, 0, $srcLen), $variant); + } catch (SodiumException $ex) { + throw new RangeException($ex->getMessage(), $ex->getCode(), $ex); + } + } + } + } else { + // Just remove all padding. + $encodedString = rtrim($encodedString, '='); + $srcLen = strlen($encodedString); + } + + $err = 0; + $dest = ''; + // Main loop (no padding): + for ($i = 0; $i + 4 <= $srcLen; $i += 4) { + /** @var array $chunk */ + $chunk = unpack('C*', substr($encodedString, $i, 4)); + $c0 = static::decode6Bits($chunk[1]); + $c1 = static::decode6Bits($chunk[2]); + $c2 = static::decode6Bits($chunk[3]); + $c3 = static::decode6Bits($chunk[4]); + + $dest .= pack( + 'CCC', + ((($c0 << 2) | ($c1 >> 4)) & 0xff), + ((($c1 << 4) | ($c2 >> 2)) & 0xff), + ((($c2 << 6) | $c3 ) & 0xff) + ); + $err |= ($c0 | $c1 | $c2 | $c3) >> 8; + } + // The last chunk, which may have padding: + if ($i < $srcLen) { + /** @var array $chunk */ + $chunk = unpack('C*', substr($encodedString, $i, $srcLen - $i)); + $c0 = static::decode6Bits($chunk[1]); + + if ($i + 2 < $srcLen) { + $c1 = static::decode6Bits($chunk[2]); + $c2 = static::decode6Bits($chunk[3]); + $dest .= pack( + 'CC', + ((($c0 << 2) | ($c1 >> 4)) & 0xff), + ((($c1 << 4) | ($c2 >> 2)) & 0xff) + ); + $err |= ($c0 | $c1 | $c2) >> 8; + if ($strictPadding) { + $err |= ($c2 << 6) & 0xff; + } + } elseif ($i + 1 < $srcLen) { + $c1 = static::decode6Bits($chunk[2]); + $dest .= pack( + 'C', + ((($c0 << 2) | ($c1 >> 4)) & 0xff) + ); + $err |= ($c0 | $c1) >> 8; + if ($strictPadding) { + $err |= ($c1 << 4) & 0xff; + } + } elseif ($strictPadding) { + $err |= 1; + } + } + $check = ($err === 0); + if (!$check) { + throw new RangeException( + 'Base64::decode() only expects characters in the correct base64 alphabet' + ); + } + return $dest; + } + + /** + * @param string $encodedString + * @return string + * @api + */ + public static function decodeNoPadding( + #[SensitiveParameter] + string $encodedString + ): string { + $srcLen = strlen($encodedString); + if ($srcLen === 0) { + return ''; + } + if (($srcLen & 3) === 0) { + // If $strLen is not zero, and it is divisible by 4, then it's at least 4. + if ($encodedString[$srcLen - 1] === '=' || $encodedString[$srcLen - 2] === '=') { + throw new InvalidArgumentException( + "decodeNoPadding() doesn't tolerate padding" + ); + } + } + return static::decode( + $encodedString, + true + ); + } + + /** + * Uses bitwise operators instead of table-lookups to turn 6-bit integers + * into 8-bit integers. + * + * Base64 character set: + * [A-Z] [a-z] [0-9] + / + * 0x41-0x5a, 0x61-0x7a, 0x30-0x39, 0x2b, 0x2f + * + * @param int $src + * @return int + */ + protected static function decode6Bits(int $src): int + { + $ret = -1; + + // if ($src > 0x40 && $src < 0x5b) $ret += $src - 0x41 + 1; // -64 + $ret += (((0x40 - $src) & ($src - 0x5b)) >> 8) & ($src - 64); + + // if ($src > 0x60 && $src < 0x7b) $ret += $src - 0x61 + 26 + 1; // -70 + $ret += (((0x60 - $src) & ($src - 0x7b)) >> 8) & ($src - 70); + + // if ($src > 0x2f && $src < 0x3a) $ret += $src - 0x30 + 52 + 1; // 5 + $ret += (((0x2f - $src) & ($src - 0x3a)) >> 8) & ($src + 5); + + // if ($src == 0x2b) $ret += 62 + 1; + $ret += (((0x2a - $src) & ($src - 0x2c)) >> 8) & 63; + + // if ($src == 0x2f) ret += 63 + 1; + $ret += (((0x2e - $src) & ($src - 0x30)) >> 8) & 64; + + return $ret; + } + + /** + * Uses bitwise operators instead of table-lookups to turn 8-bit integers + * into 6-bit integers. + * + * @param int $src + * @return string + */ + protected static function encode6Bits(int $src): string + { + $diff = 0x41; + + // if ($src > 25) $diff += 0x61 - 0x41 - 26; // 6 + $diff += ((25 - $src) >> 8) & 6; + + // if ($src > 51) $diff += 0x30 - 0x61 - 26; // -75 + $diff -= ((51 - $src) >> 8) & 75; + + // if ($src > 61) $diff += 0x2b - 0x30 - 10; // -15 + $diff -= ((61 - $src) >> 8) & 15; + + // if ($src > 62) $diff += 0x2f - 0x2b - 1; // 3 + $diff += ((62 - $src) >> 8) & 3; + + return pack('C', $src + $diff); + } +} diff --git a/vendor/paragonie/constant_time_encoding/src/Base64DotSlash.php b/vendor/paragonie/constant_time_encoding/src/Base64DotSlash.php new file mode 100644 index 0000000..8477517 --- /dev/null +++ b/vendor/paragonie/constant_time_encoding/src/Base64DotSlash.php @@ -0,0 +1,92 @@ + 0x2d && $src < 0x30) ret += $src - 0x2e + 1; // -45 + $ret += (((0x2d - $src) & ($src - 0x30)) >> 8) & ($src - 45); + + // if ($src > 0x40 && $src < 0x5b) ret += $src - 0x41 + 2 + 1; // -62 + $ret += (((0x40 - $src) & ($src - 0x5b)) >> 8) & ($src - 62); + + // if ($src > 0x60 && $src < 0x7b) ret += $src - 0x61 + 28 + 1; // -68 + $ret += (((0x60 - $src) & ($src - 0x7b)) >> 8) & ($src - 68); + + // if ($src > 0x2f && $src < 0x3a) ret += $src - 0x30 + 54 + 1; // 7 + $ret += (((0x2f - $src) & ($src - 0x3a)) >> 8) & ($src + 7); + + return $ret; + } + + /** + * Uses bitwise operators instead of table-lookups to turn 8-bit integers + * into 6-bit integers. + * + * @param int $src + * @return string + */ + #[Override] + protected static function encode6Bits(int $src): string + { + $src += 0x2e; + + // if ($src > 0x2f) $src += 0x41 - 0x30; // 17 + $src += ((0x2f - $src) >> 8) & 17; + + // if ($src > 0x5a) $src += 0x61 - 0x5b; // 6 + $src += ((0x5a - $src) >> 8) & 6; + + // if ($src > 0x7a) $src += 0x30 - 0x7b; // -75 + $src -= ((0x7a - $src) >> 8) & 75; + + return \pack('C', $src); + } +} diff --git a/vendor/paragonie/constant_time_encoding/src/Base64DotSlashOrdered.php b/vendor/paragonie/constant_time_encoding/src/Base64DotSlashOrdered.php new file mode 100644 index 0000000..2c42db3 --- /dev/null +++ b/vendor/paragonie/constant_time_encoding/src/Base64DotSlashOrdered.php @@ -0,0 +1,86 @@ + 0x2d && $src < 0x3a) ret += $src - 0x2e + 1; // -45 + $ret += (((0x2d - $src) & ($src - 0x3a)) >> 8) & ($src - 45); + + // if ($src > 0x40 && $src < 0x5b) ret += $src - 0x41 + 12 + 1; // -52 + $ret += (((0x40 - $src) & ($src - 0x5b)) >> 8) & ($src - 52); + + // if ($src > 0x60 && $src < 0x7b) ret += $src - 0x61 + 38 + 1; // -58 + $ret += (((0x60 - $src) & ($src - 0x7b)) >> 8) & ($src - 58); + + return $ret; + } + + /** + * Uses bitwise operators instead of table-lookups to turn 8-bit integers + * into 6-bit integers. + * + * @param int $src + * @return string + */ + #[Override] + protected static function encode6Bits(int $src): string + { + $src += 0x2e; + + // if ($src > 0x39) $src += 0x41 - 0x3a; // 7 + $src += ((0x39 - $src) >> 8) & 7; + + // if ($src > 0x5a) $src += 0x61 - 0x5b; // 6 + $src += ((0x5a - $src) >> 8) & 6; + + return \pack('C', $src); + } +} diff --git a/vendor/paragonie/constant_time_encoding/src/Base64UrlSafe.php b/vendor/paragonie/constant_time_encoding/src/Base64UrlSafe.php new file mode 100644 index 0000000..845aaf6 --- /dev/null +++ b/vendor/paragonie/constant_time_encoding/src/Base64UrlSafe.php @@ -0,0 +1,99 @@ + 0x40 && $src < 0x5b) $ret += $src - 0x41 + 1; // -64 + $ret += (((0x40 - $src) & ($src - 0x5b)) >> 8) & ($src - 64); + + // if ($src > 0x60 && $src < 0x7b) $ret += $src - 0x61 + 26 + 1; // -70 + $ret += (((0x60 - $src) & ($src - 0x7b)) >> 8) & ($src - 70); + + // if ($src > 0x2f && $src < 0x3a) $ret += $src - 0x30 + 52 + 1; // 5 + $ret += (((0x2f - $src) & ($src - 0x3a)) >> 8) & ($src + 5); + + // if ($src == 0x2c) $ret += 62 + 1; + $ret += (((0x2c - $src) & ($src - 0x2e)) >> 8) & 63; + + // if ($src == 0x5f) ret += 63 + 1; + $ret += (((0x5e - $src) & ($src - 0x60)) >> 8) & 64; + + return $ret; + } + + /** + * Uses bitwise operators instead of table-lookups to turn 8-bit integers + * into 6-bit integers. + * + * @param int $src + * @return string + */ + #[Override] + protected static function encode6Bits(int $src): string + { + $diff = 0x41; + + // if ($src > 25) $diff += 0x61 - 0x41 - 26; // 6 + $diff += ((25 - $src) >> 8) & 6; + + // if ($src > 51) $diff += 0x30 - 0x61 - 26; // -75 + $diff -= ((51 - $src) >> 8) & 75; + + // if ($src > 61) $diff += 0x2d - 0x30 - 10; // -13 + $diff -= ((61 - $src) >> 8) & 13; + + // if ($src > 62) $diff += 0x5f - 0x2b - 1; // 3 + $diff += ((62 - $src) >> 8) & 49; + + return \pack('C', $src + $diff); + } +} diff --git a/vendor/paragonie/constant_time_encoding/src/Binary.php b/vendor/paragonie/constant_time_encoding/src/Binary.php new file mode 100644 index 0000000..3695844 --- /dev/null +++ b/vendor/paragonie/constant_time_encoding/src/Binary.php @@ -0,0 +1,87 @@ +getMessage(), $ex->getCode(), $ex); + } + } + $hex = ''; + $len = strlen($binString); + for ($i = 0; $i < $len; ++$i) { + /** @var array $chunk */ + $chunk = unpack('C', $binString[$i]); + $c = $chunk[1] & 0xf; + $b = $chunk[1] >> 4; + + $hex .= pack( + 'CC', + (87 + $b + ((($b - 10) >> 8) & ~38)), + (87 + $c + ((($c - 10) >> 8) & ~38)) + ); + } + return $hex; + } + + /** + * Convert a binary string into a hexadecimal string without cache-timing + * leaks, returning uppercase letters (as per RFC 4648) + * + * @param string $binString (raw binary) + * @return string + * @throws TypeError + */ + public static function encodeUpper( + #[SensitiveParameter] + string $binString + ): string { + $hex = ''; + $len = strlen($binString); + + for ($i = 0; $i < $len; ++$i) { + /** @var array $chunk */ + $chunk = unpack('C', $binString[$i]); + $c = $chunk[1] & 0xf; + $b = $chunk[1] >> 4; + + $hex .= pack( + 'CC', + (55 + $b + ((($b - 10) >> 8) & ~6)), + (55 + $c + ((($c - 10) >> 8) & ~6)) + ); + } + return $hex; + } + + /** + * Convert a hexadecimal string into a binary string without cache-timing + * leaks + * + * @param string $encodedString + * @param bool $strictPadding + * @return string (raw binary) + * @throws RangeException + */ + #[Override] + public static function decode( + #[SensitiveParameter] + string $encodedString, + bool $strictPadding = false + ): string { + if (extension_loaded('sodium') && $strictPadding) { + try { + return sodium_hex2bin($encodedString); + } catch (SodiumException $ex) { + throw new RangeException($ex->getMessage(), $ex->getCode(), $ex); + } + } + $hex_pos = 0; + $bin = ''; + $c_acc = 0; + $hex_len = strlen($encodedString); + $state = 0; + if (($hex_len & 1) !== 0) { + if ($strictPadding) { + throw new RangeException( + 'Expected an even number of hexadecimal characters' + ); + } else { + $encodedString = '0' . $encodedString; + ++$hex_len; + } + } + + /** @var array $chunk */ + $chunk = unpack('C*', $encodedString); + while ($hex_pos < $hex_len) { + ++$hex_pos; + $c = $chunk[$hex_pos]; + $c_num = $c ^ 48; + $c_num0 = ($c_num - 10) >> 8; + $c_alpha = ($c & ~32) - 55; + $c_alpha0 = (($c_alpha - 10) ^ ($c_alpha - 16)) >> 8; + + if (($c_num0 | $c_alpha0) === 0) { + throw new RangeException( + 'Expected hexadecimal character' + ); + } + $c_val = ($c_num0 & $c_num) | ($c_alpha & $c_alpha0); + if ($state === 0) { + $c_acc = $c_val * 16; + } else { + $bin .= pack('C', $c_acc | $c_val); + } + $state ^= 1; + } + return $bin; + } +} diff --git a/vendor/paragonie/constant_time_encoding/src/RFC4648.php b/vendor/paragonie/constant_time_encoding/src/RFC4648.php new file mode 100644 index 0000000..fb66f73 --- /dev/null +++ b/vendor/paragonie/constant_time_encoding/src/RFC4648.php @@ -0,0 +1,208 @@ + "Zm9v" + * + * @param string $str + * @return string + * + * @throws TypeError + */ + public static function base64Encode( + #[SensitiveParameter] + string $str + ): string { + return Base64::encode($str); + } + + /** + * RFC 4648 Base64 decoding + * + * "Zm9v" -> "foo" + * + * @param string $str + * @return string + * + * @throws TypeError + */ + public static function base64Decode( + #[SensitiveParameter] + string $str + ): string { + return Base64::decode($str, true); + } + + /** + * RFC 4648 Base64 (URL Safe) encoding + * + * "foo" -> "Zm9v" + * + * @param string $str + * @return string + * + * @throws TypeError + */ + public static function base64UrlSafeEncode( + #[SensitiveParameter] + string $str + ): string { + return Base64UrlSafe::encode($str); + } + + /** + * RFC 4648 Base64 (URL Safe) decoding + * + * "Zm9v" -> "foo" + * + * @param string $str + * @return string + * + * @throws TypeError + */ + public static function base64UrlSafeDecode( + #[SensitiveParameter] + string $str + ): string { + return Base64UrlSafe::decode($str, true); + } + + /** + * RFC 4648 Base32 encoding + * + * "foo" -> "MZXW6===" + * + * @param string $str + * @return string + * + * @throws TypeError + */ + public static function base32Encode( + #[SensitiveParameter] + string $str + ): string { + return Base32::encodeUpper($str); + } + + /** + * RFC 4648 Base32 encoding + * + * "MZXW6===" -> "foo" + * + * @param string $str + * @return string + * + * @throws TypeError + */ + public static function base32Decode( + #[SensitiveParameter] + string $str + ): string { + return Base32::decodeUpper($str, true); + } + + /** + * RFC 4648 Base32-Hex encoding + * + * "foo" -> "CPNMU===" + * + * @param string $str + * @return string + * + * @throws TypeError + */ + public static function base32HexEncode( + #[SensitiveParameter] + string $str + ): string { + return Base32::encodeUpper($str); + } + + /** + * RFC 4648 Base32-Hex decoding + * + * "CPNMU===" -> "foo" + * + * @param string $str + * @return string + * + * @throws TypeError + */ + public static function base32HexDecode( + #[SensitiveParameter] + string $str + ): string { + return Base32::decodeUpper($str, true); + } + + /** + * RFC 4648 Base16 decoding + * + * "foo" -> "666F6F" + * + * @param string $str + * @return string + * + * @throws TypeError + */ + public static function base16Encode( + #[SensitiveParameter] + string $str + ): string { + return Hex::encodeUpper($str); + } + + /** + * RFC 4648 Base16 decoding + * + * "666F6F" -> "foo" + * + * @param string $str + * @return string + */ + public static function base16Decode( + #[SensitiveParameter] + string $str + ): string { + return Hex::decode($str, true); + } +} diff --git a/vendor/psr/clock/CHANGELOG.md b/vendor/psr/clock/CHANGELOG.md new file mode 100644 index 0000000..3cd6b9b --- /dev/null +++ b/vendor/psr/clock/CHANGELOG.md @@ -0,0 +1,11 @@ +# Changelog + +All notable changes to this project will be documented in this file, in reverse chronological order by release. + +## 1.0.0 + +First stable release after PSR-20 acceptance + +## 0.1.0 + +First release diff --git a/vendor/psr/clock/LICENSE b/vendor/psr/clock/LICENSE new file mode 100644 index 0000000..be68342 --- /dev/null +++ b/vendor/psr/clock/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2017 PHP Framework Interoperability Group + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/vendor/psr/clock/README.md b/vendor/psr/clock/README.md new file mode 100644 index 0000000..6ca877e --- /dev/null +++ b/vendor/psr/clock/README.md @@ -0,0 +1,61 @@ +# PSR Clock + +This repository holds the interface for [PSR-20][psr-url]. + +Note that this is not a clock of its own. It is merely an interface that +describes a clock. See the specification for more details. + +## Installation + +```bash +composer require psr/clock +``` + +## Usage + +If you need a clock, you can use the interface like this: + +```php +clock = $clock; + } + + public function doSomething() + { + /** @var DateTimeImmutable $currentDateAndTime */ + $currentDateAndTime = $this->clock->now(); + // do something useful with that information + } +} +``` + +You can then pick one of the [implementations][implementation-url] of the interface to get a clock. + +If you want to implement the interface, you can require this package and +implement `Psr\Clock\ClockInterface` in your code. + +Don't forget to add `psr/clock-implementation` to your `composer.json`s `provides`-section like this: + +```json +{ + "provides": { + "psr/clock-implementation": "1.0" + } +} +``` + +And please read the [specification text][specification-url] for details on the interface. + +[psr-url]: https://www.php-fig.org/psr/psr-20 +[package-url]: https://packagist.org/packages/psr/clock +[implementation-url]: https://packagist.org/providers/psr/clock-implementation +[specification-url]: https://github.com/php-fig/fig-standards/blob/master/proposed/clock.md diff --git a/vendor/psr/clock/composer.json b/vendor/psr/clock/composer.json new file mode 100644 index 0000000..77992ed --- /dev/null +++ b/vendor/psr/clock/composer.json @@ -0,0 +1,21 @@ +{ + "name": "psr/clock", + "description": "Common interface for reading the clock.", + "keywords": ["psr", "psr-20", "time", "clock", "now"], + "homepage": "https://github.com/php-fig/clock", + "license": "MIT", + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "require": { + "php": "^7.0 || ^8.0" + }, + "autoload": { + "psr-4": { + "Psr\\Clock\\": "src/" + } + } +} diff --git a/vendor/psr/clock/src/ClockInterface.php b/vendor/psr/clock/src/ClockInterface.php new file mode 100644 index 0000000..7b6d8d8 --- /dev/null +++ b/vendor/psr/clock/src/ClockInterface.php @@ -0,0 +1,13 @@ +..`. +The version number may have additional information, such as "-rc1,-rc2,-rc3" to mark release candidate builds for earlier access. +Such releases will be considered as "pre-releases". + +## Minor Release Support Matrix + +| Version | Supported | +|----------|--------------------| +| 11.4.x | :white_check_mark: | +| < 11.4.x | :x: | diff --git a/vendor/spomky-labs/otphp/SECURITY.md b/vendor/spomky-labs/otphp/SECURITY.md new file mode 100644 index 0000000..be7bcd8 --- /dev/null +++ b/vendor/spomky-labs/otphp/SECURITY.md @@ -0,0 +1,74 @@ +# Security Release Process + +OTPHP is devoted to providing the best experience for all developers who want to implement OTP authentication in their applications. +Spomky-Labs has adopted this security disclosure and response policy to ensure we responsibly handle critical issues. + +## Supported Versions + +The OTPHP project maintains release branches for the three most recent minor releases. +Applicable fixes, including security fixes, may be backported to those three release branches, depending on severity and feasibility. Please refer to [RELEASES.md](RELEASES.md) for details. + +## Reporting a Vulnerability - Private Disclosure Process + +Security is of the highest importance and all security vulnerabilities or suspected security vulnerabilities should be reported to OTPHP privately, to minimize attacks against current users of OTPHP before they are fixed. +Vulnerabilities will be investigated and patched on the next patch (or minor) release as soon as possible. +This information could be kept entirely internal to the project. + +If you know of a publicly disclosed security vulnerability for OTPHP, please **IMMEDIATELY** contact security@spomky-labs.com to inform the OTPHP Security Team. + +**IMPORTANT: Do not file public issues on GitHub for security vulnerabilities** + +To report a vulnerability or a security-related issue, please email the private address security@spomky-labs.com with the details of the vulnerability. +The email will be fielded by the OTPHP Security Team, which is made up of the OTPHP maintainers who have committer and release permissions. +Do not report non-security-impacting bugs through this channel. Use [GitHub issues](https://github.com/Spomky-Labs/otphp/issues/new/choose) instead. + +Emails can be encrypted if you wish to share the vulnerability details securely. +The OTPHP Security Team's PGP key is available on the [PGP keyservers](https://keys.openpgp.org/search?q=security%40spomky-labs.com). + +### Proposed Email Content + +Provide a descriptive subject line and in the body of the email include the following information: + +- Basic identity information, such as your name and your affiliation or company. +- Detailed steps to reproduce the vulnerability (POC scripts, screenshots, and compressed packet captures are all helpful to us). +- Description of the effects of the vulnerability on OTPHP and the related hardware and software configurations, so that the OTPHP Security Team can reproduce it. +- How the vulnerability affects OTPHP usage and an estimation of the attack surface, if there is one. +- List other projects or dependencies that were used in conjunction with OTPHP to produce the vulnerability. + +## When to report a vulnerability + +- When you think OTPHP has a potential security vulnerability. +- When you suspect a potential vulnerability, but you are unsure that it impacts OTPHP. +- When you know of or suspect a potential vulnerability on another project that is used by OTPHP. + +## Patch, Release, and Disclosure + +The OTPHP Security Team will respond to vulnerability reports as follows: + +1. The Security Team will investigate the vulnerability and determine its effects and criticality. +2. If the issue is not deemed to be a vulnerability, the Security Team will follow up with a detailed reason for rejection. +3. The Security Team will initiate a conversation with the reporter as soon as possible. +4. If a vulnerability is acknowledged and the timeline for a fix is determined, the Security Team will work on a plan to communicate with the appropriate community, including identifying mitigating steps that affected users can take to protect themselves until the fix is rolled out. +5. The Security Team will work on fixing the vulnerability and perform internal testing before preparing to roll out the fix. +6. A public disclosure date is negotiated by the OTPHP Security Team and the bug submitter. We prefer to fully disclose the bug as soon as possible once a user mitigation or patch is available. It is reasonable to delay disclosure when the bug or the fix is not yet fully understood, the solution is not well-tested, or for distributor coordination. The timeframe for disclosure is from immediate (especially if it's already publicly known) to a few weeks. For a critical vulnerability with a straightforward mitigation, we expect report date to public disclosure date to be on the order of 14 business days. The OTPHP Security Team holds the final say when setting a public disclosure date. +7. Once the fix is confirmed, the Security Team will patch the vulnerability in the next patch or minor release, and backport a patch release into all earlier supported releases. Upon release of the patched version of OTPHP, we will follow the **Public Disclosure Process**. + +### Public Disclosure Process + +The Security Team publishes a public [advisory](https://github.com/Spomky-Labs/otphp/security/advisories) to the OTPHP community via GitHub. In most cases, additional communication via Twitter, blog and other channels will assist in educating OTPHP users and rolling out the patched release to affected users. + +The Security Team will also publish any mitigating steps users can take until the fix can be applied to their OTPHP instances. OTPHP distributors will handle creating and publishing their own security advisories. + +## Mailing lists + +- Use security@spomky-labs.com to report security concerns to the OTPHP Security Team, who uses the list to privately discuss security issues and fixes prior to disclosure. + +## Early Disclosure to OTPHP Distributors List + +This private list is intended to be used primarily to provide actionable information to multiple distributor projects at once. This list is not intended to inform individuals about security issues. + +## Confidentiality, integrity and availability + +We consider vulnerabilities leading to the compromise of data confidentiality, elevation of privilege, or integrity to be our highest priority concerns. +Availability, in particular in areas relating to DoS and resource exhaustion, is also a serious security concern. +The OTPHP Security Team takes all vulnerabilities, potential vulnerabilities, and suspected vulnerabilities seriously and will investigate them in an urgent and expeditious manner. diff --git a/vendor/spomky-labs/otphp/composer.json b/vendor/spomky-labs/otphp/composer.json new file mode 100644 index 0000000..848a574 --- /dev/null +++ b/vendor/spomky-labs/otphp/composer.json @@ -0,0 +1,47 @@ +{ + "name": "spomky-labs/otphp", + "type": "library", + "description": "A PHP library for generating one time passwords according to RFC 4226 (HOTP Algorithm) and the RFC 6238 (TOTP Algorithm) and compatible with Google Authenticator", + "license": "MIT", + "keywords": ["otp", "hotp", "totp", "RFC 4226", "RFC 6238", "Google Authenticator", "FreeOTP"], + "homepage": "https://github.com/Spomky-Labs/otphp", + "authors": [ + { + "name": "Florent Morselli", + "homepage": "https://github.com/Spomky" + }, + { + "name": "All contributors", + "homepage": "https://github.com/Spomky-Labs/otphp/contributors" + } + ], + "require": { + "php": ">=8.1", + "paragonie/constant_time_encoding": "^2.0 || ^3.0", + "psr/clock": "^1.0", + "symfony/deprecation-contracts": "^3.2" + }, + "require-dev": { + "symfony/error-handler": "^6.4|^7.0|^8.0" + }, + "autoload": { + "psr-4": { "OTPHP\\": "src/" } + }, + "autoload-dev": { + "psr-4": { "OTPHP\\Test\\": "tests/" } + }, + "config": { + "allow-plugins": { + "phpstan/extension-installer": true, + "infection/extension-installer": true, + "composer/package-versions-deprecated": true, + "symfony/flex": true, + "symfony/runtime": true + }, + "optimize-autoloader": true, + "preferred-install": { + "*": "dist" + }, + "sort-packages": true + } +} diff --git a/vendor/spomky-labs/otphp/src/Exception/InvalidLabelException.php b/vendor/spomky-labs/otphp/src/Exception/InvalidLabelException.php new file mode 100644 index 0000000..25e188b --- /dev/null +++ b/vendor/spomky-labs/otphp/src/Exception/InvalidLabelException.php @@ -0,0 +1,25 @@ +getScheme() === 'otpauth' || throw new InvalidProvisioningUriException('Invalid scheme.'); + } catch (Throwable $throwable) { + throw new InvalidProvisioningUriException( + 'Not a valid OTP provisioning URI', + $throwable->getCode(), + $throwable + ); + } + if ($clock === null) { + trigger_deprecation( + 'spomky-labs/otphp', + '11.3.0', + 'The parameter "$clock" will become mandatory in 12.0.0. Please set a valid PSR Clock implementation instead of "null".' + ); + $clock = new InternalClock(); + } + + try { + $otp = self::createOTP($parsed_url, $clock); + + self::populateOTP($otp, $parsed_url); + } catch (InvalidProvisioningUriException $exception) { + throw $exception; + } catch (Throwable $throwable) { + throw new InvalidProvisioningUriException( + 'Not a valid OTP provisioning URI', + $throwable->getCode(), + $throwable + ); + } + + return $otp; + } + + private static function populateParameters(OTPInterface $otp, Url $data): void + { + foreach ($data->getQuery() as $key => $value) { + $otp->setParameter($key, $value); + } + } + + private static function populateOTP(OTPInterface $otp, Url $data): void + { + self::populateParameters($otp, $data); + $result = explode(':', rawurldecode(substr($data->getPath(), 1))); + + if (count($result) < 2) { + $otp->setIssuerIncludedAsParameter(false); + + return; + } + + $issuerFromLabel = $result[0]; + $issuerFromParameter = $otp->getIssuer(); + + if ($issuerFromParameter !== null) { + // Issuer parameter takes precedence over issuer in label + // According to Google Authenticator spec: "they should be equal" but not required to be + $otp->setIssuerIncludedAsParameter(true); + } else { + // No issuer parameter, use the issuer from label + $issuerFromLabel !== '' || throw new InvalidProvisioningUriException( + 'Issuer from label must not be empty.' + ); + $otp->setIssuer($issuerFromLabel); + } + } + + private static function createOTP(Url $parsed_url, ClockInterface $clock): OTPInterface + { + switch ($parsed_url->getHost()) { + case 'totp': + $totp = TOTP::createFromSecret($parsed_url->getSecret(), $clock); + $totp->setLabel(self::getLabel($parsed_url->getPath())); + + return $totp; + case 'hotp': + $hotp = HOTP::createFromSecret($parsed_url->getSecret()); + $hotp->setLabel(self::getLabel($parsed_url->getPath())); + + return $hotp; + default: + throw new InvalidProvisioningUriException(sprintf('Unsupported "%s" OTP type', $parsed_url->getHost())); + } + } + + /** + * @param non-empty-string $data + * @return non-empty-string + */ + private static function getLabel(string $data): string + { + $result = explode(':', rawurldecode(substr($data, 1))); + $label = count($result) === 2 ? $result[1] : $result[0]; + $label !== '' || throw new InvalidProvisioningUriException('Label must not be empty.'); + + return $label; + } +} diff --git a/vendor/spomky-labs/otphp/src/FactoryInterface.php b/vendor/spomky-labs/otphp/src/FactoryInterface.php new file mode 100644 index 0000000..e34056a --- /dev/null +++ b/vendor/spomky-labs/otphp/src/FactoryInterface.php @@ -0,0 +1,18 @@ +setCounter($counter); + $htop->setDigest($digest); + $htop->setDigits($digits); + + return $htop; + } + + public static function createFromSecret(string $secret): self + { + $htop = new self($secret); + $htop->setCounter(self::DEFAULT_COUNTER); + $htop->setDigest(self::DEFAULT_DIGEST); + $htop->setDigits(self::DEFAULT_DIGITS); + + return $htop; + } + + /** + * @param positive-int|null $secretSize + */ + public static function generate(?int $secretSize = null): self + { + return self::createFromSecret(self::generateSecret($secretSize)); + } + + /** + * @return 0|positive-int + */ + public function getCounter(): int + { + $value = $this->getParameter('counter'); + (is_int($value) && $value >= 0) || throw new InvalidParameterException( + 'Invalid "counter" parameter.', + 'counter', + $value + ); + + return $value; + } + + public function getProvisioningUri(): string + { + return $this->generateURI('hotp', [ + 'counter' => $this->getCounter(), + ]); + } + + /** + * If the counter is not provided, the OTP is verified at the actual counter. + * + * @param null|0|positive-int $counter + */ + public function verify(string $otp, null|int $counter = null, null|int $window = null): bool + { + $counter >= 0 || throw new InvalidParameterException( + 'The counter must be at least 0.', + 'counter', + $counter + ); + + if ($counter === null) { + $counter = $this->getCounter(); + } elseif ($counter < $this->getCounter()) { + return false; + } + + return $this->verifyOtpWithWindow($otp, $counter, $window); + } + + public function setCounter(int $counter): void + { + $this->setParameter('counter', $counter); + } + + public function withCounter(int $counter): self + { + $otp = clone $this; + $otp->setParameter('counter', $counter); + + return $otp; + } + + /** + * @return array + */ + protected function getParameterMap(): array + { + return [...parent::getParameterMap(), ...[ + 'counter' => static function (mixed $value): int { + $value = (int) $value; + $value >= 0 || throw new InvalidParameterException( + 'Counter must be at least 0.', + 'counter', + $value + ); + + return $value; + }, + ]]; + } + + private function updateCounter(int $counter): void + { + $this->setCounter($counter); + } + + /** + * @param null|0|positive-int $window + */ + private function getWindow(null|int $window): int + { + return abs($window ?? self::DEFAULT_WINDOW); + } + + /** + * @param non-empty-string $otp + * @param 0|positive-int $counter + * @param null|0|positive-int $window + */ + private function verifyOtpWithWindow(string $otp, int $counter, null|int $window): bool + { + $window = $this->getWindow($window); + + for ($i = $counter; $i <= $counter + $window; ++$i) { + if ($this->compareOTP($this->at($i), $otp)) { + $this->updateCounter($i + 1); + + return true; + } + } + + return false; + } +} diff --git a/vendor/spomky-labs/otphp/src/HOTPInterface.php b/vendor/spomky-labs/otphp/src/HOTPInterface.php new file mode 100644 index 0000000..fe6382d --- /dev/null +++ b/vendor/spomky-labs/otphp/src/HOTPInterface.php @@ -0,0 +1,41 @@ + + */ + private array $parameters = []; + + /** + * @var non-empty-string|null + */ + private null|string $issuer = null; + + /** + * @var non-empty-string|null + */ + private null|string $label = null; + + private bool $issuer_included_as_parameter = true; + + /** + * @param non-empty-string $secret + */ + protected function __construct(string $secret) + { + $this->setSecret($secret); + } + + public function getQrCodeUri(string $uri, string $placeholder): string + { + $provisioning_uri = urlencode($this->getProvisioningUri()); + + return str_replace($placeholder, $provisioning_uri, $uri); + } + + /** + * @param 0|positive-int $input + */ + public function at(int $input): string + { + return $this->generateOTP($input); + } + + /** + * @return array + */ + public function getParameters(): array + { + $parameters = $this->parameters; + + if ($this->getIssuer() !== null && $this->isIssuerIncludedAsParameter() === true) { + $parameters['issuer'] = $this->getIssuer(); + } + + return $parameters; + } + + public function getSecret(): string + { + $value = $this->getParameter('secret'); + (is_string($value) && $value !== '') || throw new InvalidParameterException( + 'Invalid "secret" parameter.', + 'secret', + $value + ); + + return $value; + } + + public function getLabel(): null|string + { + return $this->label; + } + + public function setLabel(string $label): void + { + $this->setParameter('label', $label); + } + + public function withLabel(string $label): static + { + $otp = clone $this; + $otp->setParameter('label', $label); + + return $otp; + } + + public function getIssuer(): null|string + { + return $this->issuer; + } + + public function setIssuer(string $issuer): void + { + $this->setParameter('issuer', $issuer); + } + + public function withIssuer(string $issuer): static + { + $otp = clone $this; + $otp->setParameter('issuer', $issuer); + + return $otp; + } + + public function isIssuerIncludedAsParameter(): bool + { + return $this->issuer_included_as_parameter; + } + + public function setIssuerIncludedAsParameter(bool $issuer_included_as_parameter): void + { + $this->issuer_included_as_parameter = $issuer_included_as_parameter; + } + + public function withIssuerIncludedAsParameter(bool $issuer_included_as_parameter): static + { + $otp = clone $this; + $otp->issuer_included_as_parameter = $issuer_included_as_parameter; + + return $otp; + } + + public function getDigits(): int + { + $value = $this->getParameter('digits'); + (is_int($value) && $value >= 1 && $value <= self::MAX_DIGITS) || throw new InvalidParameterException( + 'Invalid "digits" parameter.', + 'digits', + $value + ); + + return $value; + } + + public function getDigest(): string + { + $value = $this->getParameter('algorithm'); + (is_string($value) && $value !== '') || throw new InvalidParameterException( + 'Invalid "algorithm" parameter.', + 'algorithm', + $value + ); + + return $value; + } + + public function hasParameter(string $parameter): bool + { + return array_key_exists($parameter, $this->parameters); + } + + public function getParameter(string $parameter): mixed + { + if ($this->hasParameter($parameter)) { + return $this->getParameters()[$parameter]; + } + + throw new ParameterNotFoundException(sprintf('Parameter "%s" does not exist', $parameter), $parameter); + } + + public function setParameter(string $parameter, mixed $value): void + { + $map = $this->getParameterMap(); + + if (array_key_exists($parameter, $map) === true) { + $callback = $map[$parameter]; + $value = $callback($value); + } + + if (in_array($parameter, ['label', 'issuer'], true)) { + $this->{$parameter} = $value; + } else { + $this->parameters[$parameter] = $value; + } + } + + public function withParameter(string $parameter, mixed $value): static + { + $otp = clone $this; + $otp->setParameter($parameter, $value); + + return $otp; + } + + public function setSecret(string $secret): void + { + $this->setParameter('secret', $secret); + } + + public function withSecret(string $secret): static + { + $otp = clone $this; + $otp->setParameter('secret', $secret); + + return $otp; + } + + public function setDigits(int $digits): void + { + $this->setParameter('digits', $digits); + } + + public function withDigits(int $digits): static + { + $otp = clone $this; + $otp->setParameter('digits', $digits); + + return $otp; + } + + public function setDigest(string $digest): void + { + $this->setParameter('algorithm', $digest); + } + + public function withDigest(string $digest): static + { + $otp = clone $this; + $otp->setParameter('algorithm', $digest); + + return $otp; + } + + /** + * @param positive-int|null $secretSize + * + * @return non-empty-string + */ + final protected static function generateSecret(?int $secretSize = null): string + { + $secretSize ??= self::DEFAULT_SECRET_SIZE; + $secretSize > 0 || throw new InvalidParameterException( + 'Secret size must be at least 1.', + 'secretSize', + $secretSize + ); + + return Base32::encodeUpper(random_bytes($secretSize)); + } + + /** + * The OTP at the specified input. + * + * @param 0|positive-int $input + * + * @return non-empty-string + */ + protected function generateOTP(int $input): string + { + $hash = hash_hmac($this->getDigest(), $this->intToByteString($input), $this->getDecodedSecret(), true); + $unpacked = unpack('C*', $hash); + $unpacked !== false || throw new InvalidParameterException('Invalid data.', 'hash', $hash); + /** @var list $hmac */ + $hmac = array_values($unpacked); + + $offset = ($hmac[count($hmac) - 1] & 0xF); + $code = ($hmac[$offset] & 0x7F) << 24 | ($hmac[$offset + 1] & 0xFF) << 16 | ($hmac[$offset + 2] & 0xFF) << 8 | ($hmac[$offset + 3] & 0xFF); + $otp = $code % (10 ** $this->getDigits()); + + return str_pad((string) $otp, $this->getDigits(), '0', STR_PAD_LEFT); + } + + /** + * @param array $options + */ + protected function filterOptions(array &$options): void + { + foreach ([ + 'algorithm' => 'sha1', + 'period' => 30, + 'digits' => 6, + ] as $key => $default) { + if (isset($options[$key]) && $default === $options[$key]) { + unset($options[$key]); + } + } + + ksort($options); + } + + /** + * @param non-empty-string $type + * @param array $options + * + * @return non-empty-string + */ + protected function generateURI(string $type, array $options): string + { + $options = [...$options, ...$this->getParameters()]; + $this->filterOptions($options); + $params = str_replace(['+', '%7E'], ['%20', '~'], http_build_query($options, '', '&')); + + return sprintf('otpauth://%s/%s?%s', $type, rawurlencode($this->buildProvisioningUriLabel()), $params); + } + + /** + * @param non-empty-string $safe + * @param non-empty-string $user + */ + protected function compareOTP(string $safe, string $user): bool + { + return hash_equals($safe, $user); + } + + /** + * @return array + */ + protected function getParameterMap(): array + { + return [ + 'label' => function (string $value): string { + $value !== '' || throw new InvalidLabelException('Label must not be empty.', 'label', $value); + $this->validateLabel($value); + + return $value; + }, + 'secret' => static fn (string $value): string => strtoupper(trim($value, '=')), + 'algorithm' => static function (string $value): string { + $value = strtolower($value); + in_array($value, hash_hmac_algos(), true) || throw new InvalidParameterException( + sprintf('The "%s" digest is not supported.', $value), + 'algorithm', + $value + ); + $size = strlen(hash($value, '', true)); + $size >= self::MINIMUM_DIGEST_SIZE || throw new InvalidParameterException( + sprintf( + 'The "%s" digest produces a %d-byte hash which is too short for the RFC 4226 dynamic truncation; at least %d bytes are required.', + $value, + $size, + self::MINIMUM_DIGEST_SIZE + ), + 'algorithm', + $value + ); + + return $value; + }, + 'digits' => static function ($value): int { + $value = (int) $value; + ($value >= 1 && $value <= self::MAX_DIGITS) || throw new InvalidParameterException( + sprintf('Digits must be between 1 and %d.', self::MAX_DIGITS), + 'digits', + $value + ); + + return $value; + }, + 'issuer' => function (string $value): string { + $value !== '' || throw new InvalidLabelException('Issuer must not be empty.', 'issuer', $value); + $this->hasColon($value) === false || throw new InvalidLabelException( + 'Issuer must not contain a colon.', + 'issuer', + $value + ); + + return $value; + }, + ]; + } + + /** + * @return non-empty-string + */ + private function getDecodedSecret(): string + { + try { + $decoded = Base32::decodeUpper($this->getSecret()); + } catch (Exception) { + throw new SecretDecodingException('Unable to decode the secret. Is it correctly base32 encoded?'); + } + $decoded !== '' || throw new SecretDecodingException('The decoded secret must not be empty.'); + + return $decoded; + } + + private function intToByteString(int $int): string + { + $result = []; + while ($int !== 0) { + $result[] = chr($int & 0xFF); + $int >>= 8; + } + + return str_pad(implode('', array_reverse($result)), 8, "\000", STR_PAD_LEFT); + } + + /** + * @return non-empty-string + */ + private function buildProvisioningUriLabel(): string + { + $issuer = $this->getIssuer(); + $label = $this->getLabel(); + + return match (true) { + $issuer === null && $label === null => throw new InvalidLabelException( + 'The label is not set. Either label or issuer must be set.', + 'label' + ), + $label !== null && $this->hasColon($label) => throw new InvalidLabelException( + 'Label must not contain a colon.', + 'label', + $label + ), + $issuer !== null && $label !== null => $issuer . ':' . $label, + $issuer !== null => $issuer, + default => $label, + }; + } + + /** + * Validates a label according to Google Authenticator spec: + * label = accountname / issuer (":" / "%3A") *"%20" accountname + * Neither issuer nor account name may themselves contain a colon. + * + * Valid examples: + * - alice@gmail.com + * - Provider1:Alice%20Smith + * - Big%20Corporation%3A%20alice%40bigco.com + * + * @param non-empty-string $value + */ + private function validateLabel(string $value): void + { + // Check for colon separators (literal or URL-encoded) + $hasLiteralColon = str_contains($value, ':'); + $hasEncodedColon = str_contains($value, '%3A') || str_contains($value, '%3a'); + + if (! $hasLiteralColon && ! $hasEncodedColon) { + // Simple label (account name only) - no colons allowed anywhere + return; + } + + // Label contains a separator - validate issuer:account format + // Split by literal or encoded colon + $parts = match (true) { + $hasLiteralColon => explode(':', $value, 2), + default => preg_split('/%3[Aa]/', $value, 2), + }; + + if ($parts === false || count($parts) !== 2) { + throw new InvalidLabelException('Label must not contain a colon.', 'label', $value); + } + + [$issuerPart, $accountPart] = $parts; + + // Remove leading %20 (spaces) from account part per spec: *"%20" accountname + $accountPart = ltrim($accountPart, '%20'); + + // Validate that neither part contains additional colons + if ($this->hasColon($issuerPart) || $this->hasColon($accountPart)) { + throw new InvalidLabelException( + 'Neither issuer nor account name in label may contain a colon.', + 'label', + $value + ); + } + } + + /** + * @param non-empty-string $value + */ + private function hasColon(string $value): bool + { + $colons = [':', '%3A', '%3a']; + foreach ($colons as $colon) { + if (str_contains($value, $colon)) { + return true; + } + } + + return false; + } +} diff --git a/vendor/spomky-labs/otphp/src/OTPInterface.php b/vendor/spomky-labs/otphp/src/OTPInterface.php new file mode 100644 index 0000000..2ec5e4e --- /dev/null +++ b/vendor/spomky-labs/otphp/src/OTPInterface.php @@ -0,0 +1,185 @@ + + */ + public function getParameters(): array; + + /** + * @param non-empty-string $parameter + * + * @deprecated Deprecated since v11.4, use {@see self::withParameter()} instead + */ + public function setParameter(string $parameter, mixed $value): void; + + /** + * @param non-empty-string $parameter + */ + public function withParameter(string $parameter, mixed $value): self; + + /** + * Get the provisioning URI. + * + * @return non-empty-string + */ + public function getProvisioningUri(): string; + + /** + * Get the provisioning URI. + * + * @param non-empty-string $uri The Uri of the QRCode generator with all parameters. This Uri MUST contain a placeholder that will be replaced by the method. + * @param non-empty-string $placeholder the placeholder to be replaced in the QR Code generator URI + */ + public function getQrCodeUri(string $uri, string $placeholder): string; +} diff --git a/vendor/spomky-labs/otphp/src/TOTP.php b/vendor/spomky-labs/otphp/src/TOTP.php new file mode 100644 index 0000000..3cb8b10 --- /dev/null +++ b/vendor/spomky-labs/otphp/src/TOTP.php @@ -0,0 +1,262 @@ +clock = $clock; + } + + public static function create( + null|string $secret = null, + int $period = self::DEFAULT_PERIOD, + string $digest = self::DEFAULT_DIGEST, + int $digits = self::DEFAULT_DIGITS, + int $epoch = self::DEFAULT_EPOCH, + ?ClockInterface $clock = null, + ?int $secretSize = null + ): self { + $totp = $secret !== null + ? self::createFromSecret($secret, $clock) + : self::generate($clock, $secretSize) + ; + $totp->setPeriod($period); + $totp->setDigest($digest); + $totp->setDigits($digits); + $totp->setEpoch($epoch); + + return $totp; + } + + public static function createFromSecret(string $secret, ?ClockInterface $clock = null): self + { + $totp = new self($secret, $clock); + $totp->setPeriod(self::DEFAULT_PERIOD); + $totp->setDigest(self::DEFAULT_DIGEST); + $totp->setDigits(self::DEFAULT_DIGITS); + $totp->setEpoch(self::DEFAULT_EPOCH); + + return $totp; + } + + /** + * @param positive-int|null $secretSize + */ + public static function generate(?ClockInterface $clock = null, ?int $secretSize = null): self + { + return self::createFromSecret(self::generateSecret($secretSize), $clock); + } + + public function getPeriod(): int + { + $value = $this->getParameter('period'); + (is_int($value) && $value > 0) || throw new InvalidParameterException( + 'Invalid "period" parameter.', + 'period', + $value + ); + + return $value; + } + + public function getEpoch(): int + { + $value = $this->getParameter('epoch'); + (is_int($value) && $value >= 0) || throw new InvalidParameterException( + 'Invalid "epoch" parameter.', + 'epoch', + $value + ); + + return $value; + } + + public function expiresIn(): int + { + $period = $this->getPeriod(); + + return $period - (($this->clock->now()->getTimestamp() - $this->getEpoch()) % $period); + } + + /** + * The OTP at the specified input. + * + * @param 0|positive-int $input + */ + public function at(int $input): string + { + return $this->generateOTP($this->timecode($input)); + } + + public function now(): string + { + $timestamp = $this->clock->now() + ->getTimestamp(); + $timestamp >= 0 || throw new InvalidParameterException( + 'The timestamp must return a positive integer.', + 'timestamp', + $timestamp + ); + + return $this->at($timestamp); + } + + /** + * If no timestamp is provided, the OTP is verified at the actual timestamp. When used, the leeway parameter will + * allow time drift. The passed value is in seconds. + * + * @param 0|positive-int $timestamp + * @param null|0|positive-int $leeway + */ + public function verify(string $otp, null|int $timestamp = null, null|int $leeway = null): bool + { + $timestamp ??= $this->clock->now() + ->getTimestamp(); + $timestamp >= 0 || throw new InvalidParameterException( + 'Timestamp must be at least 0.', + 'timestamp', + $timestamp + ); + + if ($leeway === null) { + return $this->compareOTP($this->at($timestamp), $otp); + } + + $leeway = abs($leeway); + $leeway < $this->getPeriod() || throw new InvalidParameterException( + 'The leeway must be lower than the TOTP period', + 'leeway', + $leeway + ); + $timestampMinusLeeway = $timestamp - $leeway; + $timestampMinusLeeway >= 0 || throw new InvalidParameterException( + 'The timestamp must be greater than or equal to the leeway.', + 'timestamp', + $timestamp + ); + + return $this->compareOTP($this->at($timestampMinusLeeway), $otp) + || $this->compareOTP($this->at($timestamp), $otp) + || $this->compareOTP($this->at($timestamp + $leeway), $otp); + } + + public function getProvisioningUri(): string + { + $params = []; + if ($this->getPeriod() !== 30) { + $params['period'] = $this->getPeriod(); + } + + if ($this->getEpoch() !== 0) { + $params['epoch'] = $this->getEpoch(); + } + + return $this->generateURI('totp', $params); + } + + public function setPeriod(int $period): void + { + $this->setParameter('period', $period); + } + + public function withPeriod(int $period): self + { + $otp = clone $this; + $otp->setParameter('period', $period); + + return $otp; + } + + public function setEpoch(int $epoch): void + { + $this->setParameter('epoch', $epoch); + } + + public function withEpoch(int $epoch): self + { + $otp = clone $this; + $otp->setParameter('epoch', $epoch); + + return $otp; + } + + /** + * @return array + */ + protected function getParameterMap(): array + { + return [ + ...parent::getParameterMap(), + 'period' => static function ($value): int { + (int) $value > 0 || throw new InvalidParameterException('Period must be at least 1.', 'period', $value); + + return (int) $value; + }, + 'epoch' => static function ($value): int { + (int) $value >= 0 || throw new InvalidParameterException( + 'Epoch must be greater than or equal to 0.', + 'epoch', + $value + ); + + return (int) $value; + }, + ]; + } + + /** + * @param array $options + */ + protected function filterOptions(array &$options): void + { + parent::filterOptions($options); + + if (isset($options['epoch']) && $options['epoch'] === 0) { + unset($options['epoch']); + } + + ksort($options); + } + + /** + * @param 0|positive-int $timestamp + * + * @return 0|positive-int + */ + private function timecode(int $timestamp): int + { + $timecode = (int) floor(($timestamp - $this->getEpoch()) / $this->getPeriod()); + $timecode >= 0 || throw new InvalidParameterException( + 'Timecode must be at least 0. The timestamp must be greater than or equal to the epoch.', + 'timecode', + $timecode + ); + + return $timecode; + } +} diff --git a/vendor/spomky-labs/otphp/src/TOTPInterface.php b/vendor/spomky-labs/otphp/src/TOTPInterface.php new file mode 100644 index 0000000..4288aa6 --- /dev/null +++ b/vendor/spomky-labs/otphp/src/TOTPInterface.php @@ -0,0 +1,61 @@ + $query + */ + public function __construct( + private readonly string $scheme, + private readonly string $host, + private readonly string $path, + private readonly string $secret, + private readonly array $query + ) { + } + + /** + * @return non-empty-string + */ + public function getScheme(): string + { + return $this->scheme; + } + + /** + * @return non-empty-string + */ + public function getHost(): string + { + return $this->host; + } + + /** + * @return non-empty-string + */ + public function getPath(): string + { + return $this->path; + } + + /** + * @return non-empty-string + */ + public function getSecret(): string + { + return $this->secret; + } + + /** + * @return array + */ + public function getQuery(): array + { + return $this->query; + } + + /** + * @param non-empty-string $uri + */ + public static function fromString(string $uri): self + { + $parsed_url = parse_url($uri); + $parsed_url !== false || throw new InvalidProvisioningUriException('Invalid URI.'); + foreach (['scheme', 'host', 'path', 'query'] as $key) { + array_key_exists($key, $parsed_url) || throw new InvalidProvisioningUriException( + 'Not a valid OTP provisioning URI' + ); + } + $scheme = $parsed_url['scheme'] ?? null; + $host = $parsed_url['host'] ?? null; + $path = $parsed_url['path'] ?? null; + $query = $parsed_url['query'] ?? null; + $scheme === 'otpauth' || throw new InvalidProvisioningUriException('Not a valid OTP provisioning URI'); + (is_string($host) && $host !== '') || throw new InvalidProvisioningUriException('Invalid URI.'); + (is_string($path) && $path !== '') || throw new InvalidProvisioningUriException('Invalid URI.'); + is_string($query) || throw new InvalidProvisioningUriException('Invalid URI.'); + $parsedQuery = []; + parse_str($query, $parsedQuery); + array_key_exists('secret', $parsedQuery) || throw new InvalidProvisioningUriException( + 'Not a valid OTP provisioning URI' + ); + $secret = $parsedQuery['secret']; + (is_string($secret) && $secret !== '') || throw new InvalidProvisioningUriException('Invalid URI.'); + unset($parsedQuery['secret']); + + return new self($scheme, $host, $path, $secret, $parsedQuery); + } +} diff --git a/vendor/symfony/deprecation-contracts/CHANGELOG.md b/vendor/symfony/deprecation-contracts/CHANGELOG.md new file mode 100644 index 0000000..7932e26 --- /dev/null +++ b/vendor/symfony/deprecation-contracts/CHANGELOG.md @@ -0,0 +1,5 @@ +CHANGELOG +========= + +The changelog is maintained for all Symfony contracts at the following URL: +https://github.com/symfony/contracts/blob/main/CHANGELOG.md diff --git a/vendor/symfony/deprecation-contracts/LICENSE b/vendor/symfony/deprecation-contracts/LICENSE new file mode 100644 index 0000000..0ed3a24 --- /dev/null +++ b/vendor/symfony/deprecation-contracts/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2020-present Fabien Potencier + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/vendor/symfony/deprecation-contracts/README.md b/vendor/symfony/deprecation-contracts/README.md new file mode 100644 index 0000000..9814864 --- /dev/null +++ b/vendor/symfony/deprecation-contracts/README.md @@ -0,0 +1,26 @@ +Symfony Deprecation Contracts +============================= + +A generic function and convention to trigger deprecation notices. + +This package provides a single global function named `trigger_deprecation()` that triggers silenced deprecation notices. + +By using a custom PHP error handler such as the one provided by the Symfony ErrorHandler component, +the triggered deprecations can be caught and logged for later discovery, both on dev and prod environments. + +The function requires at least 3 arguments: + - the name of the Composer package that is triggering the deprecation + - the version of the package that introduced the deprecation + - the message of the deprecation + - more arguments can be provided: they will be inserted in the message using `printf()` formatting + +Example: +```php +trigger_deprecation('symfony/blockchain', '8.9', 'Using "%s" is deprecated, use "%s" instead.', 'bitcoin', 'fabcoin'); +``` + +This will generate the following message: +`Since symfony/blockchain 8.9: Using "bitcoin" is deprecated, use "fabcoin" instead.` + +While not recommended, the deprecation notices can be completely ignored by declaring an empty +`function trigger_deprecation() {}` in your application. diff --git a/vendor/symfony/deprecation-contracts/composer.json b/vendor/symfony/deprecation-contracts/composer.json new file mode 100644 index 0000000..9279eb1 --- /dev/null +++ b/vendor/symfony/deprecation-contracts/composer.json @@ -0,0 +1,35 @@ +{ + "name": "symfony/deprecation-contracts", + "type": "library", + "description": "A generic function and convention to trigger deprecation notices", + "homepage": "https://symfony.com", + "license": "MIT", + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "require": { + "php": ">=8.1" + }, + "autoload": { + "files": [ + "function.php" + ] + }, + "minimum-stability": "dev", + "extra": { + "branch-alias": { + "dev-main": "3.7-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + } +} diff --git a/vendor/symfony/deprecation-contracts/function.php b/vendor/symfony/deprecation-contracts/function.php new file mode 100644 index 0000000..2d56512 --- /dev/null +++ b/vendor/symfony/deprecation-contracts/function.php @@ -0,0 +1,27 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +if (!function_exists('trigger_deprecation')) { + /** + * Triggers a silenced deprecation notice. + * + * @param string $package The name of the Composer package that is triggering the deprecation + * @param string $version The version of the package that introduced the deprecation + * @param string $message The message of the deprecation + * @param mixed ...$args Values to insert in the message using printf() formatting + * + * @author Nicolas Grekas + */ + function trigger_deprecation(string $package, string $version, string $message, mixed ...$args): void + { + @trigger_error(($package || $version ? "Since $package $version: " : '').($args ? vsprintf($message, $args) : $message), \E_USER_DEPRECATED); + } +} diff --git a/xml/constants.xml b/xml/constants.xml index 41d59ba..57dec52 100644 --- a/xml/constants.xml +++ b/xml/constants.xml @@ -12,6 +12,7 @@ User Administrator Guest + Super System Administrator diff --git a/xsl/addAlert.xsl b/xsl/addAlert.xsl index 094b997..1ca02e2 100644 --- a/xsl/addAlert.xsl +++ b/xsl/addAlert.xsl @@ -10,9 +10,11 @@ addAlert - + + +