docs: add line highlight validation (#14380)
* docs: add line highlight validation * add to all projects * fixes * fixes * fix * fixes
This commit is contained in:
@@ -5,6 +5,7 @@ import rehypeSlug from "rehype-slug"
|
||||
import {
|
||||
brokenLinkCheckerPlugin,
|
||||
crossProjectLinksPlugin,
|
||||
validateHighlightsPlugin,
|
||||
} from "remark-rehype-plugins"
|
||||
import path from "path"
|
||||
import { catchBadRedirects } from "build-scripts"
|
||||
@@ -93,6 +94,7 @@ const withMDX = createMDX({
|
||||
tagName: "code",
|
||||
},
|
||||
],
|
||||
[validateHighlightsPlugin, { verbose: false }],
|
||||
[rehypeSlug],
|
||||
],
|
||||
development: process.env.NODE_ENV === "development",
|
||||
|
||||
@@ -197,10 +197,10 @@ So, to add the UI route at the `localhost:9000/app/brands` path, create the file
|
||||

|
||||
|
||||
export const uiRouteHighlights = [
|
||||
["8", "BrandsPage", "The UI route that displays a new page."],
|
||||
["23", "defineRouteConfig", "Export config to add a link for the UI route in the sidebar."],
|
||||
["24", "label", "The sidebar item's label."],
|
||||
["25", "icon", "The sidebar item's icon."]
|
||||
["10", "BrandsPage", "The UI route that displays a new page."],
|
||||
["20", "defineRouteConfig", "Export config to add a link for the UI route in the sidebar."],
|
||||
["21", "label", "The sidebar item's label."],
|
||||
["22", "icon", "The sidebar item's icon."]
|
||||
]
|
||||
|
||||
```tsx title="src/admin/routes/brands/page.tsx" highlights={uiRouteHighlights}
|
||||
|
||||
@@ -56,7 +56,7 @@ Learn how to create a middleware in the [Middlewares](../middlewares/page.mdx) c
|
||||
</Note>
|
||||
|
||||
export const highlights = [
|
||||
["10", "req.allowed", "Modify the allowed fields and relations to be retrieved"],
|
||||
["9", "req.allowed", "Modify the allowed fields and relations to be retrieved"],
|
||||
]
|
||||
|
||||
```ts title="src/api/middlewares.ts" highlights={highlights}
|
||||
|
||||
@@ -49,8 +49,8 @@ When you create a record of a data model that has one of another, pass the ID of
|
||||
For example, assuming you have the [User and Email data models from the previous chapter](../relationships/page.mdx#one-to-one-relationship), set a user's email ID as follows:
|
||||
|
||||
export const hasOneHighlights = [
|
||||
["4", "email_id", "The ID of the email that the user has."],
|
||||
["11", "email_id", "The ID of the email that the user has."]
|
||||
["4", "email", "The ID of the email that the user has."],
|
||||
["11", "email", "The ID of the email that the user has."]
|
||||
]
|
||||
|
||||
```ts highlights={hasOneHighlights}
|
||||
|
||||
@@ -576,7 +576,7 @@ You can also create a `listAndCount` method to retrieve the posts with paginatio
|
||||
Now, you can use Query to retrieve a product and its linked post from the CMS:
|
||||
|
||||
export const queryHighlights = [
|
||||
["3", `"cms_post"`, "The `alias` of the virtual data model in the link configuration."]
|
||||
["3", `"cms_post.*"`, "The `alias` of the virtual data model in the link configuration."]
|
||||
]
|
||||
|
||||
```ts highlights={queryHighlights}
|
||||
|
||||
@@ -81,7 +81,7 @@ You define a service in a `service.ts` or `service.js` file at the root of your
|
||||
|
||||
export const highlights = [
|
||||
["4", "MedusaService", "The service factory function."],
|
||||
["5", "MyCustom", "The data models to generate data-management methods for."]
|
||||
["5", "Post", "The data models to generate data-management methods for."]
|
||||
]
|
||||
|
||||
```ts title="src/modules/blog/service.ts" highlights={highlights}
|
||||
|
||||
@@ -9,6 +9,7 @@ import {
|
||||
crossProjectLinksPlugin,
|
||||
recmaInjectMdxDataPlugin,
|
||||
remarkAttachFrontmatterDataPlugin,
|
||||
validateHighlightsPlugin,
|
||||
} from "remark-rehype-plugins"
|
||||
import path from "path"
|
||||
import redirects from "./utils/redirects.mjs"
|
||||
@@ -78,6 +79,7 @@ const withMDX = mdx({
|
||||
tagName: "code",
|
||||
},
|
||||
],
|
||||
[validateHighlightsPlugin, { verbose: false }],
|
||||
[rehypeSlug],
|
||||
[
|
||||
cloudinaryImgRehypePlugin,
|
||||
|
||||
@@ -13,6 +13,7 @@ import {
|
||||
prerequisitesLinkFixerPlugin,
|
||||
remarkAttachFrontmatterDataPlugin,
|
||||
recmaInjectMdxDataPlugin,
|
||||
validateHighlightsPlugin,
|
||||
} from "remark-rehype-plugins"
|
||||
import bundleAnalyzer from "@next/bundle-analyzer"
|
||||
import withExtractedTableOfContents from "@stefanprobst/rehype-extract-toc"
|
||||
@@ -79,6 +80,7 @@ const withMDX = mdx({
|
||||
tagName: "code",
|
||||
},
|
||||
],
|
||||
[validateHighlightsPlugin, { verbose: false }],
|
||||
[rehypeSlug],
|
||||
[
|
||||
cloudinaryImgRehypePlugin,
|
||||
|
||||
@@ -229,7 +229,7 @@ Using [workflows](!docs!/learn/fundamentals/workflows), you can implement this b
|
||||
|
||||
export const bundledHighlights1 = [
|
||||
["11", "products", "Create the products part of the bundle."],
|
||||
["28", "manage_inventory", "Enabling this without specifying inventory items creates a default inventory item."]
|
||||
["29", "manage_inventory", "Enabling this without specifying inventory items creates a default inventory item."]
|
||||
]
|
||||
|
||||
```ts highlights={bundledHighlights1}
|
||||
@@ -390,7 +390,7 @@ Finally, create the bundled product:
|
||||
|
||||
export const bundledProductHighlights3 = [
|
||||
["5", "bundledProduct", "Create the bundled product."],
|
||||
["22", "inventory_items", "Pass the inventory items of the products part of the bundle."]
|
||||
["23", "inventory_items", "Pass the inventory items of the products part of the bundle."]
|
||||
]
|
||||
|
||||
```ts highlights={bundledProductHighlights3}
|
||||
|
||||
@@ -2884,9 +2884,9 @@ Create the file `src/workflows/merchant-send-quote.ts` with the following conten
|
||||

|
||||
|
||||
export const sendQuoteHighlights = [
|
||||
["15", "useQueryGraphStep", "Retrieve the quote's details."],
|
||||
["24", "validateQuoteNotAccepted", "Validate that the quote isn't already accepted by the customer."],
|
||||
["29", "updateQuotesStep", "Update the quote's status to `pending_customer`."]
|
||||
["14", "useQueryGraphStep", "Retrieve the quote's details."],
|
||||
["23", "validateQuoteNotAccepted", "Validate that the quote isn't already accepted by the customer."],
|
||||
["28", "updateQuotesStep", "Update the quote's status to `pending_customer`."]
|
||||
]
|
||||
|
||||
```ts title="src/workflows/merchant-send-quote.ts" highlights={sendQuoteHighlights}
|
||||
|
||||
@@ -1415,8 +1415,8 @@ To create the workflow, create the file `src/workflows/apply-loyalty-on-cart.ts`
|
||||
export const applyLoyaltyOnCartWorkflowHighlights = [
|
||||
["46", "useQueryGraphStep", "Retrieve the cart's details."],
|
||||
["57", "validateCustomerExistsStep", "Validate that the customer is registered."],
|
||||
["59", "getCartLoyaltyPromoStep", "Retrieve the cart's loyalty promotion."],
|
||||
["61", "acquireLockStep", "Acquire a lock on the cart to prevent concurrent modifications."],
|
||||
["61", "getCartLoyaltyPromoStep", "Retrieve the cart's loyalty promotion."],
|
||||
["66", "acquireLockStep", "Acquire a lock on the cart to prevent concurrent modifications."],
|
||||
["72", "getCartLoyaltyPromoAmountStep", "Get the amount to be discounted based on the loyalty points."],
|
||||
]
|
||||
|
||||
|
||||
@@ -917,11 +917,11 @@ A Notification Module Provider has a service that contains the sending logic. Th
|
||||
So, create the file `src/modules/twilio-sms/service.ts` with the following content:
|
||||
|
||||
export const twilioSmsServiceHighlights = [
|
||||
["8", "accountSid", "Twilio account SID."],
|
||||
["9", "authToken", "Twilio auth token."],
|
||||
["10", "from", "Twilio phone number to send the SMS from."],
|
||||
["14", "identifier", "Unique identifier for the module."],
|
||||
["15", "client", "Twilio client to send the SMS."],
|
||||
["9", "accountSid", "Twilio account SID."],
|
||||
["10", "authToken", "Twilio auth token."],
|
||||
["11", "from", "Twilio phone number to send the SMS from."],
|
||||
["15", "identifier", "Unique identifier for the module."],
|
||||
["16", "client", "Twilio client to send the SMS."],
|
||||
]
|
||||
|
||||
```ts title="src/modules/twilio-sms/service.ts" highlights={twilioSmsServiceHighlights}
|
||||
|
||||
@@ -538,12 +538,12 @@ If you get a type error on resolving the Preorder Module, run the Medusa applica
|
||||
</Note>
|
||||
|
||||
export const updatePreorderVariantStepHighlights = [
|
||||
["16", "preorderModuleService", "Resolve the Preorder Module's service from the Medusa container."],
|
||||
["20", "oldData", "Retrieve existing record to undo updates if an error occurs."],
|
||||
["24", "preorderVariant", "Update the pre-order variant."],
|
||||
["28", "preorderVariant", "Return the updated pre-order variant."],
|
||||
["28", "oldData", "Pass the old data to the compensation function."],
|
||||
["39", "updatePreorderVariants", "Undo updates if an error occurs during the workflow execution."]
|
||||
["17", "preorderModuleService", "Resolve the Preorder Module's service from the Medusa container."],
|
||||
["21", "oldData", "Retrieve existing record to undo updates if an error occurs."],
|
||||
["25", "preorderVariant", "Update the pre-order variant."],
|
||||
["29", "preorderVariant", "Return the updated pre-order variant."],
|
||||
["29", "oldData", "Pass the old data to the compensation function."],
|
||||
["40", "updatePreorderVariants", "Undo updates if an error occurs during the workflow execution."]
|
||||
]
|
||||
|
||||
```ts title="src/workflows/steps/update-preorder-variant.ts" highlights={updatePreorderVariantStepHighlights}
|
||||
@@ -623,10 +623,10 @@ The `createPreorderVariantStep` creates a pre-order variant record.
|
||||
To create the step, create the file `src/workflows/steps/create-preorder-variant.ts` with the following content:
|
||||
|
||||
export const createPreorderVariantStepHighlights = [
|
||||
["15", "preorderVariant", "Create the pre-order variant."],
|
||||
["19", "preorderVariant", "Return the created pre-order variant."],
|
||||
["19", "id", "Pass the ID to the compensation function."],
|
||||
["30", "deletePreorderVariants", "Delete the pre-order variant if an error occurs during the workflow execution."]
|
||||
["16", "preorderVariant", "Create the pre-order variant."],
|
||||
["20", "preorderVariant", "Return the created pre-order variant."],
|
||||
["20", "id", "Pass the ID to the compensation function."],
|
||||
["31", "deletePreorderVariants", "Delete the pre-order variant if an error occurs during the workflow execution."]
|
||||
]
|
||||
|
||||
```ts title="src/workflows/steps/create-preorder-variant.ts" highlights={createPreorderVariantStepHighlights}
|
||||
@@ -811,7 +811,7 @@ export const upsertPreorderVariantRouteHighlights = [
|
||||
["10", "UpsertPreorderVariantSchema", "The schema to validate the request body."],
|
||||
["18", "POST", "Expose a POST API route."],
|
||||
["24", "upsertProductVariantPreorderWorkflow", "Execute the workflow to create or update pre-order variant configurations."],
|
||||
["32", "preorder_variant", "Return the created or updated pre-order variant in the response."],
|
||||
["33", "preorder_variant", "Return the created or updated pre-order variant in the response."],
|
||||
]
|
||||
|
||||
```ts title="src/api/admin/variants/[id]/preorders/route.ts" highlights={upsertPreorderVariantRouteHighlights}
|
||||
@@ -944,12 +944,12 @@ The `disablePreorderVariantStep` changes the status of a pre-order variant recor
|
||||
Create the file `src/workflows/steps/disable-preorder-variant.ts` with the following content:
|
||||
|
||||
export const disablePreorderVariantStepHighlights = [
|
||||
["15", "oldData", "Retrieve existing record to undo updates if an error occurs."],
|
||||
["17", "preorderVariant", "Update the pre-order variant."],
|
||||
["19", "DISABLED", "Set the pre-order variant's status to `disabled`."],
|
||||
["22", "preorderVariant", "Return the updated pre-order variant."],
|
||||
["22", "oldData", "Pass the old data to the compensation function."],
|
||||
["31", "updatePreorderVariants", "Undo updates if an error occurs during the workflow execution."]
|
||||
["16", "oldData", "Retrieve existing record to undo updates if an error occurs."],
|
||||
["18", "preorderVariant", "Update the pre-order variant."],
|
||||
["20", "DISABLED", "Set the pre-order variant's status to `disabled`."],
|
||||
["23", "preorderVariant", "Return the updated pre-order variant."],
|
||||
["23", "oldData", "Pass the old data to the compensation function."],
|
||||
["32", "updatePreorderVariants", "Undo updates if an error occurs during the workflow execution."]
|
||||
]
|
||||
|
||||
```ts title="src/workflows/steps/disable-preorder-variant.ts" highlights={disablePreorderVariantStepHighlights}
|
||||
@@ -1688,9 +1688,9 @@ The `createPreordersStep` creates a `Preorder` record for each pre-order variant
|
||||
Create the file `src/workflows/steps/create-preorders.ts` with the following content:
|
||||
|
||||
export const createPreordersStepHighlights = [
|
||||
["16", "preorders", "Create pre-orders."],
|
||||
["23", "preorders", "Return the pre-orders."],
|
||||
["32", "deletePreorders", "Delete pre-orders if an error occurs during the workflow execution."],
|
||||
["17", "preorders", "Create pre-orders."],
|
||||
["24", "preorders", "Return the pre-orders."],
|
||||
["33", "deletePreorders", "Delete pre-orders if an error occurs during the workflow execution."],
|
||||
]
|
||||
|
||||
```ts title="src/workflows/steps/create-preorders.ts" highlights={createPreordersStepHighlights}
|
||||
@@ -1927,7 +1927,7 @@ export const validateCartHookHighlights = [
|
||||
["32", "variantsToAdd", "Retrieve the pre-order variants of the new items being added to the cart."],
|
||||
["42", "cartHasPreorderVariants", "Check if the cart has pre-order variants."],
|
||||
["48", "newItemsHavePreorderVariants", "Check if the new items being added have pre-order variants."],
|
||||
["55", "throw MedusaError", "Throw an error if the cart has mixed pre-order and available items."],
|
||||
["55", "MedusaError", "Throw an error if the cart has mixed pre-order and available items."],
|
||||
]
|
||||
|
||||
```ts title="src/workflows/hooks/validate-cart.ts" highlights={validateCartHookHighlights}
|
||||
@@ -2759,12 +2759,12 @@ The `updatePreordersStep` updates the details of pre-order records.
|
||||
Create the file `src/workflows/steps/update-preorders.ts` with the following content:
|
||||
|
||||
export const updatePreordersHighlights = [
|
||||
["13", "preorders", "The pre-orders to update."],
|
||||
["16", "oldPreorders", "The pre-orders before the update."],
|
||||
["20", "updatedPreorders", "Update the pre-orders."],
|
||||
["24", "updatedPreorders", "Return the updated pre-orders."],
|
||||
["24", "oldPreorders", "Pass the old pre-orders to the compensation function."],
|
||||
["33", "updatePreorders", "Revert the pre-order updates if an error occurs during the workflow's execution."]
|
||||
["14", "preorders", "The pre-orders to update."],
|
||||
["17", "oldPreorders", "The pre-orders before the update."],
|
||||
["21", "updatedPreorders", "Update the pre-orders."],
|
||||
["25", "updatedPreorders", "Return the updated pre-orders."],
|
||||
["25", "oldPreorders", "Pass the old pre-orders to the compensation function."],
|
||||
["34", "updatePreorders", "Revert the pre-order updates if an error occurs during the workflow's execution."]
|
||||
]
|
||||
|
||||
```ts title="src/workflows/steps/update-preorders.ts" highlights={updatePreordersHighlights}
|
||||
@@ -2964,14 +2964,7 @@ export const retrieveItemsToFulfillStep = createStep(
|
||||
|
||||
Then, update the workflow to the following:
|
||||
|
||||
export const fulfillPreorderWorkflowHighlights2 = [
|
||||
["22"], ["23"], ["24"], ["25"], ["37"], ["55"], ["56"], ["57"], ["58"],
|
||||
["59"], ["60"], ["61"], ["62"], ["63"], ["64"], ["65"], ["66"], ["67"],
|
||||
["68"], ["69"], ["70"], ["71"], ["72"], ["73"], ["74"], ["75"], ["76"],
|
||||
["77"], ["78"], ["79"], ["80"],
|
||||
]
|
||||
|
||||
```ts title="src/workflows/fulfill-preorder.ts" highlights={fulfillPreorderWorkflowHighlights2}
|
||||
```ts title="src/workflows/fulfill-preorder.ts"
|
||||
import { InferTypeOf } from "@medusajs/framework/types"
|
||||
import { PreorderVariant } from "../modules/preorder/models/preorder-variant"
|
||||
import { createWorkflow, transform, when, WorkflowResponse } from "@medusajs/framework/workflows-sdk"
|
||||
@@ -3135,7 +3128,7 @@ export const fulfillPreordersJobHighlights2 = [
|
||||
["24", "available_date", "Retrieve only the pre-order variants available today."],
|
||||
["43", "unfulfilledPreorders", "The unfulfilled pre-orders retrieved."],
|
||||
["44", "preorderMetadata", "The pagination details of the pre-order query."],
|
||||
["66", "fulfillPreorderWorkflow.run", "Fulfill a pre-order of the variant."],
|
||||
["66", "fulfillPreorderWorkflow", "Fulfill a pre-order of the variant."],
|
||||
]
|
||||
|
||||
```ts title="src/jobs/fulfill-preorders.ts" highlights={fulfillPreordersJobHighlights2}
|
||||
@@ -3498,7 +3491,7 @@ export const orderCanceledHighlights = [
|
||||
["14", "workflowInput", "Prepare the input to pass to the workflow."],
|
||||
["24", "preorders", "Retrieve the pre-orders of the order."],
|
||||
["41", "push", "Add the pre-orders to the workflow input."],
|
||||
["46", "cancelPreordersWorkflow.run", "Execute the cancel pre-orders workflow."],
|
||||
["46", "cancelPreordersWorkflow", "Execute the cancel pre-orders workflow."],
|
||||
]
|
||||
|
||||
```ts title="src/subscribers/order-canceled.ts" highlights={orderCanceledHighlights}
|
||||
@@ -3642,10 +3635,7 @@ Create the file `src/workflows/steps/retrieve-preorder-updates.ts` with the foll
|
||||
export const retrievePreorderUpdatesStepHighlights = [
|
||||
["20", "preordersToCancel", "The pre-orders to cancel."],
|
||||
["24", "preordersToCreate", "The pre-orders to create."],
|
||||
["20", "preorder_variant", "The pre-order variant associated with the item."],
|
||||
["32", "", "Find the new pre-order items."],
|
||||
["44", "push", "Add the pre-order variant to the pre-orders to create."],
|
||||
["50", "", "Find the pre-order items that need to be canceled."],
|
||||
["55", "push", "Add the pre-order to the pre-orders to cancel."],
|
||||
]
|
||||
|
||||
|
||||
@@ -5540,8 +5540,6 @@ You also need to update the components that use the `Item` component to pass the
|
||||
In `src/modules/cart/templates/items.tsx`, replace the `return` statement with the following:
|
||||
|
||||
export const itemsTemplateHighlights = [
|
||||
["13", "className"],
|
||||
["17", "className"],
|
||||
["34", "cartItems", "Pass new prop"]
|
||||
]
|
||||
|
||||
@@ -5669,12 +5667,7 @@ You calculate the total items by summing the quantities of the `filteredItems`,
|
||||
|
||||
Finally, in the `return` statement, replace all usages of `cartState.items` with `filteredItems`, and remove the children element of the `DeleteButton` for better styling:
|
||||
|
||||
export const cartDropdownHighlights = [
|
||||
["6", "filteredItems"], ["9", "filteredItems"],
|
||||
["21"], ["22"], ["23"], ["24"], ["25"]
|
||||
]
|
||||
|
||||
```tsx title="src/modules/layout/components/cart-dropdown/index.tsx" badgeLabel="Storefront" badgeColor="blue" highlights={cartDropdownHighlights}
|
||||
```tsx title="src/modules/layout/components/cart-dropdown/index.tsx" badgeLabel="Storefront" badgeColor="blue" highlights={[["6"], ["9"], ["21"], ["22"], ["23"], ["24"], ["25"]]}
|
||||
return (
|
||||
<div
|
||||
// ...
|
||||
@@ -5789,7 +5782,7 @@ export const removeProductBuilderFromCartWorkflowHighlights = [
|
||||
["40", "itemsToRemove", "Identify items to remove."],
|
||||
["51", "relatedItems", "Identify addon items to remove."],
|
||||
["68", "deleteLineItemsWorkflow", "Delete line items from cart."],
|
||||
["75", "updatedCart", "Retrieve updated cart."],
|
||||
["73", "updatedCart", "Retrieve updated cart."],
|
||||
["84", "releaseLockStep", "Release lock on cart."],
|
||||
]
|
||||
|
||||
@@ -5992,7 +5985,6 @@ Then, pass an `isBuilderConfigItem` prop to the `DeleteButton` component, and up
|
||||
|
||||
export const deleteButtonHighlights = [
|
||||
["3", "isBuilderConfigItem", "New prop to determine if item belongs to a product with builder configurations."],
|
||||
["6"],
|
||||
["12", "removeBuilderLineItem", "Use when the line item belongs to a product with builder configurations."],
|
||||
]
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ The Redis Cache Module is deprecated starting from [Medusa v2.11.0](https://gith
|
||||
Add the module into the `modules` property of the exported object in `medusa-config.ts`:
|
||||
|
||||
export const highlights = [
|
||||
["11", "redisUrl", "The Redis connection URL."]
|
||||
["7", "redisUrl", "The Redis connection URL."]
|
||||
]
|
||||
|
||||
```ts title="medusa-config.ts" highlights={highlights}
|
||||
|
||||
@@ -28,14 +28,10 @@ Our Cloud offering automatically provisions a Redis instance and configures the
|
||||
Add the module into the `modules` property of the exported object in `medusa-config.ts`:
|
||||
|
||||
export const highlights = [
|
||||
["12", "url", "The Redis connection URL."]
|
||||
["8", "redisUrl", "The Redis connection URL."]
|
||||
]
|
||||
|
||||
```ts title="medusa-config.ts" highlights={highlights}
|
||||
import { Modules } from "@medusajs/framework/utils"
|
||||
|
||||
// ...
|
||||
|
||||
module.exports = defineConfig({
|
||||
// ...
|
||||
modules: [
|
||||
|
||||
@@ -971,9 +971,9 @@ In `src/modules/avalara/service.ts`, add the following methods to the `AvalaraTa
|
||||
|
||||
export const avalaraItemMethodsHighlights = [
|
||||
["3", "createItems", "Create multiple items in Avalara using the Create Items API."],
|
||||
["36", "getItem", "Retrieve an item from Avalara using the Get Item API."],
|
||||
["53", "updateItem", "Update an item in Avalara using the Update Item API."],
|
||||
["82", "deleteItem", "Delete an item in Avalara using the Delete Item API."]
|
||||
["35", "getItem", "Retrieve an item from Avalara using the Get Item API."],
|
||||
["51", "updateItem", "Update an item in Avalara using the Update Item API."],
|
||||
["79", "deleteItem", "Delete an item in Avalara using the Delete Item API."]
|
||||
]
|
||||
|
||||
```ts title="src/modules/avalara/service.ts" highlights={avalaraItemMethodsHighlights}
|
||||
|
||||
@@ -2380,7 +2380,7 @@ So, create the file `src/api/store/products/[id]/[locale]/route.ts` with the fol
|
||||
|
||||
export const getProductLocaleDetailsRouteHighlights = [
|
||||
["11", "locale", "Retrieve the locale from the request's path parameters."],
|
||||
["12", "id", "Retrieve the product's ID from the request's path parameters."],
|
||||
["11", "id", "Retrieve the product's ID from the request's path parameters."],
|
||||
["13", "query", "Resolve Query from the Medusa container."],
|
||||
["15", "data", "Retrieve the product's details from Contentful."],
|
||||
["19", `"contentful_product.*"`, "Retrieve the product's details from Contentful."],
|
||||
|
||||
@@ -31,7 +31,7 @@ This guide was built with Payload v3.54.0. If you're using a different version a
|
||||
|
||||
## Summary
|
||||
|
||||
By following this tutorial, you'll learn how to:
|
||||
By following this tutorial, you'll learn how t"o:
|
||||
|
||||
- Install and set up Medusa.
|
||||
- Set up Payload in the Next.js Starter Storefront.
|
||||
@@ -357,13 +357,13 @@ Finally, you'll add the `Product` collection, which will be synced with Medusa's
|
||||
Create the file `src/collections/Products.ts` with the following content:
|
||||
|
||||
export const productCollectionHighlights = [
|
||||
["21", "update", "Only allow updating from Medusa"],
|
||||
["20", "update", "Only allow updating from Medusa"],
|
||||
["144", "update", "Only allow updating from Medusa"],
|
||||
["173", "update", "Only allow updating from Medusa"],
|
||||
["190", "update", "Only allow updating from Medusa"],
|
||||
["203", "update", "Only allow updating from Medusa"],
|
||||
["224", "create", "Only allow creating from Medusa"],
|
||||
["225", "delete", "Only allow deleting from Medusa"]
|
||||
["172", "update", "Only allow updating from Medusa"],
|
||||
["189", "update", "Only allow updating from Medusa"],
|
||||
["202", "update", "Only allow updating from Medusa"],
|
||||
["223", "create", "Only allow creating from Medusa"],
|
||||
["224", "delete", "Only allow deleting from Medusa"]
|
||||
]
|
||||
|
||||
```ts title="src/collections/Products.ts" badgeLabel="Storefront" badgeColor="blue" highlights={productCollectionHighlights}
|
||||
|
||||
@@ -681,9 +681,9 @@ If you get a type error on resolving the Sanity Module, run the Medusa applicati
|
||||
</Note>
|
||||
|
||||
export const syncStepHighlights = [
|
||||
["13", "createStep", "Create a step."],
|
||||
["15", "container", "The Medusa container to resolve resources."],
|
||||
["36", "graph", "Retrieve a paginated list of products with their sanity document."]
|
||||
["14", "createStep", "Create a step."],
|
||||
["16", "container", "The Medusa container to resolve resources."],
|
||||
["37", "graph", "Retrieve a paginated list of products with their sanity document."]
|
||||
]
|
||||
|
||||
```ts title="src/workflows/sanity-sync-products/steps/sync.ts" highlights={syncStepHighlights}
|
||||
@@ -1205,7 +1205,7 @@ Now that you're managing a product's content in Sanity, you want to show that co
|
||||
A product's details are retrieved in the file `src/app/[countryCode]/(main)/products/[handle]/page.tsx`. So, replace the `ProductPage` function with the following:
|
||||
|
||||
export const sanityContentHighlights = [
|
||||
["19", "sanity", "Get the product's content from Sanity."]
|
||||
["24", "sanity", "Get the product's content from Sanity."]
|
||||
]
|
||||
|
||||
```tsx title="src/app/[countryCode]/(main)/products/[handle]/page.tsx" badgeLabel="Storefront" badgeColor="blue" highlights={sanityContentHighlights}
|
||||
|
||||
@@ -800,10 +800,10 @@ Finally, add the `calculatePrice` method to `ShipStationProviderService`:
|
||||
|
||||
export const serviceHighlights5 = [
|
||||
["14", "shipment_id", "Retrieve the shipping method's shipment ID."],
|
||||
["20", "createShipment", "If a shipment isn't already created, create the shipment and get its rates."],
|
||||
["23", "getShipmentRates", "If a shipment is already created, retrieve its rates."],
|
||||
["27", "calculatedPrice", "Calculate the price from the specified rate."],
|
||||
["34", "is_calculated_price_tax_inclusive", "Return whether the price includes taxes."]
|
||||
["24", "createShipment", "If a shipment isn't already created, create the shipment and get its rates."],
|
||||
["37", "getShipmentRates", "If a shipment is already created, retrieve its rates."],
|
||||
["41", "calculatedPrice", "Calculate the price from the specified rate."],
|
||||
["47", "is_calculated_price_tax_inclusive", "Return whether the price includes taxes."]
|
||||
]
|
||||
|
||||
```ts title="src/modules/shipstation/service.ts" highlights={serviceHighlights5}
|
||||
@@ -892,8 +892,8 @@ Add the `validateFulfillmentData` method to `ShipStationProviderService`:
|
||||
|
||||
export const serviceHighlights4 = [
|
||||
["8", "shipment_id", "Get the ID of an already created shipment, if available."],
|
||||
["14", "createShipment", "Create a shipment if it doesn't already exist."],
|
||||
["20", "shipment_id", "Store the shipment ID in the shipping method's `data`."]
|
||||
["17", "createShipment", "Create a shipment if it doesn't already exist."],
|
||||
["38", "shipment_id", "Store the shipment ID in the shipping method's `data`."]
|
||||
]
|
||||
|
||||
```ts title="src/modules/shipstation/service.ts" highlights={serviceHighlights4}
|
||||
|
||||
@@ -657,13 +657,13 @@ The component will display the available shipping options for returns, along wit
|
||||
To create the component, create the file `src/modules/account/components/return-shipping-selector/index.tsx` with the following content:
|
||||
|
||||
export const returnShippingSelectorHighlights = [
|
||||
["13", "shippingOptions", "The available shipping options for returns."],
|
||||
["14", "selectedOption", "The currently selected shipping option ID."],
|
||||
["15", "onOptionSelect", "Callback function when a shipping option is selected."],
|
||||
["16", "cartId", "The ID of the cart associated with the order being returned."],
|
||||
["17", "currencyCode", "The currency code for displaying prices."],
|
||||
["32", "useEffect", "Fetches calculated prices for shipping options with price type 'calculated'."],
|
||||
["58", "", "Renders a message if no shipping options are available."],
|
||||
["16", "shippingOptions", "The available shipping options for returns."],
|
||||
["17", "selectedOption", "The currently selected shipping option ID."],
|
||||
["18", "onOptionSelect", "Callback function when a shipping option is selected."],
|
||||
["19", "cartId", "The ID of the cart associated with the order being returned."],
|
||||
["20", "currencyCode", "The currency code for displaying prices."],
|
||||
["35", "useEffect", "Fetches calculated prices for shipping options with price type 'calculated'."],
|
||||
["61", "", "Renders a message if no shipping options are available."],
|
||||
]
|
||||
|
||||
```tsx title="src/modules/account/components/return-shipping-selector/index.tsx" highlights={returnShippingSelectorHighlights} collapsibleLines="1-11" expandButtonLabel="Show Imports"
|
||||
|
||||
@@ -614,7 +614,7 @@ export const createWishlistStepHighlights = [
|
||||
["16", "createWishlists", "Create the wishlist."],
|
||||
["18", "wishlist", "Return the wishlist"],
|
||||
["18", "wishlist.id", "Pass the wishlist's ID to the compensation function."],
|
||||
["24", "deleteWishlists", "Delete the wishlist if an error occurs in the workflow."]
|
||||
["27", "deleteWishlists", "Delete the wishlist if an error occurs in the workflow."]
|
||||
]
|
||||
|
||||
```ts title="src/workflows/steps/create-wishlist.ts" highlights={createWishlistStepHighlights}
|
||||
@@ -1140,7 +1140,7 @@ Create the file `src/workflows/steps/create-wishlist-item.ts` with the following
|
||||
|
||||
export const createWishlistItemStepHighlights = [
|
||||
["16", "createWishlistItems", "Create the wishlist item."],
|
||||
["24", "deleteWishlistItems", "Delete the wishlist item if an error occurs in the workflow."]
|
||||
["27", "deleteWishlistItems", "Delete the wishlist item if an error occurs in the workflow."]
|
||||
]
|
||||
|
||||
```ts title="src/workflows/steps/create-wishlist-item.ts" highlights={createWishlistItemStepHighlights}
|
||||
|
||||
@@ -1297,8 +1297,8 @@ export const createBundledProductComponentHighlights2 = [
|
||||
["3", "currentProductPage", "The current page of products retrieved from the server."],
|
||||
["4", "productsCount", "The total number of products."],
|
||||
["5", "hasNextPage", "Whether there are more products to load."],
|
||||
["9", "useQuery", "Retrieve the products from the API route."],
|
||||
["23", "fetchMoreProducts", "Fetch more products when the user scrolls to the end of the list."],
|
||||
["10", "useQuery", "Retrieve the products from the API route."],
|
||||
["24", "fetchMoreProducts", "Fetch more products when the user scrolls to the end of the list."],
|
||||
]
|
||||
|
||||
```tsx title="src/admin/components/create-bundled-product.tsx" highlights={createBundledProductComponentHighlights2}
|
||||
@@ -1799,7 +1799,7 @@ export const prepareBundleCartDataStepHighlights = [
|
||||
["12", "bundle", "The bundle to add to the cart."],
|
||||
["15", "quantity", "The quantity of the bundle to add to the cart."],
|
||||
["16", "items", "The selected variants for each item in the bundle."],
|
||||
["15", "bundleItems", "Prepare the items to be added to the cart."],
|
||||
["25", "bundleItems", "Prepare the items to be added to the cart."],
|
||||
["45", "variant_id", "The ID of the selected variant to add to the cart."],
|
||||
["46", "quantity", "The quantity of the variant to add to the cart."],
|
||||
["47", "metadata", "The metadata for the line item in the cart."],
|
||||
|
||||
@@ -1887,9 +1887,9 @@ Create the file `src/workflows/create-digital-product-order/steps/create-digital
|
||||
|
||||
export const createDpoHighlights = [
|
||||
["18", "InferTypeOf", "Infer the type of the `DigitalProduct` data model since it's a variable."],
|
||||
["33", "createDigitalProductOrders", "Create the digital product order."],
|
||||
["41", "digital_product_order", "Pass the created digital product order to the compensation function."],
|
||||
["51", "deleteDigitalProductOrders", "Delete the digital product order if an error occurs in the workflow."]
|
||||
["32", "createDigitalProductOrders", "Create the digital product order."],
|
||||
["40", "digital_product_order", "Pass the created digital product order to the compensation function."],
|
||||
["50", "deleteDigitalProductOrders", "Delete the digital product order if an error occurs in the workflow."]
|
||||
]
|
||||
|
||||
```ts title="src/workflows/create-digital-product-order/steps/create-digital-product-order.ts" highlights={createDpoHighlights} collapsibleLines="1-14" expandMoreLabel="Show Imports"
|
||||
@@ -2653,10 +2653,10 @@ Create the file `src/api/store/customers/me/digital-products/[mediaId]/download/
|
||||
|
||||
export const downloadUrlHighlights = [
|
||||
["20", "query.graph", "Get the customer's orders and linked digital orders."],
|
||||
["36", "query.graph", "Get the digital product orders of the customer and associated products and media."],
|
||||
["56", "foundMedia", "Set `foundMedia` if the media's ID is equal to the ID passed as a route parameter."],
|
||||
["65", "!foundMedia", "If `foundMedia` isn't set, throw an error."],
|
||||
["72", "retrieveFile", "Retrieve the details of the media's file."]
|
||||
["34", "query.graph", "Get the digital product orders of the customer and associated products and media."],
|
||||
["55", "foundMedia", "Set `foundMedia` if the media's ID is equal to the ID passed as a route parameter."],
|
||||
["61", "!foundMedia", "If `foundMedia` isn't set, throw an error."],
|
||||
["68", "retrieveFile", "Retrieve the details of the media's file."]
|
||||
]
|
||||
|
||||
```ts title="src/api/store/customers/me/digital-products/[mediaId]/download/route.ts" highlights={downloadUrlHighlights} collapsibleLines="1-10" expandMoreLabel="Show Imports"
|
||||
|
||||
@@ -1751,7 +1751,7 @@ Create the file `src/workflows/delivery/steps/notify-restaurant.ts` with the fol
|
||||
export const notifyRestaurantStepHighlights = [
|
||||
["11", "async", "Set the step as async."],
|
||||
["18", "graph", "Retrieve the delivery and its restaurant."],
|
||||
["30", "emit", "Emit a custom event that can be used to notify the restaurant that a new delivery is created."]
|
||||
["28", "emit", "Emit a custom event that can be used to notify the restaurant that a new delivery is created."]
|
||||
]
|
||||
|
||||
```ts title="src/workflows/delivery/steps/notify-restaurant.ts" highlights={notifyRestaurantStepHighlights} collapsibleLines="1-6" expandButtonLabel="Show Imports"
|
||||
@@ -1835,7 +1835,7 @@ This step is async and its only purpose is to wait until it’s marked as succes
|
||||
Create the file `src/workflows/delivery/steps/create-order.ts` with the following content:
|
||||
|
||||
export const createOrderStepHighlights1 = [
|
||||
["16", "deliveryQuery", "Retrieve the delivery with its linked cart's details."]
|
||||
["15", "delivery", "Retrieve the delivery with its linked cart's details."]
|
||||
]
|
||||
|
||||
```ts title="src/workflows/delivery/steps/create-order.ts" highlights={createOrderStepHighlights1} collapsibleLines="1-9" expandButtonLabel="Show Imports"
|
||||
|
||||
@@ -585,11 +585,11 @@ You can now create the workflow that creates a vendor and its admin.
|
||||
Create the file `src/workflows/marketplace/create-vendor/index.ts` with the following content:
|
||||
|
||||
export const vendorWorkflowHighlights = [
|
||||
["27", "createVendorStep", "Create the vendor."],
|
||||
["33", "transform", "Prepare the vendor admin's data."],
|
||||
["43", "createVendorAdminStep", "Create the vendor admin."],
|
||||
["47", "setAuthAppMetadataStep", "Create the `vendor` actor type."],
|
||||
["53", "useQueryGraphStep", "Retrieve the created vendor with its admins."],
|
||||
["28", "createVendorStep", "Create the vendor."],
|
||||
["34", "transform", "Prepare the vendor admin's data."],
|
||||
["44", "createVendorAdminStep", "Create the vendor admin."],
|
||||
["48", "setAuthAppMetadataStep", "Create the `vendor` actor type."],
|
||||
["54", "useQueryGraphStep", "Retrieve the created vendor with its admins."],
|
||||
]
|
||||
|
||||
```ts title="src/workflows/marketplace/create-vendor/index.ts" highlights={vendorWorkflowHighlights}
|
||||
@@ -1542,7 +1542,6 @@ export const vendorOrder3Highlights = [
|
||||
["3", "map", "Loop over the vendor IDs and create a child order with only their items."],
|
||||
["11", "prepareOrderData", "Format the order data and pass it as the workflow's input."],
|
||||
["18", "push", "Add a link between the vendor and the order to be created later."],
|
||||
["30", "cancelOrderWorkflow", "Cancel all created workflows if an error occurs while creating any of them."]
|
||||
]
|
||||
|
||||
```ts title="src/workflows/marketplace/create-vendor-orders/steps/create-vendor-orders.ts" highlights={vendorOrder3Highlights}
|
||||
|
||||
@@ -722,10 +722,14 @@ The compensation function receives the subscription as a parameter. It cancels t
|
||||
Create the file `src/workflows/create-subscription/index.ts` with the following content:
|
||||
|
||||
export const createSubscriptionWorkflowHighlights = [
|
||||
["26", "completeCartWorkflow", "Complete the cart and create the order."],
|
||||
["32", "useQueryGraphStep", "Retrieve the order's details."],
|
||||
["87", "createSubscriptionStep", "Create the subscription."],
|
||||
["94", "createRemoteLinkStep", "Create the links returned by the previous step."]
|
||||
["29", "acquireLockStep", "Acquire a lock on the cart to prevent race conditions."],
|
||||
["34", "completeCartWorkflow", "Complete the cart and create the order."],
|
||||
["40", "useQueryGraphStep", "Retrieve the order's details."],
|
||||
["95", "useQueryGraphStep", "Retrieve any existing subscription links for the order."],
|
||||
["101", "when", "Check if a subscription already exists for the order."],
|
||||
["108", "createSubscriptionStep", "Create the subscription."],
|
||||
["115", "createRemoteLinkStep", "Create the links returned by the previous step."],
|
||||
["120", "releaseLockStep", "Release the lock on the cart."]
|
||||
]
|
||||
|
||||
```ts title="src/workflows/create-subscription/index.ts" highlights={createSubscriptionWorkflowHighlights} collapsibleLines="1-13" expandMoreLabel="Show Imports"
|
||||
|
||||
@@ -1212,13 +1212,7 @@ This displays the selected seat number and show date for ticket products instead
|
||||
|
||||
You should also remove the quantity selector for ticket products since you can't purchase multiple tickets for the same seat. Remove the following highlighted lines from the `return` statement of the `Item` component:
|
||||
|
||||
export const removeHighlights = [
|
||||
["5"], ["6"], ["7"], ["8"], ["9"], ["10"], ["11"], ["12"], ["13"], ["14"],
|
||||
["15"], ["16"], ["17"], ["18"], ["19"], ["20"], ["21"], ["22"], ["23"], ["24"],
|
||||
["25"], ["26"], ["27"], ["29"]
|
||||
]
|
||||
|
||||
```tsx title="src/modules/cart/components/item/index.tsx" highlights={removeHighlights}
|
||||
```tsx title="src/modules/cart/components/item/index.tsx"
|
||||
{type === "full" && (
|
||||
<Table.Cell>
|
||||
<div className="flex gap-2 items-center w-28">
|
||||
|
||||
@@ -26,7 +26,6 @@ For example:
|
||||
export const highlights = [
|
||||
["17", "cartId", "Retrieve the cart ID from `localStorage`."],
|
||||
["19", "TODO", "You can create the cart and set it here as explained in the Create Cart guide."],
|
||||
["23"], ["24"], ["25"], ["26"],
|
||||
["29", "formatPrice", "This function was previously created to format product prices. You can re-use the same function."],
|
||||
["32", "currency", "If you reuse the `formatPrice` function, pass the currency code as a parameter."],
|
||||
]
|
||||
|
||||
@@ -50,8 +50,6 @@ For example:
|
||||
export const highlights = [
|
||||
["4", "useCart", "The `useCart` hook was defined in the Cart React Context documentation."],
|
||||
["30", "address", "Assemble the address object to be used for both shipping and billing addresses."],
|
||||
["42"], ["43"], ["44"], ["45"], ["46"], ["47"], ["48"],
|
||||
["49"], ["50"],
|
||||
["96", "", "The address's country can only be within the cart's region."]
|
||||
]
|
||||
|
||||
|
||||
@@ -39,7 +39,6 @@ For example:
|
||||
export const highlights = [
|
||||
["4", "useCart", "The `useCart` hook was defined in the Cart React Context documentation."],
|
||||
["14", "TODO", "Cart must have at least one item. If not, redirect to another page."],
|
||||
["28"], ["29"], ["30"], ["31"], ["32"], ["33"], ["34"],
|
||||
]
|
||||
|
||||
```tsx highlights={highlights}
|
||||
|
||||
@@ -200,12 +200,12 @@ export const highlights = [
|
||||
|
||||
export const fetchHighlights = [
|
||||
["5", "retrieveShippingOptions", "This function retrieves the shipping options of the customer's cart."],
|
||||
["21", "calculateShippingOptionPrices", "This function retrieves the prices of shipping options of type `calculated`."],
|
||||
["34", "data", "Pass in this property any data relevant to the fulfillment provider."],
|
||||
["56", "formatPrice", "This function formats a price based on the cart's currency."],
|
||||
["65", "getShippingOptionPrice", "This function gets the price of a shipping option based on its type."],
|
||||
["77", "setShippingMethod", "This function sets the shipping method of the cart using the selected shipping option."],
|
||||
["91", "data", "Pass in this property any data relevant to the fulfillment provider."],
|
||||
["13", "calculateShippingOptionPrices", "This function retrieves the prices of shipping options of type `calculated`."],
|
||||
["19", "data", "Pass in this property any data relevant to the fulfillment provider."],
|
||||
["39", "formatPrice", "This function formats a price based on the cart's currency."],
|
||||
["48", "getShippingOptionPrice", "This function gets the price of a shipping option based on its type."],
|
||||
["60", "setShippingMethod", "This function sets the shipping method of the cart using the selected shipping option."],
|
||||
["65", "data", "Pass in this property any data relevant to the fulfillment provider."],
|
||||
]
|
||||
|
||||
```ts highlights={fetchHighlights}
|
||||
|
||||
@@ -161,8 +161,6 @@ To add a new address for the customer, send a request to the [Add Customer Addre
|
||||
export const addHighlights = [
|
||||
["4", "useRegion", "Use the hook defined in the Region Context guide."],
|
||||
["5", "useCustomer", "Use the hook defined in the Customer Context guide."],
|
||||
["29"], ["30"], ["31"], ["32"], ["33"], ["34"], ["35"], ["36"], ["37"],
|
||||
["38"], ["39"], ["40"], ["41"], ["42"], ["43"],
|
||||
]
|
||||
|
||||
```tsx highlights={addHighlights} collapsibleLines="46-117" expandButtonLabel="Show form"
|
||||
@@ -334,8 +332,6 @@ export const editHighlights = [
|
||||
["4", "useRegion", "Use the hook defined in the Region Context guide."],
|
||||
["5", "useCustomer", "Use the hook defined in the Customer Context guide."],
|
||||
["18", "address", "Retrieve the address from the customer's `addresses` property."],
|
||||
["59"], ["60"], ["61"], ["62"], ["63"], ["64"], ["65"], ["66"], ["67"],
|
||||
["68"], ["69"], ["70"], ["71"], ["72"], ["73"],
|
||||
]
|
||||
|
||||
```tsx highlights={editHighlights} collapsibleLines="76-147" expandButtonLabel="Show form"
|
||||
|
||||
@@ -292,7 +292,7 @@ curl '{backend_url}/store/products' \
|
||||
</CodeTab>
|
||||
<CodeTab label="Fetch" value="fetch">
|
||||
|
||||
```ts highlights={["2", "", "Passes the cookie session ID in your request."]}
|
||||
```ts highlights={[["2", "credentials", "Passes the cookie session ID in your request."]]}
|
||||
fetch(`<BACKEND_URL>/store/products`, {
|
||||
credentials: "include",
|
||||
})
|
||||
|
||||
@@ -33,7 +33,6 @@ For example:
|
||||
|
||||
export const highlights = [
|
||||
["4", "useCustomer", "Use the hook defined in the Customer Context guide."],
|
||||
["35"], ["36"], ["37"], ["38"], ["39"], ["40"], ["41"], ["42"], ["43"], ["44"],
|
||||
]
|
||||
|
||||
```tsx highlights={highlights} collapsibleLines="47-85" expandButtonLabel="Show form"
|
||||
|
||||
@@ -1350,7 +1350,7 @@ Then, replace the `TODO` in the `Product` component with the following:
|
||||
export const productHighlights4 = [
|
||||
["1", "price", "The formatted price to show to the customer."],
|
||||
["2", "selectedVariantPrice", "Determine the variant to show its price, which is either the selected variant or the variant with the smallest price."],
|
||||
["29", "formatPrice", "Return the formatted price using the utility you created."]
|
||||
["19", "formatPrice", "Return the formatted price using the utility you created."]
|
||||
]
|
||||
|
||||
```tsx title="components/Product/index.tsx" highlights={productHighlights4}
|
||||
@@ -2049,7 +2049,7 @@ export const shippingHighlights3 = [
|
||||
["7", "filter", "Retrieve shipping options with calculated prices only."],
|
||||
["9", "fetch", "Retrieve the calculated price from the Medusa application."],
|
||||
["24", "Promise.allSettled", "Wait for all calculated prices to be retrieved."],
|
||||
["13", "setCalculatedPrices", "Set the calculated prices in the state variable."],
|
||||
["33", "setCalculatedPrices", "Set the calculated prices in the state variable."],
|
||||
]
|
||||
|
||||
```tsx title="components/Shipping/index.tsx" highlights={shippingHighlights3}
|
||||
|
||||
@@ -50,11 +50,7 @@ Learn how to install and configure the JS SDK in the [JS SDK documentation](../.
|
||||
<CodeTabs group="store-request">
|
||||
<CodeTab label="React" value="react">
|
||||
|
||||
export const highlights = [
|
||||
["18"], ["19"], ["20"], ["21"], ["22"]
|
||||
]
|
||||
|
||||
```tsx highlights={highlights}
|
||||
```tsx highlights={[["18"], ["19"], ["20"], ["21"], ["22"]]}
|
||||
"use client" // include with Next.js 13+
|
||||
|
||||
import { useEffect, useState } from "react"
|
||||
|
||||
@@ -36,12 +36,7 @@ Learn how to install and configure the JS SDK in the [JS SDK documentation](../.
|
||||
<CodeTabs group="store-request">
|
||||
<CodeTab label="React" value="react">
|
||||
|
||||
export const highlights = [
|
||||
["18"], ["19"], ["20"],
|
||||
["21"], ["22"],
|
||||
]
|
||||
|
||||
```tsx highlights={highlights}
|
||||
```tsx highlights={[["18"], ["19"], ["20"], ["21"], ["22"]]}
|
||||
"use client" // include with Next.js 13+
|
||||
|
||||
import { useEffect, useState } from "react"
|
||||
|
||||
@@ -48,9 +48,8 @@ Learn how to install and configure the JS SDK in the [JS SDK documentation](../.
|
||||
<CodeTab label="React" value="react">
|
||||
|
||||
export const highlights = [
|
||||
["22"], ["23", `fields`, "Select the fields of category children"],
|
||||
["23", `fields`, "Select the fields of category children"],
|
||||
["24", "include_descendants_tree", "Indicate that all nested categories should be retrieved."],
|
||||
["25"], ["26"], ["27"], ["28"], ["29"],
|
||||
["39", "category_children", "Show the nested categories."],
|
||||
]
|
||||
|
||||
@@ -156,11 +155,9 @@ For example:
|
||||
<CodeTab label="React" value="react">
|
||||
|
||||
export const categoriesHighlights = [
|
||||
["22"], ["23"], ["24", `fields`, "Select the fields of category children"],
|
||||
["24", `fields`, "Select the fields of category children"],
|
||||
["25", "include_descendants_tree", "Indicate that all nested categories should be retrieved."],
|
||||
["26", "parent_category_id", "Since each category will have its children, you only retrieve categories that don't have a parent."],
|
||||
["27"], ["28"],
|
||||
["29"], ["30"], ["31"],
|
||||
["45", "category_children", "Show the nested categories."],
|
||||
]
|
||||
|
||||
|
||||
@@ -31,10 +31,7 @@ Learn how to install and configure the JS SDK in the [JS SDK documentation](../.
|
||||
<CodeTab label="React" value="react">
|
||||
|
||||
export const highlights = [
|
||||
["29"], ["30"], ["31"],
|
||||
["32", "category_id", "Pass the category ID as a query parameter."], ["33"],
|
||||
["34"], ["35"], ["36"],
|
||||
["37"], ["38"], ["39"], ["40"], ["41"], ["42"], ["43"], ["44"]
|
||||
["32", "category_id", "Pass the category ID as a query parameter."],
|
||||
]
|
||||
|
||||
```tsx highlights={highlights}
|
||||
|
||||
@@ -39,12 +39,7 @@ Learn how to install and configure the JS SDK in the [JS SDK documentation](../.
|
||||
<CodeTabs group="store-request">
|
||||
<CodeTab label="React" value="react">
|
||||
|
||||
export const highlights = [
|
||||
["22"], ["23"], ["24"],
|
||||
["25"], ["26"],
|
||||
]
|
||||
|
||||
```tsx highlights={highlights}
|
||||
```tsx highlights={[["22"], ["23"], ["24"], ["25"], ["26"]]}
|
||||
"use client" // include with Next.js 13+
|
||||
|
||||
import { useEffect, useState } from "react"
|
||||
@@ -118,13 +113,7 @@ To retrieve a product by its handle, send a request to the [List Product Categor
|
||||
<CodeTabs group="store-request">
|
||||
<CodeTab label="React" value="react">
|
||||
|
||||
export const handleHighlights = [
|
||||
["22"], ["23"], ["24"],
|
||||
["25"], ["26"], ["27"], ["28"],
|
||||
["29"], ["30"],
|
||||
]
|
||||
|
||||
```tsx highlights={handleHighlights}
|
||||
```tsx highlights={[["22"], ["23"], ["24"], ["25"], ["26"], ["27"], ["28"], ["29"], ["30"]]}
|
||||
"use client" // include with Next.js 13+
|
||||
|
||||
import { useEffect, useState } from "react"
|
||||
|
||||
@@ -36,12 +36,7 @@ Learn how to install and configure the JS SDK in the [JS SDK documentation](../.
|
||||
<CodeTabs group="store-request">
|
||||
<CodeTab label="React" value="react">
|
||||
|
||||
export const highlights = [
|
||||
["18"], ["19"], ["20"],
|
||||
["21"], ["22"],
|
||||
]
|
||||
|
||||
```tsx highlights={highlights}
|
||||
```tsx highlights={[["18"], ["19"], ["20"], ["21"], ["22"]]}
|
||||
"use client" // include with Next.js 13+
|
||||
|
||||
import { useEffect, useState } from "react"
|
||||
|
||||
@@ -31,10 +31,7 @@ Learn how to install and configure the JS SDK in the [JS SDK documentation](../.
|
||||
<CodeTab label="React" value="react">
|
||||
|
||||
export const highlights = [
|
||||
["29"], ["30"], ["31"],
|
||||
["32", "collection_id", "Pass the collection ID as a query parameter."], ["33"],
|
||||
["34"], ["35"], ["36"],
|
||||
["37"], ["38"], ["39"], ["40"], ["41"], ["42"], ["43"], ["44"], ["45"], ["46"], ["47"]
|
||||
["32", "collection_id", "Pass the collection ID as a query parameter."],
|
||||
]
|
||||
|
||||
```tsx highlights={highlights}
|
||||
|
||||
@@ -39,12 +39,7 @@ Learn how to install and configure the JS SDK in the [JS SDK documentation](../.
|
||||
<CodeTabs group="store-request">
|
||||
<CodeTab label="React" value="react">
|
||||
|
||||
export const highlights = [
|
||||
["22"], ["23"], ["24"],
|
||||
["25"], ["26"],
|
||||
]
|
||||
|
||||
```tsx highlights={highlights}
|
||||
```tsx highlights={[["22"], ["23"], ["24"], ["25"], ["26"]]}
|
||||
"use client" // include with Next.js 13+
|
||||
|
||||
import { useEffect, useState } from "react"
|
||||
@@ -117,12 +112,7 @@ To retrieve a product by its handle, send a request to the [List Product Collect
|
||||
<CodeTabs group="store-request">
|
||||
<CodeTab label="React" value="react">
|
||||
|
||||
export const handleHighlights = [
|
||||
["24"], ["25"], ["26"],
|
||||
["27"], ["28"], ["29"], ["30"], ["31"], ["32"],
|
||||
]
|
||||
|
||||
```tsx highlights={handleHighlights}
|
||||
```tsx highlights={[["24"], ["25"], ["26"], ["27"], ["28"], ["29"], ["30"], ["31"], ["32"]]}
|
||||
"use client" // include with Next.js 13+
|
||||
|
||||
import { useEffect, useState } from "react"
|
||||
|
||||
@@ -29,11 +29,7 @@ Learn how to install and configure the JS SDK in the [JS SDK documentation](../.
|
||||
<CodeTabs group="store-request">
|
||||
<CodeTab label="React" value="react">
|
||||
|
||||
export const highlights = [
|
||||
["18"], ["19"], ["20"], ["21"], ["22"]
|
||||
]
|
||||
|
||||
```tsx highlights={highlights}
|
||||
```tsx highlights={[["18"], ["19"], ["20"], ["21"], ["22"]]}
|
||||
"use client" // include with Next.js 13+
|
||||
|
||||
import { useEffect, useState } from "react"
|
||||
|
||||
@@ -38,12 +38,7 @@ Learn how to install and configure the JS SDK in the [JS SDK documentation](../.
|
||||
<CodeTabs group="store-request">
|
||||
<CodeTab label="React" value="react">
|
||||
|
||||
export const highlights = [
|
||||
["22"], ["23"],
|
||||
["24"], ["25"], ["26"], ["27"],
|
||||
]
|
||||
|
||||
```tsx highlights={highlights}
|
||||
```tsx highlights={[["22"], ["23"], ["24"], ["25"], ["26"], ["27"]]}
|
||||
"use client" // include with Next.js 13+
|
||||
|
||||
import { useEffect, useState } from "react"
|
||||
@@ -137,11 +132,7 @@ To retrieve a product by its handle, send a request to the [List Products API ro
|
||||
<CodeTabs group="store-request">
|
||||
<CodeTab label="React" value="react">
|
||||
|
||||
export const handleHighlights = [
|
||||
["24"], ["25"], ["26"], ["27"], ["28"], ["29"], ["30"], ["31"], ["32"]
|
||||
]
|
||||
|
||||
```tsx highlights={handleHighlights}
|
||||
```tsx highlights={[["24"], ["25"], ["26"], ["27"], ["28"], ["29"], ["30"], ["31"], ["32"]]}
|
||||
"use client" // include with Next.js 13+
|
||||
|
||||
import { useEffect, useState } from "react"
|
||||
|
||||
@@ -48,7 +48,7 @@ export const highlights = [
|
||||
["38", "regionId", "Retrieve the selected region from the `localStorage`."],
|
||||
["41", "list", "If no region is selected, retrieve the list of regions from the Medusa application and select the first one."],
|
||||
["47", "retrieve", "If a region is selected, retrieve it from the Medusa application."],
|
||||
["6", "useRegion", "The hook that child components of the provider use to access the region."]
|
||||
["64", "useRegion", "The hook that child components of the provider use to access the region."]
|
||||
]
|
||||
|
||||
```tsx highlights={highlights}
|
||||
|
||||
@@ -33,11 +33,7 @@ Learn how to install and configure the JS SDK in the [JS SDK documentation](../.
|
||||
<CodeTabs group="store-request">
|
||||
<CodeTab label="React" value="react">
|
||||
|
||||
export const highlights = [
|
||||
["18"], ["19"], ["20"], ["21"], ["22"]
|
||||
]
|
||||
|
||||
```tsx highlights={highlights}
|
||||
```tsx highlights={[["18"], ["19"], ["20"], ["21"], ["22"]]}
|
||||
"use client" // include with Next.js 13+
|
||||
|
||||
import { useEffect, useState } from "react"
|
||||
|
||||
@@ -4,6 +4,7 @@ import {
|
||||
prerequisitesLinkFixerPlugin,
|
||||
recmaInjectMdxDataPlugin,
|
||||
typeListLinkFixerPlugin,
|
||||
validateHighlightsPlugin,
|
||||
workflowDiagramLinkFixerPlugin,
|
||||
} from "remark-rehype-plugins"
|
||||
|
||||
@@ -48,6 +49,7 @@ const withMDX = mdx({
|
||||
},
|
||||
],
|
||||
...mdxPluginOptions.options.rehypePlugins,
|
||||
[validateHighlightsPlugin, { verbose: false }],
|
||||
[localLinksRehypePlugin],
|
||||
[typeListLinkFixerPlugin],
|
||||
[
|
||||
|
||||
@@ -13,6 +13,7 @@ import {
|
||||
prerequisitesLinkFixerPlugin,
|
||||
remarkAttachFrontmatterDataPlugin,
|
||||
recmaInjectMdxDataPlugin,
|
||||
validateHighlightsPlugin,
|
||||
uiRehypePlugin,
|
||||
} from "remark-rehype-plugins"
|
||||
import bundleAnalyzer from "@next/bundle-analyzer"
|
||||
@@ -81,6 +82,7 @@ const withMDX = mdx({
|
||||
tagName: "code",
|
||||
},
|
||||
],
|
||||
[validateHighlightsPlugin, { verbose: false }],
|
||||
[rehypeSlug],
|
||||
[
|
||||
cloudinaryImgRehypePlugin,
|
||||
|
||||
@@ -13,6 +13,7 @@ import {
|
||||
prerequisitesLinkFixerPlugin,
|
||||
remarkAttachFrontmatterDataPlugin,
|
||||
recmaInjectMdxDataPlugin,
|
||||
validateHighlightsPlugin,
|
||||
} from "remark-rehype-plugins"
|
||||
import bundleAnalyzer from "@next/bundle-analyzer"
|
||||
import withExtractedTableOfContents from "@stefanprobst/rehype-extract-toc"
|
||||
@@ -79,6 +80,7 @@ const withMDX = mdx({
|
||||
tagName: "code",
|
||||
},
|
||||
],
|
||||
[validateHighlightsPlugin, { verbose: false }],
|
||||
[rehypeSlug],
|
||||
[
|
||||
cloudinaryImgRehypePlugin,
|
||||
|
||||
@@ -9,24 +9,39 @@ import {
|
||||
JSXTextExpression,
|
||||
LiteralExpression,
|
||||
ObjectExpression,
|
||||
TemplateLiteralExpression,
|
||||
VariableDeclaration,
|
||||
} from "types"
|
||||
|
||||
const ALLOWED_BODY_TYPES = ["ExpressionStatement", "ExportNamedDeclaration"]
|
||||
|
||||
export function estreeToJs(estree: Estree) {
|
||||
// TODO improve on this utility. Currently it's implemented to work
|
||||
// for specific use cases as we don't have a lot of info on other
|
||||
// use cases.
|
||||
if (
|
||||
!estree.body?.length ||
|
||||
estree.body[0].type !== "ExpressionStatement" ||
|
||||
!estree.body[0].expression
|
||||
!estree.body[0].type ||
|
||||
!ALLOWED_BODY_TYPES.includes(estree.body[0].type)
|
||||
) {
|
||||
return
|
||||
}
|
||||
|
||||
switch (estree.body[0].type) {
|
||||
case "ExpressionStatement":
|
||||
if (!estree.body[0].expression) {
|
||||
return
|
||||
}
|
||||
return expressionToJs(estree.body[0].expression)
|
||||
case "ExportNamedDeclaration":
|
||||
if (!estree.body[0].declaration) {
|
||||
return
|
||||
}
|
||||
return declarationToJs(estree.body[0].declaration)
|
||||
}
|
||||
}
|
||||
|
||||
function expressionToJs(
|
||||
export function expressionToJs(
|
||||
expression: Expression
|
||||
): ExpressionJsVar | ExpressionJsVar[] | undefined {
|
||||
switch (expression.type) {
|
||||
@@ -84,5 +99,36 @@ function expressionToJs(
|
||||
},
|
||||
data: text,
|
||||
}
|
||||
case "TemplateLiteral":
|
||||
const templateExpression = expression as TemplateLiteralExpression
|
||||
let value = ""
|
||||
let raw = ""
|
||||
templateExpression.quasis.forEach((quasi) => {
|
||||
value += quasi.value.cooked
|
||||
raw += quasi.value.raw
|
||||
})
|
||||
return {
|
||||
original: {
|
||||
type: "Literal",
|
||||
value,
|
||||
raw,
|
||||
},
|
||||
data: value,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function declarationToJs(declaration: VariableDeclaration): {
|
||||
name: string
|
||||
value: ExpressionJsVar | ExpressionJsVar[] | undefined
|
||||
} {
|
||||
if (!declaration.declarations.length) {
|
||||
throw new Error("No declarations found")
|
||||
}
|
||||
const name = declaration.declarations[0].id.name
|
||||
const value = expressionToJs(declaration.declarations[0].init)
|
||||
return {
|
||||
name,
|
||||
value,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -175,7 +175,7 @@ function componentChecker({
|
||||
|
||||
const itemJsVar = estreeToJs(attribute.value.data.estree)
|
||||
|
||||
if (!itemJsVar) {
|
||||
if (!itemJsVar || "name" in itemJsVar) {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -217,7 +217,7 @@ function checkLink({
|
||||
currentPageFilePath: string
|
||||
options: BrokenLinkCheckerOptions
|
||||
}) {
|
||||
if (!link || typeof link !== "string") {
|
||||
if (!link || typeof link !== "string" || link === "/" || link === "#") {
|
||||
return
|
||||
}
|
||||
// try to remove hash
|
||||
|
||||
@@ -88,7 +88,7 @@ function componentFixer(
|
||||
|
||||
const itemJsVar = estreeToJs(attribute.value.data.estree)
|
||||
|
||||
if (!itemJsVar) {
|
||||
if (!itemJsVar || "name" in itemJsVar) {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ export * from "./prerequisites-link-fixer.js"
|
||||
export * from "./resolve-admonitions.js"
|
||||
export * from "./type-list-link-fixer.js"
|
||||
export * from "./ui-rehype-plugin.js"
|
||||
export * from "./validate-highlights.js"
|
||||
export * from "./workflow-diagram-link-fixer.js"
|
||||
|
||||
export * from "./utils/fix-link.js"
|
||||
|
||||
@@ -105,7 +105,7 @@ export function componentLinkFixer(
|
||||
|
||||
const itemJsVar = estreeToJs(attribute.value.data.estree)
|
||||
|
||||
if (!itemJsVar) {
|
||||
if (!itemJsVar || "name" in itemJsVar) {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
253
www/packages/remark-rehype-plugins/src/validate-highlights.ts
Normal file
253
www/packages/remark-rehype-plugins/src/validate-highlights.ts
Normal file
@@ -0,0 +1,253 @@
|
||||
import {
|
||||
ArrayExpression,
|
||||
Estree,
|
||||
ExpressionJsVar,
|
||||
Identifier,
|
||||
JSXElementExpression,
|
||||
JSXExpressionContainer,
|
||||
LiteralExpression,
|
||||
UnistNode,
|
||||
UnistTree,
|
||||
} from "types"
|
||||
import type { Transformer } from "unified"
|
||||
import { estreeToJs, expressionToJs } from "docs-utils"
|
||||
|
||||
type Options = {
|
||||
verbose?: boolean
|
||||
}
|
||||
|
||||
export function validateHighlightsPlugin(options?: Options): Transformer {
|
||||
const { verbose } = options || {}
|
||||
return async (tree) => {
|
||||
const { visit } = await import("unist-util-visit")
|
||||
const highlightConsts = new Map<string, string[][]>()
|
||||
|
||||
visit(tree as UnistTree, ["mdxjsEsm", "element"], (node: UnistNode) => {
|
||||
if (node.type === "mdxjsEsm") {
|
||||
if (node.data && "estree" in node.data && node.data.estree) {
|
||||
const highlightsJsVar = estreeToJs(node.data.estree)
|
||||
|
||||
if (
|
||||
!highlightsJsVar ||
|
||||
!("name" in highlightsJsVar) ||
|
||||
typeof highlightsJsVar.name !== "string" ||
|
||||
!Array.isArray(highlightsJsVar.value)
|
||||
) {
|
||||
return
|
||||
}
|
||||
|
||||
const highlights = getHighlightsFromExpressionJsVar(
|
||||
highlightsJsVar.value
|
||||
)
|
||||
if (highlights) {
|
||||
highlightConsts.set(highlightsJsVar.name, highlights)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if (
|
||||
node.tagName !== "pre" ||
|
||||
!node.children?.length ||
|
||||
!node.children[0].data ||
|
||||
!("estree" in node.children[0].data) ||
|
||||
!node.children[0].data.estree
|
||||
) {
|
||||
return
|
||||
}
|
||||
|
||||
const body = (node.children[0].data.estree as Estree).body?.[0]
|
||||
|
||||
if (
|
||||
!body ||
|
||||
body.type !== "ExpressionStatement" ||
|
||||
!body.expression ||
|
||||
body.expression.type !== "JSXElement"
|
||||
) {
|
||||
return
|
||||
}
|
||||
|
||||
const bodyExpression = body.expression as JSXElementExpression
|
||||
|
||||
if (
|
||||
!bodyExpression.children.length ||
|
||||
bodyExpression.children[0].type !== "JSXExpressionContainer"
|
||||
) {
|
||||
return
|
||||
}
|
||||
|
||||
const codeExpression = (
|
||||
bodyExpression.children[0] as JSXExpressionContainer
|
||||
).expression
|
||||
|
||||
if (codeExpression.type !== "Literal") {
|
||||
return
|
||||
}
|
||||
|
||||
const highlightsAttr = bodyExpression.openingElement?.attributes.find(
|
||||
(attr) => attr.name.name === "highlights"
|
||||
)
|
||||
|
||||
if (!highlightsAttr) {
|
||||
return
|
||||
}
|
||||
|
||||
let highlights: string[][] | undefined
|
||||
if (
|
||||
highlightsAttr.value.expression.type !== "Identifier" &&
|
||||
highlightsAttr.value.expression.type === "ArrayExpression"
|
||||
) {
|
||||
const highlightsJs = getExpressionJsVarFromArrExpression(
|
||||
highlightsAttr.value.expression as ArrayExpression
|
||||
)
|
||||
if (!highlightsJs || !Array.isArray(highlightsJs)) {
|
||||
return
|
||||
}
|
||||
highlights = getHighlightsFromExpressionJsVar(highlightsJs)
|
||||
|
||||
if (!highlights) {
|
||||
return
|
||||
}
|
||||
} else {
|
||||
if (highlightsAttr.value.expression.type !== "Identifier") {
|
||||
return
|
||||
}
|
||||
const name = (highlightsAttr.value.expression as Identifier).name
|
||||
highlights = highlightConsts.get(name)
|
||||
|
||||
if (!highlights) {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
const code = (codeExpression as LiteralExpression).value as string
|
||||
|
||||
validateCodeHighlights({
|
||||
highlights,
|
||||
code,
|
||||
verbose,
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const getExpressionJsVarFromArrExpression = (
|
||||
expression: ArrayExpression
|
||||
): ExpressionJsVar[][] => {
|
||||
if (!Array.isArray(expression.elements)) {
|
||||
return []
|
||||
}
|
||||
return expression.elements.map((elm) => {
|
||||
const elmJsVar = expressionToJs(elm)
|
||||
if (!elmJsVar || !Array.isArray(elmJsVar)) {
|
||||
return []
|
||||
}
|
||||
return elmJsVar
|
||||
})
|
||||
}
|
||||
|
||||
const getHighlightsFromExpressionJsVar = (
|
||||
expression: ExpressionJsVar[] | ExpressionJsVar[][]
|
||||
): string[][] | undefined => {
|
||||
const highlights: string[][] = []
|
||||
const shouldExtractHighlights = !Array.isArray(expression[0])
|
||||
// the expression is an array where each three items are a highlight
|
||||
// so we need to split the expression into groups of three items first
|
||||
const highlightExpressions = shouldExtractHighlights
|
||||
? (expression as ExpressionJsVar[]).reduce((acc, item, index) => {
|
||||
if (index % 3 === 0) {
|
||||
acc.push([])
|
||||
}
|
||||
acc[acc.length - 1].push(item)
|
||||
return acc
|
||||
}, [] as ExpressionJsVar[][])
|
||||
: (expression as ExpressionJsVar[][])
|
||||
|
||||
if (!highlightExpressions.length) {
|
||||
return undefined
|
||||
}
|
||||
|
||||
for (const highlightExpression of highlightExpressions) {
|
||||
if (highlightExpression.length !== 3) {
|
||||
continue
|
||||
}
|
||||
|
||||
const highlight = []
|
||||
for (const item of highlightExpression) {
|
||||
if (typeof item.data !== "string") {
|
||||
continue
|
||||
}
|
||||
highlight.push(item.data)
|
||||
}
|
||||
highlights.push(highlight)
|
||||
}
|
||||
|
||||
return !highlights.length ? undefined : highlights
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates that the highlights of each code block are correct. It validates:
|
||||
*
|
||||
* 1. The highlight's first parameter is a string number of a valid line number in the code block.
|
||||
* 2. The highlight's second parameter is a string that is a valid text in the line of the code block.
|
||||
*/
|
||||
const validateCodeHighlights = ({
|
||||
highlights,
|
||||
code,
|
||||
verbose,
|
||||
}: {
|
||||
highlights: string[][]
|
||||
code: string
|
||||
verbose?: boolean
|
||||
}): void => {
|
||||
try {
|
||||
const lines = code.trim().split("\n")
|
||||
for (const highlight of highlights) {
|
||||
if (highlight.length < 2) {
|
||||
throw new Error(`Highlight array must have at least 2 elements`)
|
||||
}
|
||||
|
||||
const lineNumber = highlight[0]
|
||||
const text = highlight[1]
|
||||
|
||||
if (typeof lineNumber !== "string" || typeof text !== "string") {
|
||||
throw new Error(`Highlight array must have at least 2 elements`)
|
||||
}
|
||||
|
||||
if (isNaN(Number(lineNumber))) {
|
||||
throw new Error(`Highlight line number must be a number`)
|
||||
}
|
||||
|
||||
const line = lines[Number(lineNumber) - 1]?.trim()
|
||||
if (line === undefined) {
|
||||
throw new Error(`Highlight line number ${lineNumber} not found in code`)
|
||||
}
|
||||
|
||||
if (text.length && !line.includes(text)) {
|
||||
throw new Error(
|
||||
`Highlight text ${text} not found in line ${lineNumber}`
|
||||
)
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
throw new Error(
|
||||
formatError({
|
||||
message: (err as Error).message,
|
||||
code,
|
||||
verbose,
|
||||
})
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const formatError = ({
|
||||
message,
|
||||
code,
|
||||
verbose,
|
||||
}: {
|
||||
message: string
|
||||
code: string
|
||||
verbose?: boolean
|
||||
}): string => {
|
||||
return `${message}${verbose ? `:\n${code}` : ""}`
|
||||
}
|
||||
@@ -41,6 +41,10 @@ export type LiteralExpression = {
|
||||
export type JSXElementExpression = {
|
||||
type: "JSXElement" | "JSXFragment"
|
||||
children: Expression[]
|
||||
openingElement: {
|
||||
type: "JSXOpeningElement"
|
||||
attributes: UnistJSXAttributeNode[]
|
||||
}
|
||||
}
|
||||
|
||||
export type JSXTextExpression = {
|
||||
@@ -49,6 +53,33 @@ export type JSXTextExpression = {
|
||||
raw: string
|
||||
}
|
||||
|
||||
export type VariableDeclaration = {
|
||||
type: "VariableDeclaration"
|
||||
declarations: VariableDeclarator[]
|
||||
}
|
||||
export type VariableDeclarator = {
|
||||
type: "VariableDeclarator"
|
||||
id: Identifier
|
||||
init: Expression
|
||||
}
|
||||
|
||||
export type Identifier = {
|
||||
type: "Identifier"
|
||||
name: string
|
||||
}
|
||||
|
||||
export type TemplateLiteralExpression = {
|
||||
type: "TemplateLiteral"
|
||||
expressions: Expression[]
|
||||
quasis: {
|
||||
type: "TemplateElement"
|
||||
value: {
|
||||
raw: string
|
||||
cooked: string
|
||||
}
|
||||
}[]
|
||||
}
|
||||
|
||||
export type Expression =
|
||||
| {
|
||||
type: string
|
||||
@@ -60,10 +91,28 @@ export type Expression =
|
||||
| JSXTextExpression
|
||||
|
||||
export interface Estree {
|
||||
body?: {
|
||||
type?: string
|
||||
body?: (
|
||||
| {
|
||||
type?: "ExpressionStatement"
|
||||
expression?: Expression
|
||||
}[]
|
||||
}
|
||||
| {
|
||||
type?: "ExportNamedDeclaration"
|
||||
declaration?: VariableDeclaration
|
||||
}
|
||||
)[]
|
||||
}
|
||||
|
||||
export interface UnistJSXAttributeNode {
|
||||
type: "JSXAttribute"
|
||||
name: {
|
||||
type: "JSXIdentifier"
|
||||
name: string
|
||||
}
|
||||
value: {
|
||||
type: "JSXExpressionContainer"
|
||||
expression: Identifier | Expression
|
||||
}
|
||||
}
|
||||
|
||||
export interface UnistNodeWithData extends UnistNode {
|
||||
@@ -244,3 +293,8 @@ export type ExpressionJsVarObj = {
|
||||
}
|
||||
|
||||
export type ExpressionJsVar = ExpressionJsVarObj | ExpressionJsVarLiteral
|
||||
|
||||
export type JSXExpressionContainer = {
|
||||
type: "JSXExpressionContainer"
|
||||
expression: Expression
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user