From a7d670037afb494b874887310f75f25c5e524bf0 Mon Sep 17 00:00:00 2001 From: guitavano Date: Thu, 16 Oct 2025 10:58:05 -0300 Subject: [PATCH 1/3] fix slugify for price ranges --- vtex/utils/slugify.ts | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/vtex/utils/slugify.ts b/vtex/utils/slugify.ts index 516727ba9..a26f060b2 100644 --- a/vtex/utils/slugify.ts +++ b/vtex/utils/slugify.ts @@ -2,8 +2,24 @@ const mapped = JSON.parse( `{"Á":"A","Ä":"A","Â":"A","À":"A","Ã":"A","Å":"A","Č":"C","Ç":"C","Ć":"C","Ď":"D","É":"E","Ě":"E","Ë":"E","È":"E","Ê":"E","Ẽ":"E","Ĕ":"E","Ȇ":"E","Í":"I","Ì":"I","Î":"I","Ï":"I","Ň":"N","Ñ":"N","Ó":"O","Ö":"O","Ò":"O","Ô":"O","Õ":"O","Ø":"O","Ř":"R","Ŕ":"R","Š":"S","Ť":"T","Ú":"U","Ů":"U","Ü":"U","Ù":"U","Û":"U","Ý":"Y","Ÿ":"Y","Ž":"Z","á":"a","ä":"a","â":"a","à":"a","ã":"a","å":"a","č":"c","ç":"c","ć":"c","ď":"d","é":"e","ě":"e","ë":"e","è":"e","ê":"e","ẽ":"e","ĕ":"e","ȇ":"e","í":"i","ì":"i","î":"i","ï":"i","ň":"n","ñ":"n","ó":"o","ö":"o","ò":"o","ô":"o","õ":"o","ø":"o","ð":"o","ř":"r","ŕ":"r","š":"s","ť":"t","ú":"u","ů":"u","ü":"u","ù":"u","û":"u","ý":"y","ÿ":"y","ž":"z","þ":"b","Þ":"B","Đ":"D","đ":"d","ß":"B","Æ":"A","a":"a"}`, ); -export const slugify = (str: string) => - str +export const slugify = (str: string) => { + // Check if this looks like a price range (e.g., "de-400-a-799.99") + const isPriceRange = /de-\d+([,.]?\d+)?-a-\d+([,.]?\d+)?/.test(str); + + if (isPriceRange) { + // For price ranges, preserve decimal points and only replace other special chars + return str + .replace(/,/g, "") + .replace(/[·/_:]/g, "-") // Remove dot from this regex to preserve decimals + .replace(/[*+~()'"!:@&\[\]`/ %$#?{}|><=_^]/g, "-") // Remove dot from this regex too + .split("") + .map((char) => mapped[char] ?? char) + .join("") + .toLowerCase(); + } + + // Original behavior for non-price strings + return str .replace(/,/g, "") .replace(/[·/_,:]/g, "-") .replace(/[*+~.()'"!:@&\[\]`/ %$#?{}|><=_^]/g, "-") @@ -11,3 +27,4 @@ export const slugify = (str: string) => .map((char) => mapped[char] ?? char) .join("") .toLowerCase(); +}; From 8e5480b58d378f3afdbfef51a729a35bfeeaa2dc Mon Sep 17 00:00:00 2001 From: guitavano Date: Thu, 16 Oct 2025 10:59:55 -0300 Subject: [PATCH 2/3] fmt --- google-drive/utils/query.ts | 5 +-- google-drive/utils/types.ts | 38 +++++++++---------- .../actions/conversations/archiveThread.ts | 1 - hubspot/actions/conversations/updateThread.ts | 1 - vtex/utils/slugify.ts | 8 ++-- 5 files changed, 25 insertions(+), 28 deletions(-) diff --git a/google-drive/utils/query.ts b/google-drive/utils/query.ts index 3c75632aa..f0811ac84 100644 --- a/google-drive/utils/query.ts +++ b/google-drive/utils/query.ts @@ -2,10 +2,10 @@ import { QueryCondition } from "./types.ts"; /** * Builds a Google Drive API query string from an array of query conditions. - * + * * @param queries Array of query conditions * @returns Formatted query string for Google Drive API - * + * * @example * ```typescript * const queries = [ @@ -63,4 +63,3 @@ export function buildQueryString(queries: QueryCondition[]): string { return conditionStr; }).join(" "); } - diff --git a/google-drive/utils/types.ts b/google-drive/utils/types.ts index b00d9eec4..21dd5da0d 100644 --- a/google-drive/utils/types.ts +++ b/google-drive/utils/types.ts @@ -129,12 +129,12 @@ export interface QueryCondition { * The field to filter by (e.g., 'name', 'mimeType', 'trashed') */ term: QueryTerm; - + /** * The comparison operator (e.g., '=', 'contains', '>', 'in') */ operator: QueryOperator; - + /** * The value to compare against. * - For strings: use quotes in the value if needed (e.g., 'hello') @@ -144,16 +144,16 @@ export interface QueryCondition { * - For 'has' operator (properties): object like "{ key='dept' and value='sales' }" */ value: string; - + /** * How to combine with the next condition. * - 'and': Both conditions must be true * - 'or': Either condition must be true - * + * * Omit for the last condition in the array. */ combinator?: QueryCombinator; - + /** * If true, negates this condition with 'not'. * @default false @@ -165,7 +165,7 @@ export interface SearchFilesParams { /** * Array of query conditions to filter files. * Each condition specifies a term, operator, value, and optional combinator. - * + * * Examples: * ```typescript * // Search for non-trashed image files @@ -173,73 +173,73 @@ export interface SearchFilesParams { * { term: "trashed", operator: "=", value: "false", combinator: "and" }, * { term: "mimeType", operator: "contains", value: "image/" } * ] - * + * * // Search for files named "hello" or "goodbye" * queries: [ * { term: "name", operator: "=", value: "hello", combinator: "or" }, * { term: "name", operator: "=", value: "goodbye" } * ] - * + * * // Search for Google Docs I own * queries: [ * { term: "mimeType", operator: "=", value: "application/vnd.google-apps.document", combinator: "and" }, * { term: "owners", operator: "in", value: "me" } * ] - * + * * // Search in specific folder * queries: [ * { term: "parents", operator: "in", value: "FOLDER_ID_HERE" } * ] - * + * * // Files modified after date * queries: [ * { term: "modifiedTime", operator: ">", value: "2024-01-01T12:00:00" } * ] * ``` - * + * * @see https://developers.google.com/drive/api/guides/search-files */ queries: QueryCondition[]; - + /** * Maximum number of files to return per page (1-1000). * @default 100 */ pageSize?: number; - + /** * Token for retrieving the next page of results. */ pageToken?: string; - + /** * Selector specifying which fields to include in the response. * @default "nextPageToken, files(id, name, mimeType, modifiedTime, size, webViewLink)" */ fields?: string; - + /** * Comma-separated list of spaces to query within. * Supported values: 'drive', 'appDataFolder', 'photos' * @default "drive" */ spaces?: string; - + /** * Bodies of items (files/documents) to which the query applies. * Supported values: 'user', 'domain', 'drive', 'allDrives' * @default "user" */ corpora?: string; - + /** * Sort order for the returned files. - * Examples: 'createdTime', 'folder', 'modifiedByMeTime', 'modifiedTime', + * Examples: 'createdTime', 'folder', 'modifiedByMeTime', 'modifiedTime', * 'name', 'quotaBytesUsed', 'recency', 'sharedWithMeTime', 'starred', 'viewedByMeTime' * Add 'desc' suffix for descending order: 'modifiedTime desc' */ orderBy?: string; - + /** * Whether to include items from all drives (Team Drives) in results. * @default false diff --git a/hubspot/actions/conversations/archiveThread.ts b/hubspot/actions/conversations/archiveThread.ts index 6f899c9de..a88dfd21c 100644 --- a/hubspot/actions/conversations/archiveThread.ts +++ b/hubspot/actions/conversations/archiveThread.ts @@ -26,4 +26,3 @@ export default async function archiveThread( `/conversations/v3/conversations/threads/${threadId}`, ); } - diff --git a/hubspot/actions/conversations/updateThread.ts b/hubspot/actions/conversations/updateThread.ts index 9cf055b18..da7eadc2c 100644 --- a/hubspot/actions/conversations/updateThread.ts +++ b/hubspot/actions/conversations/updateThread.ts @@ -151,4 +151,3 @@ export default async function updateThread( return response; } - diff --git a/vtex/utils/slugify.ts b/vtex/utils/slugify.ts index a26f060b2..eb19c933e 100644 --- a/vtex/utils/slugify.ts +++ b/vtex/utils/slugify.ts @@ -5,19 +5,19 @@ const mapped = JSON.parse( export const slugify = (str: string) => { // Check if this looks like a price range (e.g., "de-400-a-799.99") const isPriceRange = /de-\d+([,.]?\d+)?-a-\d+([,.]?\d+)?/.test(str); - + if (isPriceRange) { // For price ranges, preserve decimal points and only replace other special chars return str .replace(/,/g, "") - .replace(/[·/_:]/g, "-") // Remove dot from this regex to preserve decimals - .replace(/[*+~()'"!:@&\[\]`/ %$#?{}|><=_^]/g, "-") // Remove dot from this regex too + .replace(/[·/_:]/g, "-") // Remove dot from this regex to preserve decimals + .replace(/[*+~()'"!:@&\[\]`/ %$#?{}|><=_^]/g, "-") // Remove dot from this regex too .split("") .map((char) => mapped[char] ?? char) .join("") .toLowerCase(); } - + // Original behavior for non-price strings return str .replace(/,/g, "") From c96840c2ac04e3513a2e607ea8df995eccaf78ee Mon Sep 17 00:00:00 2001 From: guitavano Date: Thu, 16 Oct 2025 12:04:29 -0300 Subject: [PATCH 3/3] force hasToBeFullPath false --- vtex/loaders/legacy/productListingPage.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/vtex/loaders/legacy/productListingPage.ts b/vtex/loaders/legacy/productListingPage.ts index 46fa6ba66..ef689875f 100644 --- a/vtex/loaders/legacy/productListingPage.ts +++ b/vtex/loaders/legacy/productListingPage.ts @@ -367,6 +367,7 @@ const loader = async ( ? getFlatCategories(vtexFacets.CategoriesTrees) : {}; + const filters = Object.entries({ Departments: vtexFacets.Departments, Categories: getCategoryFacets( @@ -387,7 +388,7 @@ const loader = async ( term, filtersBehavior, props.ignoreCaseSelected, - name === "Categories", + false, ) ) .flat()