vite-plugin-react-shopify 2.1.1 → 2.2.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/index.js CHANGED
@@ -590,6 +590,21 @@ function pathToFileURL(filePath) {
590
590
  return "file://" + absPath;
591
591
  }
592
592
  var log6 = logger("ssg:renderer");
593
+ var DEFAULT_LIQUID_FILTERS = {
594
+ textarea: " | newline_to_br",
595
+ image_picker: " | img_url: 'master'"
596
+ };
597
+ function buildLiquidFilterMap(settings, prefix) {
598
+ const map = {};
599
+ if (!settings) return map;
600
+ for (const s of settings) {
601
+ const filter = DEFAULT_LIQUID_FILTERS[s.type];
602
+ if (filter) {
603
+ map[`${prefix}${s.id}`] = filter;
604
+ }
605
+ }
606
+ return map;
607
+ }
593
608
  function renderEntry(tmpFile, entry, projectRoot) {
594
609
  return import(pathToFileURL(tmpFile)).then((mod) => {
595
610
  const Component = mod.default;
@@ -612,11 +627,15 @@ function renderEntry(tmpFile, entry, projectRoot) {
612
627
  return null;
613
628
  }
614
629
  globalThis.__shopify_ssg_target = entry.targetType;
630
+ const prefix = entry.targetType === "block" ? "block.settings." : "section.settings.";
631
+ const filterMap = buildLiquidFilterMap(shopifyMeta?.settings, prefix);
632
+ globalThis.__shopify_ssg_liquid_filters = filterMap;
615
633
  const trackedExpressions = /* @__PURE__ */ new Set();
616
634
  globalThis.__shopify_ssg_liquid_track = trackedExpressions;
617
635
  const element = createElement(Component);
618
636
  let html = renderToStaticMarkup(element);
619
637
  delete globalThis.__shopify_ssg_liquid_track;
638
+ delete globalThis.__shopify_ssg_liquid_filters;
620
639
  html = normalizeVoidElements(html);
621
640
  html = normalizeStyleAttributes(html);
622
641
  html = unwrapHtmlEntities(html);
@@ -992,7 +1011,7 @@ function shopifySSG(options) {
992
1011
  if (id === "\0vite-plugin-shopify:runtime") {
993
1012
  const exports = [
994
1013
  `export { LiquidDataProvider, LiquidDataContext } from 'vite-plugin-shopify/runtime'`,
995
- `export { useLiquid, useLiquidValues, useSectionSettings, useBlockSettings, useSnippetParams, useBlockParams } from 'vite-plugin-shopify/runtime'`
1014
+ `export { useLiquidValue, useLiquidValues, useSectionSettings, useBlockSettings, useSnippetParams, useBlockParams } from 'vite-plugin-shopify/runtime'`
996
1015
  ];
997
1016
  return exports.join("\n");
998
1017
  }
@@ -1,13 +1,21 @@
1
1
  import * as react from 'react';
2
2
 
3
- declare function useLiquid(expr: string): {
4
- value: string | undefined;
5
- };
6
- declare function useLiquidValues<T extends Record<string, string>>(map: T): {
7
- values: {
8
- [K in keyof T]: string | undefined;
9
- };
3
+ declare function parseLiquidBoolean(value: string | boolean | undefined | null): boolean;
4
+ declare function parseLiquidNumber(value: string | number | undefined | null, defaultVal?: number): number;
5
+ type LiquidTypeMode = "string" | "number" | "boolean";
6
+ type Setter<T> = (val: T | ((prev: T) => T)) => void;
7
+ type ValueForMode<M extends LiquidTypeMode | undefined> = M extends "number" ? number : M extends "boolean" ? boolean : string | undefined;
8
+ declare function useLiquidValue(expr: string): [string | undefined, Setter<string | undefined>];
9
+ declare function useLiquidValue(expr: string, type: "string"): [string | undefined, Setter<string | undefined>];
10
+ declare function useLiquidValue(expr: string, type: "number"): [number, Setter<number>];
11
+ declare function useLiquidValue(expr: string, type: "boolean"): [boolean, Setter<boolean>];
12
+ type TypeModes<T extends Record<string, string>> = Partial<{
13
+ [K in keyof T & string]: LiquidTypeMode;
14
+ }>;
15
+ type InferValues<T extends Record<string, string>, Types extends TypeModes<T>> = {
16
+ [K in keyof T & string]: ValueForMode<Types[K]>;
10
17
  };
18
+ declare function useLiquidValues<T extends Record<string, string>, const Types extends TypeModes<T> = {}>(map: T, types?: Types): InferValues<T, Types>;
11
19
  declare function useSectionSettings(key: string): {
12
20
  value: string | undefined;
13
21
  };
@@ -21,12 +29,7 @@ declare function useBlockParams(key: string): {
21
29
  value: string | undefined;
22
30
  };
23
31
 
24
- /** SSR-safe boolean parser: treats Liquid expression strings as truthy, real booleans as-is */
25
- declare function parseLiquidBoolean(value: string | boolean | undefined | null): boolean;
26
- /** SSR-safe number parser: returns defaultVal for unparseable SSR placeholders */
27
- declare function parseLiquidNumber(value: string | number | undefined | null, defaultVal?: number): number;
28
-
29
32
  declare const LiquidDataContext: react.Context<Record<string, any>>;
30
33
  declare const LiquidDataProvider: react.Provider<Record<string, any>>;
31
34
 
32
- export { LiquidDataContext, LiquidDataProvider, parseLiquidBoolean, parseLiquidNumber, useBlockParams, useBlockSettings, useLiquid, useLiquidValues, useSectionSettings, useSnippetParams };
35
+ export { LiquidDataContext, LiquidDataProvider, type LiquidTypeMode, parseLiquidBoolean, parseLiquidNumber, useBlockParams, useBlockSettings, useLiquidValue, useLiquidValues, useSectionSettings, useSnippetParams };
@@ -1,5 +1,5 @@
1
1
  // src/runtime/hooks.ts
2
- import { useContext } from "react";
2
+ import { useContext, useEffect, useState } from "react";
3
3
 
4
4
  // src/runtime/provider.ts
5
5
  import { createContext } from "react";
@@ -7,46 +7,40 @@ var LiquidDataContext = createContext({});
7
7
  var LiquidDataProvider = LiquidDataContext.Provider;
8
8
 
9
9
  // src/runtime/hooks.ts
10
- function useLiquid(expr) {
10
+ function getLiquidFilter(expr) {
11
+ const filterMap = globalThis.__shopify_ssg_liquid_filters;
12
+ return filterMap?.[expr] ?? "";
13
+ }
14
+ function useLiquidRaw(expr) {
11
15
  const data = useContext(LiquidDataContext);
12
16
  if (typeof globalThis.document === "undefined") {
13
17
  const tracker = globalThis.__shopify_ssg_liquid_track;
14
18
  if (tracker) tracker.add(expr);
15
- return { value: `{{ ${expr} }}` };
19
+ const filter = getLiquidFilter(expr);
20
+ return `{{ ${expr}${filter} }}`;
16
21
  }
17
22
  if (Object.prototype.hasOwnProperty.call(data, expr)) {
18
- return { value: data[expr] };
23
+ return data[expr];
19
24
  }
20
- return { value: void 0 };
25
+ return void 0;
21
26
  }
22
- function useLiquidValues(map) {
27
+ function useLiquidRawValues(map) {
23
28
  const data = useContext(LiquidDataContext);
24
29
  if (typeof globalThis.document === "undefined") {
25
30
  const tracker = globalThis.__shopify_ssg_liquid_track;
26
31
  const values2 = {};
27
32
  for (const [key, expr] of Object.entries(map)) {
28
33
  if (tracker) tracker.add(expr);
29
- values2[key] = `{{ ${expr} }}`;
34
+ const filter = getLiquidFilter(expr);
35
+ values2[key] = `{{ ${expr}${filter} }}`;
30
36
  }
31
- return { values: values2 };
37
+ return values2;
32
38
  }
33
39
  const values = {};
34
40
  for (const [key, expr] of Object.entries(map)) {
35
41
  values[key] = Object.prototype.hasOwnProperty.call(data, expr) ? data[expr] : void 0;
36
42
  }
37
- return { values };
38
- }
39
- function useSectionSettings(key) {
40
- return useLiquid(`section.settings.${key}`);
41
- }
42
- function useBlockSettings(key) {
43
- return useLiquid(`block.settings.${key}`);
44
- }
45
- function useSnippetParams(key) {
46
- return useLiquid(key);
47
- }
48
- function useBlockParams(key) {
49
- return useLiquid(key);
43
+ return values;
50
44
  }
51
45
  function parseLiquidBoolean(value) {
52
46
  if (typeof value === "boolean") return value;
@@ -59,6 +53,76 @@ function parseLiquidNumber(value, defaultVal = 0) {
59
53
  const num = Number(value);
60
54
  return Number.isNaN(num) ? defaultVal : num;
61
55
  }
56
+ function useLiquidValue(expr, type = "string") {
57
+ const raw = useLiquidRaw(expr);
58
+ const isSSR = typeof globalThis.document === "undefined";
59
+ let initialVal;
60
+ if (type === "boolean") {
61
+ initialVal = false;
62
+ } else if (type === "number") {
63
+ initialVal = isSSR ? raw : parseLiquidNumber(raw, 0);
64
+ } else {
65
+ initialVal = raw;
66
+ }
67
+ const [val, setVal] = useState(initialVal);
68
+ useEffect(() => {
69
+ if (type === "number") setVal(parseLiquidNumber(raw, 0));
70
+ else if (type === "boolean") setVal(parseLiquidBoolean(raw));
71
+ else setVal(raw);
72
+ }, [raw]);
73
+ return [val, setVal];
74
+ }
75
+ function useLiquidValues(map, types) {
76
+ const raw = useLiquidRawValues(map);
77
+ const keys = Object.keys(map);
78
+ const rawDep = keys.map((k) => raw[k]).join("\0");
79
+ const isSSR = typeof globalThis.document === "undefined";
80
+ const [parsed, setParsed] = useState(() => {
81
+ const vals = {};
82
+ for (const k of keys) {
83
+ const mode = types?.[k] ?? "string";
84
+ if (mode === "boolean") {
85
+ vals[k] = false;
86
+ } else if (mode === "number") {
87
+ vals[k] = isSSR ? raw[k] : parseLiquidNumber(raw[k], 0);
88
+ } else {
89
+ vals[k] = raw[k];
90
+ }
91
+ }
92
+ return vals;
93
+ });
94
+ useEffect(() => {
95
+ setParsed((prev) => {
96
+ let changed = false;
97
+ const next = { ...prev };
98
+ for (const k of keys) {
99
+ const mode = types?.[k] ?? "string";
100
+ let v;
101
+ if (mode === "number") v = parseLiquidNumber(raw[k], 0);
102
+ else if (mode === "boolean") v = parseLiquidBoolean(raw[k]);
103
+ else v = raw[k];
104
+ if (v !== prev[k]) {
105
+ next[k] = v;
106
+ changed = true;
107
+ }
108
+ }
109
+ return changed ? next : prev;
110
+ });
111
+ }, [rawDep]);
112
+ return parsed;
113
+ }
114
+ function useSectionSettings(key) {
115
+ return { value: useLiquidRaw(`section.settings.${key}`) };
116
+ }
117
+ function useBlockSettings(key) {
118
+ return { value: useLiquidRaw(`block.settings.${key}`) };
119
+ }
120
+ function useSnippetParams(key) {
121
+ return { value: useLiquidRaw(key) };
122
+ }
123
+ function useBlockParams(key) {
124
+ return { value: useLiquidRaw(key) };
125
+ }
62
126
  export {
63
127
  LiquidDataContext,
64
128
  LiquidDataProvider,
@@ -66,7 +130,7 @@ export {
66
130
  parseLiquidNumber,
67
131
  useBlockParams,
68
132
  useBlockSettings,
69
- useLiquid,
133
+ useLiquidValue,
70
134
  useLiquidValues,
71
135
  useSectionSettings,
72
136
  useSnippetParams
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vite-plugin-react-shopify",
3
- "version": "2.1.1",
3
+ "version": "2.2.1",
4
4
  "description": "Vite plugin for React Shopify themes",
5
5
  "files": [
6
6
  "dist"