Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | 1x 1x 8x 8x 8x 1x 1x 7x 7x 7x 7x 7x 7x 1x 1x 1x 12x 12x 7x 12x 1x 12x 3x 12x 1x 12x 12x | import type { SearchAst } from '../types';
/**
* Escapes a value for use inside a Shopify Storefront search clause.
*
* @param value - The raw term word.
* @returns The escaped word (backslashes and double quotes neutralized).
* @source
*/
function escapeShopify(value: string): string {
return value.replace(/\\/g, '\\\\').replace(/"/g, '\\"');
}
/**
* Builds a `title:*word*` clause for each word in a phrase, AND-ing them so a
* multi-word phrase stays a single logical unit. Mirrors how Shopify already
* treats the bare multi-word default, keeping the candidate pool broad for the
* client-side fuzzy filter to refine.
*
* @param value - The phrase term value.
* @returns A Shopify clause string, parenthesized when it has multiple words.
* @source
*/
function termToClause(value: string): string {
const words = value.split(/\s+/).filter(Boolean);
if (words.length === 0) return '';
const clauses = words.map((word) => `title:*${escapeShopify(word)}*`);
return clauses.length === 1 ? clauses[0] : `(${clauses.join(' AND ')})`;
}
/**
* Translates a {@link SearchAst} into a Shopify Storefront search query string.
*
* @category Utils
* @group Converters
* @param ast - The parsed query tree.
* @returns A Shopify search DSL string (e.g. `title:*foo* AND (title:*bar* OR title:*baz*)`).
* @example
* ```ts
* translateAstToShopifyQuery({ type: "and",
* left: { type: "term", value: "Carbonate", phrase: false },
* right: { type: "or",
* left: { type: "term", value: "Sodium", phrase: false },
* right: { type: "term", value: "Potassium", phrase: false } } });
* // "title:*Carbonate* AND (title:*Sodium* OR title:*Potassium*)"
* ```
* @source
*/
export function translateAstToShopifyQuery(ast: SearchAst): string {
switch (ast.type) {
case 'term':
return termToClause(ast.value);
case 'and':
return `(${translateAstToShopifyQuery(ast.left)} AND ${translateAstToShopifyQuery(ast.right)})`;
case 'or':
return `(${translateAstToShopifyQuery(ast.left)} OR ${translateAstToShopifyQuery(ast.right)})`;
case 'not':
return `NOT ${translateAstToShopifyQuery(ast.operand)}`;
}
}
|