@mohasinac/appkit 4.62.1 → 4.63.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/.build-stamp.json +3 -3
- package/dist/_internal/client/features/layout/DashboardLayoutClient.js +8 -29
- package/dist/_internal/client/features/layout/filterNavItems.d.ts +28 -0
- package/dist/_internal/client/features/layout/filterNavItems.js +35 -0
- package/dist/_internal/server/features/ads/booking.d.ts +118 -0
- package/dist/_internal/server/features/ads/booking.js +326 -0
- package/dist/_internal/server/features/checkout/actions.d.ts +51 -11
- package/dist/_internal/server/features/checkout/actions.js +335 -80
- package/dist/_internal/server/features/checkout/expand-order-items.d.ts +1 -2
- package/dist/_internal/server/features/checkout/expand-order-items.js +32 -0
- package/dist/_internal/server/features/checkout/freeze-parts.d.ts +50 -0
- package/dist/_internal/server/features/checkout/freeze-parts.js +94 -0
- package/dist/_internal/server/features/checkout/value-otp-gate.d.ts +55 -0
- package/dist/_internal/server/features/checkout/value-otp-gate.js +60 -0
- package/dist/_internal/server/features/dashboard/attention.d.ts +128 -0
- package/dist/_internal/server/features/dashboard/attention.js +183 -0
- package/dist/_internal/server/features/dashboard/data.d.ts +47 -0
- package/dist/_internal/server/features/dashboard/data.js +82 -0
- package/dist/_internal/server/features/inventory/reservations.d.ts +99 -0
- package/dist/_internal/server/features/inventory/reservations.js +273 -0
- package/dist/_internal/server/features/offers/destinations.d.ts +40 -0
- package/dist/_internal/server/features/offers/destinations.js +65 -0
- package/dist/_internal/server/features/orders/adapters.js +21 -0
- package/dist/_internal/server/features/orders/amend-delivery.d.ts +56 -0
- package/dist/_internal/server/features/orders/amend-delivery.js +124 -0
- package/dist/_internal/server/features/orders/balance.d.ts +89 -0
- package/dist/_internal/server/features/orders/balance.js +256 -0
- package/dist/_internal/server/features/pricing/actions.d.ts +58 -0
- package/dist/_internal/server/features/pricing/actions.js +144 -0
- package/dist/_internal/server/features/shipping/book-split.d.ts +86 -0
- package/dist/_internal/server/features/shipping/book-split.js +130 -0
- package/dist/_internal/server/features/shipping/book.d.ts +61 -0
- package/dist/_internal/server/features/shipping/book.js +176 -0
- package/dist/_internal/server/features/shipping/courier-block.js +26 -1
- package/dist/_internal/server/features/site-settings/adapters.d.ts +1 -1
- package/dist/_internal/server/features/site-settings/adapters.js +14 -0
- package/dist/_internal/server/features/stores/adapters.d.ts +1 -1
- package/dist/_internal/server/features/stores/adapters.js +14 -0
- package/dist/_internal/server/functions/scheduled.d.ts +2 -1
- package/dist/_internal/server/functions/scheduled.js +57 -1
- package/dist/_internal/server/jobs/core/autoPayoutEligibility.js +2 -0
- package/dist/_internal/server/jobs/core/jobRunners.js +45 -0
- package/dist/_internal/server/jobs/core/onOrderStatusChange.js +4 -1
- package/dist/_internal/server/jobs/core/reservationExpiry.d.ts +17 -0
- package/dist/_internal/server/jobs/core/reservationExpiry.js +40 -0
- package/dist/_internal/server/jobs/core/weeklyPayoutEligibility.js +15 -0
- package/dist/_internal/server/jobs/handlers/index.d.ts +1 -0
- package/dist/_internal/server/jobs/handlers/index.js +1 -0
- package/dist/_internal/server/jobs/handlers/reservationExpiry.d.ts +2 -0
- package/dist/_internal/server/jobs/handlers/reservationExpiry.js +2 -0
- package/dist/_internal/shared/actions/action-registry.d.ts +1 -1
- package/dist/_internal/shared/actions/action-registry.js +268 -0
- package/dist/_internal/shared/checkout/order-math.d.ts +31 -2
- package/dist/_internal/shared/checkout/order-math.js +22 -36
- package/dist/_internal/shared/checkout/rules/index.d.ts +1 -1
- package/dist/_internal/shared/checkout/rules/index.js +1 -1
- package/dist/_internal/shared/checkout/rules/payment-gate.d.ts +18 -0
- package/dist/_internal/shared/checkout/rules/payment-gate.js +25 -0
- package/dist/_internal/shared/checkout/split.d.ts +0 -12
- package/dist/_internal/shared/checkout/split.js +22 -2
- package/dist/_internal/shared/content/disclaimers.js +7 -7
- package/dist/_internal/shared/content/published-values.d.ts +6 -1
- package/dist/_internal/shared/content/published-values.js +8 -0
- package/dist/_internal/shared/features/admin/integrations.d.ts +32 -2
- package/dist/_internal/shared/features/admin/integrations.js +19 -9
- package/dist/_internal/shared/features/dashboard/hub-sections.d.ts +72 -0
- package/dist/_internal/shared/features/dashboard/hub-sections.js +75 -0
- package/dist/_internal/shared/features/emi/choice.d.ts +98 -0
- package/dist/_internal/shared/features/emi/choice.js +69 -0
- package/dist/_internal/shared/features/emi/group.d.ts +84 -0
- package/dist/_internal/shared/features/emi/group.js +126 -0
- package/dist/_internal/shared/features/ledger/posting.d.ts +107 -0
- package/dist/_internal/shared/features/ledger/posting.js +165 -0
- package/dist/_internal/shared/features/ledger/reports.d.ts +76 -0
- package/dist/_internal/shared/features/ledger/reports.js +127 -0
- package/dist/_internal/shared/features/ledger/rules.d.ts +170 -0
- package/dist/_internal/shared/features/ledger/rules.js +221 -0
- package/dist/_internal/shared/features/offers/coordination.d.ts +122 -0
- package/dist/_internal/shared/features/offers/coordination.js +80 -0
- package/dist/_internal/shared/features/orders/delivery-snapshot.d.ts +114 -0
- package/dist/_internal/shared/features/orders/delivery-snapshot.js +116 -0
- package/dist/_internal/shared/features/payouts/pay-period.d.ts +91 -0
- package/dist/_internal/shared/features/payouts/pay-period.js +104 -0
- package/dist/_internal/shared/features/points/accepts.d.ts +1 -8
- package/dist/_internal/shared/features/points/accepts.js +12 -6
- package/dist/_internal/shared/features/pricing/rate-registry.d.ts +150 -0
- package/dist/_internal/shared/features/pricing/rate-registry.js +246 -0
- package/dist/_internal/shared/features/shipping/parcel.d.ts +123 -0
- package/dist/_internal/shared/features/shipping/parcel.js +139 -0
- package/dist/_internal/shared/features/site-settings/fees.d.ts +16 -8
- package/dist/_internal/shared/features/site-settings/fees.js +12 -8
- package/dist/_internal/shared/fees/explain.d.ts +81 -0
- package/dist/_internal/shared/fees/explain.js +101 -0
- package/dist/_internal/shared/history/index.d.ts +1 -1
- package/dist/_internal/shared/history/index.js +1 -1
- package/dist/_internal/shared/history/types.d.ts +7 -1
- package/dist/_internal/shared/history/types.js +25 -0
- package/dist/client.d.ts +11 -1
- package/dist/client.js +13 -0
- package/dist/constants/api-endpoints.d.ts +72 -0
- package/dist/constants/api-endpoints.js +41 -0
- package/dist/constants/field-names.d.ts +41 -0
- package/dist/constants/field-names.js +47 -0
- package/dist/features/account/components/UserOrdersView.js +28 -2
- package/dist/features/admin/components/AdminIntegrationsView.d.ts +55 -0
- package/dist/features/admin/components/AdminIntegrationsView.js +74 -0
- package/dist/features/admin/components/AdminOrderEditorView.d.ts +16 -1
- package/dist/features/admin/components/AdminOrderEditorView.js +72 -3
- package/dist/features/admin/components/AdminOrdersView.js +20 -1
- package/dist/features/admin/schemas/firestore.d.ts +32 -0
- package/dist/features/ads/schemas/booking-write.d.ts +157 -0
- package/dist/features/ads/schemas/booking-write.js +88 -0
- package/dist/features/ads/schemas/creative-form.d.ts +18 -0
- package/dist/features/ads/schemas/creative-form.js +51 -0
- package/dist/features/ads/schemas/firestore.d.ts +140 -0
- package/dist/features/ads/schemas/firestore.js +109 -0
- package/dist/features/auctions/repository/bid.repository.js +3 -1
- package/dist/features/audit-log/schemas/firestore.d.ts +110 -0
- package/dist/features/audit-log/schemas/firestore.js +74 -0
- package/dist/features/auth/actions/profile-actions.d.ts +69 -1
- package/dist/features/auth/actions/profile-actions.js +62 -1
- package/dist/features/auth/schemas/firestore.d.ts +16 -2
- package/dist/features/auth/schemas/firestore.js +2 -1
- package/dist/features/blog/actions/blog-actions.d.ts +6 -0
- package/dist/features/blog/actions/blog-actions.js +17 -2
- package/dist/features/blog/api/route.js +4 -1
- package/dist/features/blog/columns/index.js +5 -0
- package/dist/features/blog/components/BlogIndexPageView.js +2 -1
- package/dist/features/blog/repository/blog.repository.d.ts +4 -0
- package/dist/features/blog/repository/blog.repository.js +5 -0
- package/dist/features/blog/schemas/blog-form.d.ts +3 -0
- package/dist/features/blog/schemas/blog-form.js +1 -0
- package/dist/features/blog/schemas/firestore.d.ts +38 -1
- package/dist/features/blog/schemas/firestore.js +23 -0
- package/dist/features/blog/schemas/index.d.ts +6 -0
- package/dist/features/blog/schemas/index.js +2 -0
- package/dist/features/blog/types/index.d.ts +2 -0
- package/dist/features/cart/components/CartPriceBreakdown.d.ts +12 -1
- package/dist/features/cart/components/CartPriceBreakdown.js +24 -5
- package/dist/features/cart/repository/cart.repository.d.ts +14 -0
- package/dist/features/cart/repository/cart.repository.js +20 -0
- package/dist/features/cart/schemas/firestore.d.ts +24 -0
- package/dist/features/dashboard/components/DashboardHubView.d.ts +83 -0
- package/dist/features/dashboard/components/DashboardHubView.js +56 -0
- package/dist/features/dashboard/components/DashboardSectionsClient.d.ts +23 -0
- package/dist/features/dashboard/components/DashboardSectionsClient.js +66 -0
- package/dist/features/dispute-reasons/components/AdminDisputeReasonsView.d.ts +55 -0
- package/dist/features/dispute-reasons/components/AdminDisputeReasonsView.js +175 -0
- package/dist/features/dispute-reasons/repository/dispute-reasons.repository.d.ts +24 -0
- package/dist/features/dispute-reasons/repository/dispute-reasons.repository.js +28 -0
- package/dist/features/dispute-reasons/schemas/firestore.d.ts +3 -5
- package/dist/features/events/components/EventSaleBanner.js +1 -1
- package/dist/features/faq/components/FAQPageContent.js +2 -2
- package/dist/features/gateway-events/schemas/index.d.ts +2 -2
- package/dist/features/homepage/schemas/index.d.ts +8 -8
- package/dist/features/inventory/schemas/stock-reservation.d.ts +114 -0
- package/dist/features/inventory/schemas/stock-reservation.js +103 -0
- package/dist/features/layout/AppLayoutShell.d.ts +9 -1
- package/dist/features/layout/AppLayoutShell.js +12 -4
- package/dist/features/layout/BottomActions.js +2 -1
- package/dist/features/layout/BottomNavbar.d.ts +10 -2
- package/dist/features/layout/SideActionDock.js +52 -2
- package/dist/features/layout/TitleBarLayout.js +13 -4
- package/dist/features/layout/TitleBarLayout.style.css +59 -0
- package/dist/features/layout/useCtaReveal.d.ts +16 -1
- package/dist/features/layout/useCtaReveal.js +17 -26
- package/dist/features/ledger/repository/journal.repository.d.ts +110 -0
- package/dist/features/ledger/repository/journal.repository.js +312 -0
- package/dist/features/ledger/schemas/expenses.d.ts +87 -0
- package/dist/features/ledger/schemas/expenses.js +27 -0
- package/dist/features/ledger/schemas/firestore.d.ts +183 -0
- package/dist/features/ledger/schemas/firestore.js +69 -0
- package/dist/features/orders/components/BalancePaymentPanel.d.ts +12 -0
- package/dist/features/orders/components/BalancePaymentPanel.js +94 -0
- package/dist/features/orders/components/RaiseDisputeForm.js +19 -11
- package/dist/features/orders/repository/orders.repository.d.ts +28 -1
- package/dist/features/orders/repository/orders.repository.js +60 -6
- package/dist/features/orders/schemas/balance.d.ts +40 -0
- package/dist/features/orders/schemas/balance.js +47 -0
- package/dist/features/orders/schemas/firestore.d.ts +202 -0
- package/dist/features/orders/schemas/firestore.js +43 -0
- package/dist/features/orders/schemas/index.d.ts +2 -2
- package/dist/features/orders/types/index.d.ts +21 -0
- package/dist/features/payments/repository/payout.repository.js +3 -2
- package/dist/features/payments/schemas/firestore.d.ts +92 -1
- package/dist/features/payments/schemas/firestore.js +23 -0
- package/dist/features/pricing/components/AdminPricingView.d.ts +13 -0
- package/dist/features/pricing/components/AdminPricingView.js +157 -0
- package/dist/features/products/schemas/firestore.d.ts +26 -1
- package/dist/features/products/schemas/firestore.js +2 -0
- package/dist/features/products/schemas/index.d.ts +2 -2
- package/dist/features/reviews/repository/reviews.repository.d.ts +14 -0
- package/dist/features/reviews/repository/reviews.repository.js +16 -0
- package/dist/features/scams/repository/scammer.repository.js +2 -1
- package/dist/features/scams/schemas/firestore.d.ts +2 -1
- package/dist/features/scams/schemas/firestore.js +2 -1
- package/dist/features/seller/actions/offer-actions.js +56 -0
- package/dist/features/seller/actions/seller-actions.d.ts +1 -1
- package/dist/features/seller/actions/seller-actions.js +4 -0
- package/dist/features/seller/components/DispatchForm.d.ts +11 -0
- package/dist/features/seller/components/DispatchForm.js +190 -0
- package/dist/features/seller/components/SellerOrdersView.js +94 -2
- package/dist/features/seller/components/index.d.ts +1 -0
- package/dist/features/seller/components/index.js +1 -0
- package/dist/features/seller/repository/offer.repository.js +4 -3
- package/dist/features/seller/schemas/firestore.d.ts +23 -2
- package/dist/features/seller/schemas/firestore.js +3 -2
- package/dist/features/seller/schemas/index.d.ts +4 -4
- package/dist/features/seller/schemas/order-forms.d.ts +61 -4
- package/dist/features/seller/schemas/order-forms.js +41 -8
- package/dist/features/shipments/schemas/firestore.d.ts +25 -0
- package/dist/features/shipping-boxes/repository/shipping-boxes.repository.d.ts +39 -0
- package/dist/features/shipping-boxes/repository/shipping-boxes.repository.js +55 -0
- package/dist/features/shipping-boxes/schemas/firestore.d.ts +2 -4
- package/dist/features/stores/repository/store.repository.d.ts +18 -0
- package/dist/features/stores/repository/store.repository.js +27 -1
- package/dist/features/stores/schemas/firestore.d.ts +41 -0
- package/dist/features/stores/schemas/firestore.js +20 -0
- package/dist/features/stores/schemas/index.d.ts +6 -6
- package/dist/features/support/repository/support.repository.js +72 -6
- package/dist/features/support/schemas/firestore.d.ts +17 -0
- package/dist/features/support/schemas/index.d.ts +2 -2
- package/dist/index.d.ts +5 -0
- package/dist/index.js +19 -0
- package/dist/next/routing/route-map.d.ts +92 -0
- package/dist/next/routing/route-map.js +53 -0
- package/dist/react/contexts/SessionContext.d.ts +17 -1
- package/dist/schemas/registry.d.ts +22 -16
- package/dist/security/pii-schemas.d.ts +1 -1
- package/dist/security/pii-schemas.js +45 -0
- package/dist/server-entry.d.ts +1 -1
- package/dist/server-entry.js +10 -1
- package/dist/server.d.ts +29 -1
- package/dist/server.js +158 -0
- package/dist/styles.css +349 -1
- package/dist/tailwind-utilities.css +1 -1
- package/dist/ui/components/Button.d.ts +10 -1
- package/dist/ui/components/Button.js +25 -3
- package/dist/ui/components/Chart.d.ts +63 -0
- package/dist/ui/components/Chart.js +169 -0
- package/dist/ui/components/Chart.style.css +214 -0
- package/dist/ui/components/Disclaimer.js +10 -1
- package/dist/ui/components/OverflowRow.js +54 -2
- package/dist/ui/components/OverflowRow.style.css +38 -0
- package/dist/ui/components/RichTextEditor.js +99 -8
- package/dist/ui/components/chart-spec.d.ts +68 -0
- package/dist/ui/components/chart-spec.js +140 -0
- package/dist/ui/components/index.style.css +1 -0
- package/dist/ui/components/surface-tokens.d.ts +1 -1
- package/dist/ui/components/surface-tokens.js +9 -0
- package/dist/ui/components/toolbar-collapse.d.ts +13 -0
- package/dist/ui/components/toolbar-collapse.js +10 -1
- package/dist/ui/index.d.ts +6 -0
- package/dist/ui/index.js +3 -0
- package/dist/ui/rich-text/RichText.d.ts +10 -1
- package/dist/ui/rich-text/RichText.js +33 -2
- package/dist/ui/rich-text/RichText.style.css +35 -0
- package/dist/ui/rich-text/RichTextRenderer.d.ts +30 -1
- package/dist/ui/rich-text/RichTextRenderer.js +34 -2
- package/dist/ui/rich-text/chart-blocks.d.ts +62 -0
- package/dist/ui/rich-text/chart-blocks.js +87 -0
- package/package.json +1 -1
- package/scripts/seed-cli.mjs +3 -0
|
@@ -3,6 +3,14 @@ export interface RichTextRendererProps {
|
|
|
3
3
|
html?: string | null;
|
|
4
4
|
className?: string;
|
|
5
5
|
proseClass?: string;
|
|
6
|
+
/**
|
|
7
|
+
* Render `<figure data-chart>` placeholders as live charts. Default true.
|
|
8
|
+
*
|
|
9
|
+
* Pass `false` where a chart cannot work — an email body, a plain-text
|
|
10
|
+
* export, an OG image — so the placeholder is simply dropped rather than
|
|
11
|
+
* mounting a client component into a context that cannot hydrate it.
|
|
12
|
+
*/
|
|
13
|
+
charts?: boolean;
|
|
6
14
|
}
|
|
7
15
|
/**
|
|
8
16
|
* SSR-safe HTML renderer for admin/CMS-authored rich text content.
|
|
@@ -12,5 +20,26 @@ export interface RichTextRendererProps {
|
|
|
12
20
|
*
|
|
13
21
|
* For user-generated content or untrusted HTML, use <RichText> instead
|
|
14
22
|
* (client-only, runs the DOM-based sanitizer).
|
|
23
|
+
*
|
|
24
|
+
* ## 🛑 It is no longer a single `innerHTML` dump, and why that is safe
|
|
25
|
+
*
|
|
26
|
+
* Chart blocks are stored as `<figure data-chart='{json}'>` and have to become
|
|
27
|
+
* real components to be theme-aware, so the HTML is split and the chart
|
|
28
|
+
* segments are replaced with `<ChartFromJson>`. Two properties keep this from
|
|
29
|
+
* being a regression:
|
|
30
|
+
*
|
|
31
|
+
* - **The fast path is unchanged.** `splitChartBlocks` rejects on a substring
|
|
32
|
+
* test, so content with no chart returns one segment and renders through the
|
|
33
|
+
* same single `dangerouslySetInnerHTML` as before.
|
|
34
|
+
* - **Splitting cannot introduce markup.** Segments are slices of the original
|
|
35
|
+
* string, concatenated in document order; nothing is rewritten. A malformed
|
|
36
|
+
* chart figure fails the match and stays ordinary HTML.
|
|
37
|
+
*
|
|
38
|
+
* 🛑 The prose wrapper stays on the OUTER element, and each segment's own
|
|
39
|
+
* wrapper is `display: contents` (`.appkit-rich-text__seg`). A segment needs an
|
|
40
|
+
* element to carry `dangerouslySetInnerHTML`, but leaving that element in the
|
|
41
|
+
* box tree restarts `prose`'s adjacency and first/last-child margin rules at
|
|
42
|
+
* every chart — so paragraphs either side of a chart would space differently
|
|
43
|
+
* from paragraphs anywhere else on the page.
|
|
15
44
|
*/
|
|
16
|
-
export declare function RichTextRenderer({ html, className, proseClass, }: RichTextRendererProps): React.JSX.Element | null;
|
|
45
|
+
export declare function RichTextRenderer({ html, className, proseClass, charts, }: RichTextRendererProps): React.JSX.Element | null;
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { splitChartBlocks } from "./chart-blocks.js";
|
|
3
|
+
import { ChartFromJson } from "../components/Chart.js";
|
|
2
4
|
/**
|
|
3
5
|
* SSR-safe HTML renderer for admin/CMS-authored rich text content.
|
|
4
6
|
*
|
|
@@ -7,9 +9,39 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
|
7
9
|
*
|
|
8
10
|
* For user-generated content or untrusted HTML, use <RichText> instead
|
|
9
11
|
* (client-only, runs the DOM-based sanitizer).
|
|
12
|
+
*
|
|
13
|
+
* ## 🛑 It is no longer a single `innerHTML` dump, and why that is safe
|
|
14
|
+
*
|
|
15
|
+
* Chart blocks are stored as `<figure data-chart='{json}'>` and have to become
|
|
16
|
+
* real components to be theme-aware, so the HTML is split and the chart
|
|
17
|
+
* segments are replaced with `<ChartFromJson>`. Two properties keep this from
|
|
18
|
+
* being a regression:
|
|
19
|
+
*
|
|
20
|
+
* - **The fast path is unchanged.** `splitChartBlocks` rejects on a substring
|
|
21
|
+
* test, so content with no chart returns one segment and renders through the
|
|
22
|
+
* same single `dangerouslySetInnerHTML` as before.
|
|
23
|
+
* - **Splitting cannot introduce markup.** Segments are slices of the original
|
|
24
|
+
* string, concatenated in document order; nothing is rewritten. A malformed
|
|
25
|
+
* chart figure fails the match and stays ordinary HTML.
|
|
26
|
+
*
|
|
27
|
+
* 🛑 The prose wrapper stays on the OUTER element, and each segment's own
|
|
28
|
+
* wrapper is `display: contents` (`.appkit-rich-text__seg`). A segment needs an
|
|
29
|
+
* element to carry `dangerouslySetInnerHTML`, but leaving that element in the
|
|
30
|
+
* box tree restarts `prose`'s adjacency and first/last-child margin rules at
|
|
31
|
+
* every chart — so paragraphs either side of a chart would space differently
|
|
32
|
+
* from paragraphs anywhere else on the page.
|
|
10
33
|
*/
|
|
11
|
-
export function RichTextRenderer({ html, className = "", proseClass = "prose max-w-none dark:prose-invert", }) {
|
|
34
|
+
export function RichTextRenderer({ html, className = "", proseClass = "prose max-w-none dark:prose-invert", charts = true, }) {
|
|
12
35
|
if (!html)
|
|
13
36
|
return null;
|
|
14
|
-
|
|
37
|
+
const wrapperClass = `appkit-rich-text ${proseClass} ${className}`.trim();
|
|
38
|
+
const segments = charts ? splitChartBlocks(html) : [{ type: "html", html }];
|
|
39
|
+
// Single HTML segment — the overwhelmingly common case. Identical to the
|
|
40
|
+
// pre-chart behaviour, down to the element shape.
|
|
41
|
+
if (segments.length === 1 && segments[0].type === "html") {
|
|
42
|
+
return (_jsx("div", { className: wrapperClass, dangerouslySetInnerHTML: { __html: segments[0].html } }));
|
|
43
|
+
}
|
|
44
|
+
return (_jsx("div", { className: wrapperClass, children: segments.map((seg, i) => seg.type === "html" ? (_jsx("div", { className: "appkit-rich-text__seg", dangerouslySetInnerHTML: { __html: seg.html } }, `h${i}`)) : (
|
|
45
|
+
// eslint-disable-next-line react/no-array-index-key
|
|
46
|
+
_jsx(ChartFromJson, { json: seg.json }, `c${i}`))) }));
|
|
15
47
|
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Splitting rich-text HTML around `<figure data-chart>` placeholders.
|
|
3
|
+
*
|
|
4
|
+
* ## 🛑 Why this is regex and not a DOM parse
|
|
5
|
+
*
|
|
6
|
+
* `RichTextRenderer` is a React Server Component — no `DOMParser`, no
|
|
7
|
+
* `document`. So the split has to work on the string, and it is only safe to do
|
|
8
|
+
* that because the shape being matched is one we WRITE: a childless
|
|
9
|
+
* `<figure data-chart='…'></figure>` emitted by the chart toolbar button.
|
|
10
|
+
*
|
|
11
|
+
* This is deliberately not a general HTML parser and must not grow into one. It
|
|
12
|
+
* matches exactly one element shape and hands everything else through
|
|
13
|
+
* untouched, so a malformed chart figure degrades to "rendered as ordinary
|
|
14
|
+
* HTML" rather than corrupting the document around it.
|
|
15
|
+
*
|
|
16
|
+
* ## 🛑 Why the JSON needs entity decoding
|
|
17
|
+
*
|
|
18
|
+
* A `ChartSpec` is full of `"` characters, so the attribute is written
|
|
19
|
+
* single-quoted. But anything that round-trips the HTML through a DOM — the
|
|
20
|
+
* client sanitiser's `DOMParser`, a contenteditable surface, an admin preview —
|
|
21
|
+
* re-serialises it double-quoted with the inner quotes as `"`. Both
|
|
22
|
+
* spellings therefore occur in stored content, and a renderer that handles only
|
|
23
|
+
* the one it writes will fail on its own saved output.
|
|
24
|
+
*
|
|
25
|
+
* Pure. No React, no DOM, safe on the server.
|
|
26
|
+
*/
|
|
27
|
+
import type { ChartSpec } from "../components/chart-spec";
|
|
28
|
+
/** A run of ordinary HTML, or a chart placeholder's raw JSON payload. */
|
|
29
|
+
export type RichTextSegment = {
|
|
30
|
+
type: "html";
|
|
31
|
+
html: string;
|
|
32
|
+
} | {
|
|
33
|
+
type: "chart";
|
|
34
|
+
json: string;
|
|
35
|
+
};
|
|
36
|
+
/**
|
|
37
|
+
* Decode the entity subset an HTML serialiser can introduce inside an
|
|
38
|
+
* attribute value.
|
|
39
|
+
*
|
|
40
|
+
* 🛑 `&` is decoded LAST. Decoding it first turns a legitimately encoded
|
|
41
|
+
* `&quot;` into `"` and then into `"`, which injects a quote the
|
|
42
|
+
* author never wrote and breaks the JSON parse — the classic double-decode bug.
|
|
43
|
+
*/
|
|
44
|
+
export declare function decodeAttrEntities(s: string): string;
|
|
45
|
+
/**
|
|
46
|
+
* Split HTML into alternating prose and chart segments, in document order.
|
|
47
|
+
*
|
|
48
|
+
* Returns a single `html` segment when there are no charts, so the common case
|
|
49
|
+
* costs one regex test and the caller's fast path stays a plain innerHTML
|
|
50
|
+
* render.
|
|
51
|
+
*/
|
|
52
|
+
export declare function splitChartBlocks(html: string): RichTextSegment[];
|
|
53
|
+
/** True when the content carries at least one chart placeholder. Stateless. */
|
|
54
|
+
export declare function hasChartBlock(html: string | null | undefined): boolean;
|
|
55
|
+
/**
|
|
56
|
+
* Build the placeholder a toolbar or a seed fixture should emit.
|
|
57
|
+
*
|
|
58
|
+
* Single-quoted, with any single quote in the payload escaped as `'` so the
|
|
59
|
+
* attribute cannot be terminated early by a label containing an apostrophe —
|
|
60
|
+
* "Blader's choice" is an entirely ordinary series label.
|
|
61
|
+
*/
|
|
62
|
+
export declare function chartFigureHtml(spec: ChartSpec): string;
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Matches a childless `<figure>` carrying `data-chart`, single- or
|
|
3
|
+
* double-quoted. `[\s\S]*?` rather than `.*?` because stored content is
|
|
4
|
+
* frequently pretty-printed across lines.
|
|
5
|
+
*/
|
|
6
|
+
const CHART_FIGURE_RE = /<figure\b[^>]*\bdata-chart\s*=\s*(?:'([^']*)'|"([^"]*)")[^>]*>[\s\S]*?<\/figure\s*>/gi;
|
|
7
|
+
/**
|
|
8
|
+
* 🛑 A SECOND, non-global copy, purely for `hasChartBlock`.
|
|
9
|
+
*
|
|
10
|
+
* `RegExp.prototype.test` on a `/g` regex ADVANCES `lastIndex`, so calling it
|
|
11
|
+
* twice on the same string returns `true` then `false`. Measured on the first
|
|
12
|
+
* draft of this file: three consecutive calls gave `true false true`. Sharing
|
|
13
|
+
* one `/g` literal between `exec` in a loop and `test` as a predicate is the
|
|
14
|
+
* bug — a predicate must be stateless, so it gets its own non-global regex
|
|
15
|
+
* rather than relying on every caller to reset `lastIndex` first.
|
|
16
|
+
*
|
|
17
|
+
* Derived from `.source` so the pattern has exactly one definition. It is also
|
|
18
|
+
* written as a LITERAL above rather than built from a string: a string-built
|
|
19
|
+
* pattern needs every backslash doubled, which is silently destroyed by any
|
|
20
|
+
* tool that re-escapes the file on the way in — a draft of this module lost
|
|
21
|
+
* `\s` to `s` that way and matched nothing at all while looking correct.
|
|
22
|
+
*/
|
|
23
|
+
const CHART_FIGURE_TEST_RE = new RegExp(CHART_FIGURE_RE.source, "i");
|
|
24
|
+
/**
|
|
25
|
+
* Decode the entity subset an HTML serialiser can introduce inside an
|
|
26
|
+
* attribute value.
|
|
27
|
+
*
|
|
28
|
+
* 🛑 `&` is decoded LAST. Decoding it first turns a legitimately encoded
|
|
29
|
+
* `&quot;` into `"` and then into `"`, which injects a quote the
|
|
30
|
+
* author never wrote and breaks the JSON parse — the classic double-decode bug.
|
|
31
|
+
*/
|
|
32
|
+
export function decodeAttrEntities(s) {
|
|
33
|
+
return s
|
|
34
|
+
.replace(/"/g, '"')
|
|
35
|
+
.replace(/�*39;/g, "'")
|
|
36
|
+
.replace(/'/g, "'")
|
|
37
|
+
.replace(/</g, "<")
|
|
38
|
+
.replace(/>/g, ">")
|
|
39
|
+
.replace(/&/g, "&");
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Split HTML into alternating prose and chart segments, in document order.
|
|
43
|
+
*
|
|
44
|
+
* Returns a single `html` segment when there are no charts, so the common case
|
|
45
|
+
* costs one regex test and the caller's fast path stays a plain innerHTML
|
|
46
|
+
* render.
|
|
47
|
+
*/
|
|
48
|
+
export function splitChartBlocks(html) {
|
|
49
|
+
if (!html)
|
|
50
|
+
return [];
|
|
51
|
+
// Cheap reject before the real scan — most content has no chart at all.
|
|
52
|
+
if (!html.includes("data-chart"))
|
|
53
|
+
return [{ type: "html", html }];
|
|
54
|
+
const segments = [];
|
|
55
|
+
let cursor = 0;
|
|
56
|
+
// `exec` in a loop needs a fresh lastIndex; the literal is module-scoped and
|
|
57
|
+
// /g, so reset rather than relying on a previous call having run to the end.
|
|
58
|
+
CHART_FIGURE_RE.lastIndex = 0;
|
|
59
|
+
let m;
|
|
60
|
+
while ((m = CHART_FIGURE_RE.exec(html)) !== null) {
|
|
61
|
+
if (m.index > cursor) {
|
|
62
|
+
segments.push({ type: "html", html: html.slice(cursor, m.index) });
|
|
63
|
+
}
|
|
64
|
+
const raw = m[1] ?? m[2] ?? "";
|
|
65
|
+
segments.push({ type: "chart", json: decodeAttrEntities(raw) });
|
|
66
|
+
cursor = m.index + m[0].length;
|
|
67
|
+
}
|
|
68
|
+
if (cursor < html.length) {
|
|
69
|
+
segments.push({ type: "html", html: html.slice(cursor) });
|
|
70
|
+
}
|
|
71
|
+
return segments;
|
|
72
|
+
}
|
|
73
|
+
/** True when the content carries at least one chart placeholder. Stateless. */
|
|
74
|
+
export function hasChartBlock(html) {
|
|
75
|
+
return !!html && CHART_FIGURE_TEST_RE.test(html);
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Build the placeholder a toolbar or a seed fixture should emit.
|
|
79
|
+
*
|
|
80
|
+
* Single-quoted, with any single quote in the payload escaped as `'` so the
|
|
81
|
+
* attribute cannot be terminated early by a label containing an apostrophe —
|
|
82
|
+
* "Blader's choice" is an entirely ordinary series label.
|
|
83
|
+
*/
|
|
84
|
+
export function chartFigureHtml(spec) {
|
|
85
|
+
const json = JSON.stringify(spec).replace(/'/g, "'");
|
|
86
|
+
return `<figure data-chart='${json}'></figure>`;
|
|
87
|
+
}
|
package/package.json
CHANGED
package/scripts/seed-cli.mjs
CHANGED
|
@@ -274,6 +274,7 @@ const {
|
|
|
274
274
|
wishlistsSeedData, historySeedData,
|
|
275
275
|
groupedListingsSeedData,
|
|
276
276
|
mediaAssetsSeedData, mediaAssetsEditorialSeedData,
|
|
277
|
+
chartOfAccountsSeedData,
|
|
277
278
|
scammersSeedData, productFeaturesSeedData, taxCodesSeedData,
|
|
278
279
|
disputeReasonsSeedData,
|
|
279
280
|
authenticityKnowledgeSeedData,
|
|
@@ -387,6 +388,7 @@ const COLLECTION_MAP = {
|
|
|
387
388
|
* precisely so a Firestore wipe cannot orphan Storage.
|
|
388
389
|
*/
|
|
389
390
|
mediaAssets: "mediaAssets",
|
|
391
|
+
chartOfAccounts: "chartOfAccounts",
|
|
390
392
|
scammerProfiles: SCAMMER_COLLECTION,
|
|
391
393
|
productFeatures: PRODUCT_FEATURES_COLLECTION,
|
|
392
394
|
authenticityKnowledge: "authenticityKnowledge",
|
|
@@ -769,6 +771,7 @@ const SEED_DATA_MAP = {
|
|
|
769
771
|
// rewritten wholesale by upload-taxonomy-images.mjs, so the editorial rows
|
|
770
772
|
// are kept beside them rather than inside that file.
|
|
771
773
|
mediaAssets: [...mediaAssetsSeedData, ...mediaAssetsEditorialSeedData],
|
|
774
|
+
chartOfAccounts: chartOfAccountsSeedData,
|
|
772
775
|
scammerProfiles: scammersSeedData,
|
|
773
776
|
productFeatures: productFeaturesSeedData,
|
|
774
777
|
authenticityKnowledge: authenticityKnowledgeSeedData,
|