pte-interpolation-core 1.1.1 → 1.2.0
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/README.md +36 -23
- package/dist/index.cjs +4 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +6 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/__tests__/fixtures.ts +1 -3
- package/src/__tests__/getMissingVariableKeys.test.ts +88 -0
- package/src/getMissingVariableKeys.ts +10 -0
- package/src/index.ts +1 -0
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|

|
|
6
6
|
|
|
7
|
-
Framework-agnostic utilities for [Portable Text](https://portabletext.org/) variable interpolation. Extract variable keys from PTE blocks and resolve them to plain strings - with zero dependencies.
|
|
7
|
+
Framework-agnostic utilities for [Portable Text](https://portabletext.org/) variable interpolation. Extract variable keys from PTE blocks and resolve them to plain strings - with zero dependencies. Use this package when you need plain string output without a React dependency: email templates, PDF generation, Node.js scripts, SMS or push notifications, or any non-React framework (Vue, Svelte, Angular, etc.). For React rendering with rich text output, use [`pte-interpolation-react`](https://www.npmjs.com/package/pte-interpolation-react) instead - it re-exports everything from this package.
|
|
8
8
|
|
|
9
9
|
Part of [sanity-pte-interpolation](https://github.com/jordanl17/sanity-pte-interpolation). For adding variable picker inline blocks to Sanity Studio, see [`sanity-plugin-pte-interpolation`](https://www.npmjs.com/package/sanity-plugin-pte-interpolation). For React rendering with rich text output, see [`pte-interpolation-react`](https://www.npmjs.com/package/pte-interpolation-react).
|
|
10
10
|
|
|
@@ -16,18 +16,6 @@ npm install pte-interpolation-core
|
|
|
16
16
|
|
|
17
17
|
No peer dependencies required.
|
|
18
18
|
|
|
19
|
-
## When to Use
|
|
20
|
-
|
|
21
|
-
Use this package when you need plain string output from interpolated Portable Text - without a React dependency. Common use cases include:
|
|
22
|
-
|
|
23
|
-
- Email templates (server-side rendering)
|
|
24
|
-
- PDF generation
|
|
25
|
-
- Node.js scripts and background jobs
|
|
26
|
-
- SMS or push notification text
|
|
27
|
-
- Any non-React framework (Vue, Svelte, Angular, etc.)
|
|
28
|
-
|
|
29
|
-
If you are rendering in React and want rich text output, use [`pte-interpolation-react`](https://www.npmjs.com/package/pte-interpolation-react) instead - it re-exports everything from this package, so you get both APIs without installing core separately.
|
|
30
|
-
|
|
31
19
|
## Usage
|
|
32
20
|
|
|
33
21
|
### Extract variable keys
|
|
@@ -38,7 +26,7 @@ If you are rendering in React and want rich text output, use [`pte-interpolation
|
|
|
38
26
|
import {extractVariableKeys} from 'pte-interpolation-core'
|
|
39
27
|
|
|
40
28
|
const keys = extractVariableKeys(blocks)
|
|
41
|
-
// ['firstName', '
|
|
29
|
+
// ['firstName', 'vouchersRemaining']
|
|
42
30
|
```
|
|
43
31
|
|
|
44
32
|
### Interpolate to a plain string
|
|
@@ -49,10 +37,10 @@ const keys = extractVariableKeys(blocks)
|
|
|
49
37
|
import {interpolateToString} from 'pte-interpolation-core'
|
|
50
38
|
|
|
51
39
|
const text = interpolateToString(blocks, {
|
|
52
|
-
firstName: '
|
|
53
|
-
|
|
40
|
+
firstName: 'Sarah',
|
|
41
|
+
vouchersRemaining: '3',
|
|
54
42
|
})
|
|
55
|
-
// "
|
|
43
|
+
// "Hi, Sarah! You have 3 vouchers remaining."
|
|
56
44
|
```
|
|
57
45
|
|
|
58
46
|
### Custom fallback for missing values
|
|
@@ -61,23 +49,37 @@ By default, unresolved variables render as `{variableKey}` (e.g. `{firstName}`).
|
|
|
61
49
|
|
|
62
50
|
```ts
|
|
63
51
|
const text = interpolateToString(blocks, {}, (variableKey) => `[${variableKey}]`)
|
|
64
|
-
// "
|
|
52
|
+
// "Hi, [firstName]! You have [vouchersRemaining] vouchers remaining."
|
|
65
53
|
```
|
|
66
54
|
|
|
67
|
-
|
|
55
|
+
### Detect missing variables
|
|
56
|
+
|
|
57
|
+
`getMissingVariableKeys` returns the variable keys present in PTE content but absent from the provided values map - useful for validating before sending emails, notifications, or other interpolated content:
|
|
58
|
+
|
|
59
|
+
```ts
|
|
60
|
+
import {getMissingVariableKeys} from 'pte-interpolation-core'
|
|
61
|
+
|
|
62
|
+
const missing = getMissingVariableKeys(blocks, {firstName: 'Sarah'})
|
|
63
|
+
// ['vouchersRemaining']
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## Related Packages
|
|
68
67
|
|
|
69
68
|
This package handles **resolution** of variable blocks that already exist in Portable Text. To add the variable picker to Sanity Studio's Portable Text Editor, use [`sanity-plugin-pte-interpolation`](https://www.npmjs.com/package/sanity-plugin-pte-interpolation):
|
|
70
69
|
|
|
71
70
|
```ts
|
|
71
|
+
import {defineField} from 'sanity'
|
|
72
72
|
import {interpolationVariables} from 'sanity-plugin-pte-interpolation'
|
|
73
73
|
|
|
74
74
|
defineField({
|
|
75
|
-
name: '
|
|
75
|
+
name: 'message',
|
|
76
76
|
type: 'array',
|
|
77
77
|
of: [
|
|
78
78
|
interpolationVariables([
|
|
79
79
|
{id: 'firstName', name: 'First name'},
|
|
80
|
-
{id: '
|
|
80
|
+
{id: 'vouchersRemaining', name: 'Vouchers remaining'},
|
|
81
|
+
{id: 'totalVouchers', name: 'Total vouchers'},
|
|
82
|
+
{id: 'expiryDate', name: 'Expiry date'},
|
|
81
83
|
]),
|
|
82
84
|
],
|
|
83
85
|
})
|
|
@@ -91,9 +93,9 @@ Variable blocks in stored Portable Text look like this:
|
|
|
91
93
|
{
|
|
92
94
|
"_type": "block",
|
|
93
95
|
"children": [
|
|
94
|
-
{"_type": "span", "text": "
|
|
96
|
+
{"_type": "span", "text": "Hi, "},
|
|
95
97
|
{"_type": "pteInterpolationVariable", "variableKey": "firstName"},
|
|
96
|
-
{"_type": "span", "text": "
|
|
98
|
+
{"_type": "span", "text": ","}
|
|
97
99
|
]
|
|
98
100
|
}
|
|
99
101
|
```
|
|
@@ -112,6 +114,17 @@ Returns the unique variable keys from an array of PTE blocks, in first-occurrenc
|
|
|
112
114
|
|
|
113
115
|
Returns `string[]`.
|
|
114
116
|
|
|
117
|
+
### `getMissingVariableKeys(blocks, values)`
|
|
118
|
+
|
|
119
|
+
Returns the variable keys present in PTE content but absent from the provided values map. Keys are deduplicated and returned in first-occurrence order. An empty string `""` is considered a provided value.
|
|
120
|
+
|
|
121
|
+
| Parameter | Type | Description |
|
|
122
|
+
| --------- | ------------------------- | ----------------------------------- |
|
|
123
|
+
| `blocks` | `PortableTextBlockLike[]` | Portable Text blocks to scan |
|
|
124
|
+
| `values` | `Record<string, string>` | Map of variable IDs to their values |
|
|
125
|
+
|
|
126
|
+
Returns `string[]`.
|
|
127
|
+
|
|
115
128
|
### `interpolateToString(blocks, values, fallback?)`
|
|
116
129
|
|
|
117
130
|
Resolves PTE blocks to a plain string, replacing variable blocks with the corresponding values. Multiple blocks are joined with newlines.
|
package/dist/index.cjs
CHANGED
|
@@ -9,6 +9,9 @@ function extractVariableKeys(blocks) {
|
|
|
9
9
|
return typeof variableKey != "string" || seen.has(variableKey) ? accumulated : (seen.add(variableKey), [...accumulated, variableKey]);
|
|
10
10
|
}, keys), []);
|
|
11
11
|
}
|
|
12
|
+
function getMissingVariableKeys(blocks, values) {
|
|
13
|
+
return extractVariableKeys(blocks).filter((key) => values[key] === void 0);
|
|
14
|
+
}
|
|
12
15
|
function defaultFallback(variableKey) {
|
|
13
16
|
return `{${variableKey}}`;
|
|
14
17
|
}
|
|
@@ -24,5 +27,6 @@ function interpolateToString(blocks, values, fallback = defaultFallback) {
|
|
|
24
27
|
}
|
|
25
28
|
exports.VARIABLE_TYPE_PREFIX = VARIABLE_TYPE_PREFIX;
|
|
26
29
|
exports.extractVariableKeys = extractVariableKeys;
|
|
30
|
+
exports.getMissingVariableKeys = getMissingVariableKeys;
|
|
27
31
|
exports.interpolateToString = interpolateToString;
|
|
28
32
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","sources":["../src/constants.ts","../src/extractVariableKeys.ts","../src/interpolateToString.ts"],"sourcesContent":["/** @public */\nexport const VARIABLE_TYPE_PREFIX = 'pteInterpolationVariable'\n","import {VARIABLE_TYPE_PREFIX} from './constants'\nimport type {PortableTextBlockLike} from './types'\n\n/** @public */\nexport function extractVariableKeys(blocks: PortableTextBlockLike[]): string[] {\n const seen = new Set<string>()\n\n return blocks.reduce<string[]>((keys, block) => {\n const children = block.children ?? []\n\n return children.reduce((accumulated, child) => {\n if (child._type !== VARIABLE_TYPE_PREFIX) return accumulated\n\n const variableKey = child.variableKey\n if (typeof variableKey !== 'string') return accumulated\n if (seen.has(variableKey)) return accumulated\n\n seen.add(variableKey)\n return [...accumulated, variableKey]\n }, keys)\n }, [])\n}\n","import {VARIABLE_TYPE_PREFIX} from './constants'\nimport type {InterpolationFallback, InterpolationValues, PortableTextBlockLike} from './types'\n\nfunction defaultFallback(variableKey: string): string {\n return `{${variableKey}}`\n}\n\n/** @public */\nexport function interpolateToString(\n blocks: PortableTextBlockLike[],\n values: InterpolationValues,\n fallback: InterpolationFallback = defaultFallback,\n): string {\n return blocks\n .map((block) => {\n const children = block.children ?? []\n\n return children\n .map((child) => {\n if (child._type === VARIABLE_TYPE_PREFIX) {\n const variableKey = child.variableKey as string\n return values[variableKey] !== undefined ? values[variableKey] : fallback(variableKey)\n }\n\n return typeof child.text === 'string' ? child.text : ''\n })\n .join('')\n })\n .join('\\n')\n}\n"],"names":[],"mappings":";;AACO,MAAM,uBAAuB;ACG7B,SAAS,oBAAoB,QAA2C;AAC7E,QAAM,2BAAW,IAAA;AAEjB,SAAO,OAAO,OAAiB,CAAC,MAAM,WACnB,MAAM,YAAY,CAAA,GAEnB,OAAO,CAAC,aAAa,UAAU;AAC7C,QAAI,MAAM,UAAU,qBAAsB,QAAO;AAEjD,UAAM,cAAc,MAAM;AAE1B,WADI,OAAO,eAAgB,YACvB,KAAK,IAAI,WAAW,IAAU,eAElC,KAAK,IAAI,WAAW,GACb,CAAC,GAAG,aAAa,WAAW;AAAA,EACrC,GAAG,IAAI,GACN,EAAE;AACP;
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../src/constants.ts","../src/extractVariableKeys.ts","../src/getMissingVariableKeys.ts","../src/interpolateToString.ts"],"sourcesContent":["/** @public */\nexport const VARIABLE_TYPE_PREFIX = 'pteInterpolationVariable'\n","import {VARIABLE_TYPE_PREFIX} from './constants'\nimport type {PortableTextBlockLike} from './types'\n\n/** @public */\nexport function extractVariableKeys(blocks: PortableTextBlockLike[]): string[] {\n const seen = new Set<string>()\n\n return blocks.reduce<string[]>((keys, block) => {\n const children = block.children ?? []\n\n return children.reduce((accumulated, child) => {\n if (child._type !== VARIABLE_TYPE_PREFIX) return accumulated\n\n const variableKey = child.variableKey\n if (typeof variableKey !== 'string') return accumulated\n if (seen.has(variableKey)) return accumulated\n\n seen.add(variableKey)\n return [...accumulated, variableKey]\n }, keys)\n }, [])\n}\n","import {extractVariableKeys} from './extractVariableKeys'\nimport type {InterpolationValues, PortableTextBlockLike} from './types'\n\n/** @public */\nexport function getMissingVariableKeys(\n blocks: PortableTextBlockLike[],\n values: InterpolationValues,\n): string[] {\n return extractVariableKeys(blocks).filter((key) => values[key] === undefined)\n}\n","import {VARIABLE_TYPE_PREFIX} from './constants'\nimport type {InterpolationFallback, InterpolationValues, PortableTextBlockLike} from './types'\n\nfunction defaultFallback(variableKey: string): string {\n return `{${variableKey}}`\n}\n\n/** @public */\nexport function interpolateToString(\n blocks: PortableTextBlockLike[],\n values: InterpolationValues,\n fallback: InterpolationFallback = defaultFallback,\n): string {\n return blocks\n .map((block) => {\n const children = block.children ?? []\n\n return children\n .map((child) => {\n if (child._type === VARIABLE_TYPE_PREFIX) {\n const variableKey = child.variableKey as string\n return values[variableKey] !== undefined ? values[variableKey] : fallback(variableKey)\n }\n\n return typeof child.text === 'string' ? child.text : ''\n })\n .join('')\n })\n .join('\\n')\n}\n"],"names":[],"mappings":";;AACO,MAAM,uBAAuB;ACG7B,SAAS,oBAAoB,QAA2C;AAC7E,QAAM,2BAAW,IAAA;AAEjB,SAAO,OAAO,OAAiB,CAAC,MAAM,WACnB,MAAM,YAAY,CAAA,GAEnB,OAAO,CAAC,aAAa,UAAU;AAC7C,QAAI,MAAM,UAAU,qBAAsB,QAAO;AAEjD,UAAM,cAAc,MAAM;AAE1B,WADI,OAAO,eAAgB,YACvB,KAAK,IAAI,WAAW,IAAU,eAElC,KAAK,IAAI,WAAW,GACb,CAAC,GAAG,aAAa,WAAW;AAAA,EACrC,GAAG,IAAI,GACN,EAAE;AACP;ACjBO,SAAS,uBACd,QACA,QACU;AACV,SAAO,oBAAoB,MAAM,EAAE,OAAO,CAAC,QAAQ,OAAO,GAAG,MAAM,MAAS;AAC9E;ACNA,SAAS,gBAAgB,aAA6B;AACpD,SAAO,IAAI,WAAW;AACxB;AAGO,SAAS,oBACd,QACA,QACA,WAAkC,iBAC1B;AACR,SAAO,OACJ,IAAI,CAAC,WACa,MAAM,YAAY,CAAA,GAGhC,IAAI,CAAC,UAAU;AACd,QAAI,MAAM,UAAU,sBAAsB;AACxC,YAAM,cAAc,MAAM;AAC1B,aAAO,OAAO,WAAW,MAAM,SAAY,OAAO,WAAW,IAAI,SAAS,WAAW;AAAA,IACvF;AAEA,WAAO,OAAO,MAAM,QAAS,WAAW,MAAM,OAAO;AAAA,EACvD,CAAC,EACA,KAAK,EAAE,CACX,EACA,KAAK;AAAA,CAAI;AACd;;;;;"}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
/** @public */
|
|
2
2
|
export declare function extractVariableKeys(blocks: PortableTextBlockLike[]): string[]
|
|
3
3
|
|
|
4
|
+
/** @public */
|
|
5
|
+
export declare function getMissingVariableKeys(
|
|
6
|
+
blocks: PortableTextBlockLike[],
|
|
7
|
+
values: InterpolationValues,
|
|
8
|
+
): string[]
|
|
9
|
+
|
|
4
10
|
/** @public */
|
|
5
11
|
export declare function interpolateToString(
|
|
6
12
|
blocks: PortableTextBlockLike[],
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
/** @public */
|
|
2
2
|
export declare function extractVariableKeys(blocks: PortableTextBlockLike[]): string[]
|
|
3
3
|
|
|
4
|
+
/** @public */
|
|
5
|
+
export declare function getMissingVariableKeys(
|
|
6
|
+
blocks: PortableTextBlockLike[],
|
|
7
|
+
values: InterpolationValues,
|
|
8
|
+
): string[]
|
|
9
|
+
|
|
4
10
|
/** @public */
|
|
5
11
|
export declare function interpolateToString(
|
|
6
12
|
blocks: PortableTextBlockLike[],
|
package/dist/index.js
CHANGED
|
@@ -7,6 +7,9 @@ function extractVariableKeys(blocks) {
|
|
|
7
7
|
return typeof variableKey != "string" || seen.has(variableKey) ? accumulated : (seen.add(variableKey), [...accumulated, variableKey]);
|
|
8
8
|
}, keys), []);
|
|
9
9
|
}
|
|
10
|
+
function getMissingVariableKeys(blocks, values) {
|
|
11
|
+
return extractVariableKeys(blocks).filter((key) => values[key] === void 0);
|
|
12
|
+
}
|
|
10
13
|
function defaultFallback(variableKey) {
|
|
11
14
|
return `{${variableKey}}`;
|
|
12
15
|
}
|
|
@@ -23,6 +26,7 @@ function interpolateToString(blocks, values, fallback = defaultFallback) {
|
|
|
23
26
|
export {
|
|
24
27
|
VARIABLE_TYPE_PREFIX,
|
|
25
28
|
extractVariableKeys,
|
|
29
|
+
getMissingVariableKeys,
|
|
26
30
|
interpolateToString
|
|
27
31
|
};
|
|
28
32
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../src/constants.ts","../src/extractVariableKeys.ts","../src/interpolateToString.ts"],"sourcesContent":["/** @public */\nexport const VARIABLE_TYPE_PREFIX = 'pteInterpolationVariable'\n","import {VARIABLE_TYPE_PREFIX} from './constants'\nimport type {PortableTextBlockLike} from './types'\n\n/** @public */\nexport function extractVariableKeys(blocks: PortableTextBlockLike[]): string[] {\n const seen = new Set<string>()\n\n return blocks.reduce<string[]>((keys, block) => {\n const children = block.children ?? []\n\n return children.reduce((accumulated, child) => {\n if (child._type !== VARIABLE_TYPE_PREFIX) return accumulated\n\n const variableKey = child.variableKey\n if (typeof variableKey !== 'string') return accumulated\n if (seen.has(variableKey)) return accumulated\n\n seen.add(variableKey)\n return [...accumulated, variableKey]\n }, keys)\n }, [])\n}\n","import {VARIABLE_TYPE_PREFIX} from './constants'\nimport type {InterpolationFallback, InterpolationValues, PortableTextBlockLike} from './types'\n\nfunction defaultFallback(variableKey: string): string {\n return `{${variableKey}}`\n}\n\n/** @public */\nexport function interpolateToString(\n blocks: PortableTextBlockLike[],\n values: InterpolationValues,\n fallback: InterpolationFallback = defaultFallback,\n): string {\n return blocks\n .map((block) => {\n const children = block.children ?? []\n\n return children\n .map((child) => {\n if (child._type === VARIABLE_TYPE_PREFIX) {\n const variableKey = child.variableKey as string\n return values[variableKey] !== undefined ? values[variableKey] : fallback(variableKey)\n }\n\n return typeof child.text === 'string' ? child.text : ''\n })\n .join('')\n })\n .join('\\n')\n}\n"],"names":[],"mappings":"AACO,MAAM,uBAAuB;ACG7B,SAAS,oBAAoB,QAA2C;AAC7E,QAAM,2BAAW,IAAA;AAEjB,SAAO,OAAO,OAAiB,CAAC,MAAM,WACnB,MAAM,YAAY,CAAA,GAEnB,OAAO,CAAC,aAAa,UAAU;AAC7C,QAAI,MAAM,UAAU,qBAAsB,QAAO;AAEjD,UAAM,cAAc,MAAM;AAE1B,WADI,OAAO,eAAgB,YACvB,KAAK,IAAI,WAAW,IAAU,eAElC,KAAK,IAAI,WAAW,GACb,CAAC,GAAG,aAAa,WAAW;AAAA,EACrC,GAAG,IAAI,GACN,EAAE;AACP;
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/constants.ts","../src/extractVariableKeys.ts","../src/getMissingVariableKeys.ts","../src/interpolateToString.ts"],"sourcesContent":["/** @public */\nexport const VARIABLE_TYPE_PREFIX = 'pteInterpolationVariable'\n","import {VARIABLE_TYPE_PREFIX} from './constants'\nimport type {PortableTextBlockLike} from './types'\n\n/** @public */\nexport function extractVariableKeys(blocks: PortableTextBlockLike[]): string[] {\n const seen = new Set<string>()\n\n return blocks.reduce<string[]>((keys, block) => {\n const children = block.children ?? []\n\n return children.reduce((accumulated, child) => {\n if (child._type !== VARIABLE_TYPE_PREFIX) return accumulated\n\n const variableKey = child.variableKey\n if (typeof variableKey !== 'string') return accumulated\n if (seen.has(variableKey)) return accumulated\n\n seen.add(variableKey)\n return [...accumulated, variableKey]\n }, keys)\n }, [])\n}\n","import {extractVariableKeys} from './extractVariableKeys'\nimport type {InterpolationValues, PortableTextBlockLike} from './types'\n\n/** @public */\nexport function getMissingVariableKeys(\n blocks: PortableTextBlockLike[],\n values: InterpolationValues,\n): string[] {\n return extractVariableKeys(blocks).filter((key) => values[key] === undefined)\n}\n","import {VARIABLE_TYPE_PREFIX} from './constants'\nimport type {InterpolationFallback, InterpolationValues, PortableTextBlockLike} from './types'\n\nfunction defaultFallback(variableKey: string): string {\n return `{${variableKey}}`\n}\n\n/** @public */\nexport function interpolateToString(\n blocks: PortableTextBlockLike[],\n values: InterpolationValues,\n fallback: InterpolationFallback = defaultFallback,\n): string {\n return blocks\n .map((block) => {\n const children = block.children ?? []\n\n return children\n .map((child) => {\n if (child._type === VARIABLE_TYPE_PREFIX) {\n const variableKey = child.variableKey as string\n return values[variableKey] !== undefined ? values[variableKey] : fallback(variableKey)\n }\n\n return typeof child.text === 'string' ? child.text : ''\n })\n .join('')\n })\n .join('\\n')\n}\n"],"names":[],"mappings":"AACO,MAAM,uBAAuB;ACG7B,SAAS,oBAAoB,QAA2C;AAC7E,QAAM,2BAAW,IAAA;AAEjB,SAAO,OAAO,OAAiB,CAAC,MAAM,WACnB,MAAM,YAAY,CAAA,GAEnB,OAAO,CAAC,aAAa,UAAU;AAC7C,QAAI,MAAM,UAAU,qBAAsB,QAAO;AAEjD,UAAM,cAAc,MAAM;AAE1B,WADI,OAAO,eAAgB,YACvB,KAAK,IAAI,WAAW,IAAU,eAElC,KAAK,IAAI,WAAW,GACb,CAAC,GAAG,aAAa,WAAW;AAAA,EACrC,GAAG,IAAI,GACN,EAAE;AACP;ACjBO,SAAS,uBACd,QACA,QACU;AACV,SAAO,oBAAoB,MAAM,EAAE,OAAO,CAAC,QAAQ,OAAO,GAAG,MAAM,MAAS;AAC9E;ACNA,SAAS,gBAAgB,aAA6B;AACpD,SAAO,IAAI,WAAW;AACxB;AAGO,SAAS,oBACd,QACA,QACA,WAAkC,iBAC1B;AACR,SAAO,OACJ,IAAI,CAAC,WACa,MAAM,YAAY,CAAA,GAGhC,IAAI,CAAC,UAAU;AACd,QAAI,MAAM,UAAU,sBAAsB;AACxC,YAAM,cAAc,MAAM;AAC1B,aAAO,OAAO,WAAW,MAAM,SAAY,OAAO,WAAW,IAAI,SAAS,WAAW;AAAA,IACvF;AAEA,WAAO,OAAO,MAAM,QAAS,WAAW,MAAM,OAAO;AAAA,EACvD,CAAC,EACA,KAAK,EAAE,CACX,EACA,KAAK;AAAA,CAAI;AACd;"}
|
package/package.json
CHANGED
|
@@ -85,9 +85,7 @@ export const blockWithNonStringVariableKey: PortableTextBlockLike[] = [
|
|
|
85
85
|
{
|
|
86
86
|
_type: 'block',
|
|
87
87
|
_key: 'block-1',
|
|
88
|
-
children: [
|
|
89
|
-
{_type: 'pteInterpolationVariable', _key: 'var-1', variableKey: 123 as unknown as string},
|
|
90
|
-
],
|
|
88
|
+
children: [{_type: 'pteInterpolationVariable', _key: 'var-1', variableKey: 123} as never],
|
|
91
89
|
},
|
|
92
90
|
]
|
|
93
91
|
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import {describe, expect, it} from 'vitest'
|
|
2
|
+
import {getMissingVariableKeys} from '../getMissingVariableKeys'
|
|
3
|
+
import {
|
|
4
|
+
blockWithNoChildren,
|
|
5
|
+
blockWithNonStringVariableKey,
|
|
6
|
+
consecutiveVariablesBlock,
|
|
7
|
+
duplicateVariableBlock,
|
|
8
|
+
emptyBlocksContent,
|
|
9
|
+
multiBlockContent,
|
|
10
|
+
multipleVariablesBlock,
|
|
11
|
+
plainTextBlock,
|
|
12
|
+
singleVariableBlock,
|
|
13
|
+
} from './fixtures'
|
|
14
|
+
|
|
15
|
+
describe('getMissingVariableKeys', () => {
|
|
16
|
+
it('returns empty array for empty blocks', () => {
|
|
17
|
+
expect(getMissingVariableKeys(emptyBlocksContent, {})).toEqual([])
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
it('returns empty array when no variables exist', () => {
|
|
21
|
+
expect(getMissingVariableKeys(plainTextBlock, {})).toEqual([])
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
it('returns empty array when all variables provided', () => {
|
|
25
|
+
expect(getMissingVariableKeys(singleVariableBlock, {firstName: 'Alice'})).toEqual([])
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
it('returns empty array when all multiple variables provided', () => {
|
|
29
|
+
expect(
|
|
30
|
+
getMissingVariableKeys(multipleVariablesBlock, {
|
|
31
|
+
firstName: 'Alice',
|
|
32
|
+
lastName: 'Smith',
|
|
33
|
+
email: 'a@b.com',
|
|
34
|
+
}),
|
|
35
|
+
).toEqual([])
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
it('returns missing key when value not provided', () => {
|
|
39
|
+
expect(getMissingVariableKeys(singleVariableBlock, {})).toEqual(['firstName'])
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
it('returns only missing keys when some values provided', () => {
|
|
43
|
+
expect(getMissingVariableKeys(multipleVariablesBlock, {firstName: 'Alice'})).toEqual([
|
|
44
|
+
'lastName',
|
|
45
|
+
'email',
|
|
46
|
+
])
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
it('does not treat empty string as missing', () => {
|
|
50
|
+
expect(getMissingVariableKeys(singleVariableBlock, {firstName: ''})).toEqual([])
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
it('returns missing keys across multiple blocks', () => {
|
|
54
|
+
expect(getMissingVariableKeys(multiBlockContent, {firstName: 'Alice'})).toEqual(['email'])
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
it('deduplicates missing keys', () => {
|
|
58
|
+
expect(getMissingVariableKeys(duplicateVariableBlock, {})).toEqual(['firstName'])
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
it('handles blocks with no children property', () => {
|
|
62
|
+
expect(getMissingVariableKeys(blockWithNoChildren, {})).toEqual([])
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
it('skips children with non-string variableKey', () => {
|
|
66
|
+
expect(getMissingVariableKeys(blockWithNonStringVariableKey, {})).toEqual([])
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
it('returns missing keys for consecutive variables', () => {
|
|
70
|
+
expect(getMissingVariableKeys(consecutiveVariablesBlock, {firstName: 'Alice'})).toEqual([
|
|
71
|
+
'lastName',
|
|
72
|
+
])
|
|
73
|
+
})
|
|
74
|
+
|
|
75
|
+
it('ignores extra values not in blocks', () => {
|
|
76
|
+
expect(
|
|
77
|
+
getMissingVariableKeys(singleVariableBlock, {firstName: 'Alice', extraKey: 'ignored'}),
|
|
78
|
+
).toEqual([])
|
|
79
|
+
})
|
|
80
|
+
|
|
81
|
+
it('preserves first-occurrence order of missing keys', () => {
|
|
82
|
+
expect(getMissingVariableKeys(multipleVariablesBlock, {})).toEqual([
|
|
83
|
+
'firstName',
|
|
84
|
+
'lastName',
|
|
85
|
+
'email',
|
|
86
|
+
])
|
|
87
|
+
})
|
|
88
|
+
})
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import {extractVariableKeys} from './extractVariableKeys'
|
|
2
|
+
import type {InterpolationValues, PortableTextBlockLike} from './types'
|
|
3
|
+
|
|
4
|
+
/** @public */
|
|
5
|
+
export function getMissingVariableKeys(
|
|
6
|
+
blocks: PortableTextBlockLike[],
|
|
7
|
+
values: InterpolationValues,
|
|
8
|
+
): string[] {
|
|
9
|
+
return extractVariableKeys(blocks).filter((key) => values[key] === undefined)
|
|
10
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export {VARIABLE_TYPE_PREFIX} from './constants'
|
|
2
2
|
export {extractVariableKeys} from './extractVariableKeys'
|
|
3
|
+
export {getMissingVariableKeys} from './getMissingVariableKeys'
|
|
3
4
|
export {interpolateToString} from './interpolateToString'
|
|
4
5
|
export type {
|
|
5
6
|
InterpolationFallback,
|