@pdfme/schemas 6.1.1 → 6.1.2-dev.3

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.
Files changed (60) hide show
  1. package/dist/box.d.ts +45 -0
  2. package/dist/{builtins-CWHhKSVA.js → builtins-BB2DHceW.js} +482 -548
  3. package/dist/builtins-BB2DHceW.js.map +1 -0
  4. package/dist/builtins.d.ts +1 -1
  5. package/dist/builtins.js +1 -1
  6. package/dist/checkbox/index.d.ts +2 -2
  7. package/dist/dynamicLayout.d.ts +4 -0
  8. package/dist/dynamicLayout.js +20 -0
  9. package/dist/dynamicLayout.js.map +1 -0
  10. package/dist/{dynamicTemplate-DmuRoTw4.js → dynamicTemplate-B4GCNLF9.js} +19 -53
  11. package/dist/dynamicTemplate-B4GCNLF9.js.map +1 -0
  12. package/dist/{lists-B6dmgpkS.js → dynamicTemplate-BwzF9C1L.js} +3 -6
  13. package/dist/dynamicTemplate-BwzF9C1L.js.map +1 -0
  14. package/dist/dynamicTemplate-C7MdZxPm.js +75 -0
  15. package/dist/dynamicTemplate-C7MdZxPm.js.map +1 -0
  16. package/dist/graphics/image.d.ts +1 -1
  17. package/dist/graphics/signature.d.ts +1 -1
  18. package/dist/helper-CEme39Uo.js +40 -0
  19. package/dist/helper-CEme39Uo.js.map +1 -0
  20. package/dist/index.d.ts +1 -0
  21. package/dist/index.js +268 -102
  22. package/dist/index.js.map +1 -1
  23. package/dist/list/types.d.ts +0 -5
  24. package/dist/lists.d.ts +2 -1
  25. package/dist/lists.js +3 -2
  26. package/dist/measure-L5diay3k.js +612 -0
  27. package/dist/measure-L5diay3k.js.map +1 -0
  28. package/dist/multiVariableText/dynamicTemplate.d.ts +2 -0
  29. package/dist/radioGroup/index.d.ts +2 -2
  30. package/dist/select/index.d.ts +2 -2
  31. package/dist/shapes/line.d.ts +1 -1
  32. package/dist/shapes/rectAndEllipse.d.ts +1 -2
  33. package/dist/{helper-M_MmV_d5.js → splitRange-DmVDtmzO.js} +132 -6
  34. package/dist/splitRange-DmVDtmzO.js.map +1 -0
  35. package/dist/splitRange.d.ts +16 -0
  36. package/dist/tables/helper.d.ts +12 -104
  37. package/dist/tables/types.d.ts +2 -6
  38. package/dist/tables.d.ts +1 -0
  39. package/dist/tables.js +3 -2
  40. package/dist/text/constants.d.ts +3 -0
  41. package/dist/text/dynamicTemplate.d.ts +2 -0
  42. package/dist/text/linkAnnotation.d.ts +14 -0
  43. package/dist/text/measure.d.ts +32 -0
  44. package/dist/text/overflow.d.ts +7 -0
  45. package/dist/text/richTextPdfRender.d.ts +3 -2
  46. package/dist/text/types.d.ts +7 -0
  47. package/dist/texts.d.ts +5 -0
  48. package/dist/texts.js +4 -0
  49. package/dist/types.d.ts +16 -0
  50. package/dist/types.js +0 -0
  51. package/dist/utils-zDZkqBnX.js +250 -0
  52. package/dist/utils-zDZkqBnX.js.map +1 -0
  53. package/dist/utils.d.ts +3 -0
  54. package/dist/utils.js +3 -215
  55. package/package.json +16 -1
  56. package/dist/builtins-CWHhKSVA.js.map +0 -1
  57. package/dist/dynamicTemplate-DmuRoTw4.js.map +0 -1
  58. package/dist/helper-M_MmV_d5.js.map +0 -1
  59. package/dist/lists-B6dmgpkS.js.map +0 -1
  60. package/dist/utils.js.map +0 -1
@@ -0,0 +1,75 @@
1
+ import { s as createTextLineSplitRange } from "./splitRange-DmVDtmzO.js";
2
+ import { a as measureTextLines, c as sumLineHeights, d as isInlineMarkdownTextSchema, n as getTextLineHeightsWithBox, r as getTextSplitBoxStyle } from "./measure-L5diay3k.js";
3
+ import { n as substituteVariablesAsInlineMarkdownLiterals, r as validateVariables, t as substituteVariables } from "./helper-CEme39Uo.js";
4
+ //#region src/multiVariableText/dynamicTemplate.ts
5
+ var getDynamicLayoutForMultiVariableText = async (value, args) => {
6
+ if (args.schema.type !== "multiVariableText") return { heights: [args.schema.height] };
7
+ const schema = args.schema;
8
+ if (schema.overflow !== "expand") return { heights: [schema.height] };
9
+ let renderValue = value;
10
+ if (!schema.readOnly) {
11
+ if (!validateVariables(value, schema)) return { heights: [schema.height] };
12
+ renderValue = isInlineMarkdownTextSchema(schema) ? substituteVariablesAsInlineMarkdownLiterals(schema.text || "", value) : substituteVariables(schema.text || "", value);
13
+ }
14
+ const { lineHeights } = await measureTextLines({
15
+ value: renderValue,
16
+ schema,
17
+ font: args.options.font,
18
+ _cache: args._cache,
19
+ ignoreDynamicFontSize: true
20
+ });
21
+ const heights = getTextLineHeightsWithBox(lineHeights, schema);
22
+ const measuredHeight = sumLineHeights(heights);
23
+ if (measuredHeight <= schema.height || lineHeights.length === 0) return {
24
+ heights: [schema.height],
25
+ patchSplitSchema: () => ({ dynamicFontSize: void 0 })
26
+ };
27
+ return {
28
+ heights: lineHeights.length === 1 ? [Math.max(schema.height, measuredHeight)] : heights,
29
+ patchSplitSchema: ({ start, end, isSplit }) => ({
30
+ dynamicFontSize: void 0,
31
+ __splitRange: lineHeights.length === 1 ? void 0 : createTextLineSplitRange(start, end),
32
+ __isSplit: isSplit,
33
+ ...getTextSplitBoxStyle(schema, {
34
+ start,
35
+ end
36
+ }, lineHeights.length)
37
+ })
38
+ };
39
+ };
40
+ //#endregion
41
+ //#region src/text/dynamicTemplate.ts
42
+ var getDynamicLayoutForText = async (value, args) => {
43
+ if (args.schema.type !== "text") return { heights: [args.schema.height] };
44
+ const schema = args.schema;
45
+ if (schema.overflow !== "expand") return { heights: [schema.height] };
46
+ const { lineHeights } = await measureTextLines({
47
+ value,
48
+ schema,
49
+ font: args.options.font,
50
+ _cache: args._cache,
51
+ ignoreDynamicFontSize: true
52
+ });
53
+ const heights = getTextLineHeightsWithBox(lineHeights, schema);
54
+ const measuredHeight = sumLineHeights(heights);
55
+ if (measuredHeight <= schema.height || lineHeights.length === 0) return {
56
+ heights: [schema.height],
57
+ patchSplitSchema: () => ({ dynamicFontSize: void 0 })
58
+ };
59
+ return {
60
+ heights: lineHeights.length === 1 ? [Math.max(schema.height, measuredHeight)] : heights,
61
+ patchSplitSchema: ({ start, end, isSplit }) => ({
62
+ dynamicFontSize: void 0,
63
+ __splitRange: lineHeights.length === 1 ? void 0 : createTextLineSplitRange(start, end),
64
+ __isSplit: isSplit,
65
+ ...getTextSplitBoxStyle(schema, {
66
+ start,
67
+ end
68
+ }, lineHeights.length)
69
+ })
70
+ };
71
+ };
72
+ //#endregion
73
+ export { getDynamicLayoutForMultiVariableText as n, getDynamicLayoutForText as t };
74
+
75
+ //# sourceMappingURL=dynamicTemplate-C7MdZxPm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dynamicTemplate-C7MdZxPm.js","names":[],"sources":["../src/multiVariableText/dynamicTemplate.ts","../src/text/dynamicTemplate.ts"],"sourcesContent":["import type { DynamicLayoutArgs, DynamicLayoutResult } from '@pdfme/common';\nimport { TEXT_OVERFLOW_EXPAND } from '../text/constants.js';\nimport {\n getTextLineHeightsWithBox,\n getTextSplitBoxStyle,\n measureTextLines,\n sumLineHeights,\n} from '../text/measure.js';\nimport { isInlineMarkdownTextSchema } from '../text/richText.js';\nimport type { MultiVariableTextSchema } from './types.js';\nimport {\n substituteVariables,\n substituteVariablesAsInlineMarkdownLiterals,\n validateVariables,\n} from './helper.js';\nimport { createTextLineSplitRange } from '../splitRange.js';\n\nexport const getDynamicLayoutForMultiVariableText = async (\n value: string,\n args: DynamicLayoutArgs,\n): Promise<DynamicLayoutResult> => {\n if (args.schema.type !== 'multiVariableText') return { heights: [args.schema.height] };\n\n const schema = args.schema as MultiVariableTextSchema;\n if (schema.overflow !== TEXT_OVERFLOW_EXPAND) {\n return { heights: [schema.height] };\n }\n\n let renderValue = value;\n if (!schema.readOnly) {\n if (!validateVariables(value, schema)) {\n return { heights: [schema.height] };\n }\n\n renderValue = isInlineMarkdownTextSchema(schema)\n ? substituteVariablesAsInlineMarkdownLiterals(schema.text || '', value)\n : substituteVariables(schema.text || '', value);\n }\n const { lineHeights } = await measureTextLines({\n value: renderValue,\n schema,\n font: args.options.font,\n _cache: args._cache,\n // `expand` owns the height decision, so measuring against a shrink-to-fit font size\n // would make the field keep its original box instead of growing.\n ignoreDynamicFontSize: true,\n });\n const heights = getTextLineHeightsWithBox(lineHeights, schema);\n const measuredHeight = sumLineHeights(heights);\n\n if (measuredHeight <= schema.height || lineHeights.length === 0) {\n return {\n heights: [schema.height],\n patchSplitSchema: () => ({ dynamicFontSize: undefined }),\n };\n }\n\n return {\n heights: lineHeights.length === 1 ? [Math.max(schema.height, measuredHeight)] : heights,\n patchSplitSchema: ({ start, end, isSplit }) => ({\n dynamicFontSize: undefined,\n __splitRange: lineHeights.length === 1 ? undefined : createTextLineSplitRange(start, end),\n __isSplit: isSplit,\n ...getTextSplitBoxStyle(schema, { start, end }, lineHeights.length),\n }),\n };\n};\n","import type { DynamicLayoutArgs, DynamicLayoutResult } from '@pdfme/common';\nimport { TEXT_OVERFLOW_EXPAND } from './constants.js';\nimport {\n getTextLineHeightsWithBox,\n getTextSplitBoxStyle,\n measureTextLines,\n sumLineHeights,\n} from './measure.js';\nimport type { TextSchema } from './types.js';\nimport { createTextLineSplitRange } from '../splitRange.js';\n\nexport const getDynamicLayoutForText = async (\n value: string,\n args: DynamicLayoutArgs,\n): Promise<DynamicLayoutResult> => {\n if (args.schema.type !== 'text') return { heights: [args.schema.height] };\n\n const schema = args.schema as TextSchema;\n if (schema.overflow !== TEXT_OVERFLOW_EXPAND) {\n return { heights: [schema.height] };\n }\n\n const { lineHeights } = await measureTextLines({\n value,\n schema,\n font: args.options.font,\n _cache: args._cache,\n // `expand` owns the height decision, so measuring against a shrink-to-fit font size\n // would make the field keep its original box instead of growing.\n ignoreDynamicFontSize: true,\n });\n const heights = getTextLineHeightsWithBox(lineHeights, schema);\n const measuredHeight = sumLineHeights(heights);\n\n if (measuredHeight <= schema.height || lineHeights.length === 0) {\n return {\n heights: [schema.height],\n patchSplitSchema: () => ({ dynamicFontSize: undefined }),\n };\n }\n\n return {\n heights: lineHeights.length === 1 ? [Math.max(schema.height, measuredHeight)] : heights,\n patchSplitSchema: ({ start, end, isSplit }) => ({\n dynamicFontSize: undefined,\n __splitRange: lineHeights.length === 1 ? undefined : createTextLineSplitRange(start, end),\n __isSplit: isSplit,\n ...getTextSplitBoxStyle(schema, { start, end }, lineHeights.length),\n }),\n };\n};\n"],"mappings":";;;;AAiBA,IAAa,uCAAuC,OAClD,OACA,SACiC;AACjC,KAAI,KAAK,OAAO,SAAS,oBAAqB,QAAO,EAAE,SAAS,CAAC,KAAK,OAAO,OAAO,EAAE;CAEtF,MAAM,SAAS,KAAK;AACpB,KAAI,OAAO,aAAA,SACT,QAAO,EAAE,SAAS,CAAC,OAAO,OAAO,EAAE;CAGrC,IAAI,cAAc;AAClB,KAAI,CAAC,OAAO,UAAU;AACpB,MAAI,CAAC,kBAAkB,OAAO,OAAO,CACnC,QAAO,EAAE,SAAS,CAAC,OAAO,OAAO,EAAE;AAGrC,gBAAc,2BAA2B,OAAO,GAC5C,4CAA4C,OAAO,QAAQ,IAAI,MAAM,GACrE,oBAAoB,OAAO,QAAQ,IAAI,MAAM;;CAEnD,MAAM,EAAE,gBAAgB,MAAM,iBAAiB;EAC7C,OAAO;EACP;EACA,MAAM,KAAK,QAAQ;EACnB,QAAQ,KAAK;EAGb,uBAAuB;EACxB,CAAC;CACF,MAAM,UAAU,0BAA0B,aAAa,OAAO;CAC9D,MAAM,iBAAiB,eAAe,QAAQ;AAE9C,KAAI,kBAAkB,OAAO,UAAU,YAAY,WAAW,EAC5D,QAAO;EACL,SAAS,CAAC,OAAO,OAAO;EACxB,yBAAyB,EAAE,iBAAiB,KAAA,GAAW;EACxD;AAGH,QAAO;EACL,SAAS,YAAY,WAAW,IAAI,CAAC,KAAK,IAAI,OAAO,QAAQ,eAAe,CAAC,GAAG;EAChF,mBAAmB,EAAE,OAAO,KAAK,eAAe;GAC9C,iBAAiB,KAAA;GACjB,cAAc,YAAY,WAAW,IAAI,KAAA,IAAY,yBAAyB,OAAO,IAAI;GACzF,WAAW;GACX,GAAG,qBAAqB,QAAQ;IAAE;IAAO;IAAK,EAAE,YAAY,OAAO;GACpE;EACF;;;;ACtDH,IAAa,0BAA0B,OACrC,OACA,SACiC;AACjC,KAAI,KAAK,OAAO,SAAS,OAAQ,QAAO,EAAE,SAAS,CAAC,KAAK,OAAO,OAAO,EAAE;CAEzE,MAAM,SAAS,KAAK;AACpB,KAAI,OAAO,aAAA,SACT,QAAO,EAAE,SAAS,CAAC,OAAO,OAAO,EAAE;CAGrC,MAAM,EAAE,gBAAgB,MAAM,iBAAiB;EAC7C;EACA;EACA,MAAM,KAAK,QAAQ;EACnB,QAAQ,KAAK;EAGb,uBAAuB;EACxB,CAAC;CACF,MAAM,UAAU,0BAA0B,aAAa,OAAO;CAC9D,MAAM,iBAAiB,eAAe,QAAQ;AAE9C,KAAI,kBAAkB,OAAO,UAAU,YAAY,WAAW,EAC5D,QAAO;EACL,SAAS,CAAC,OAAO,OAAO;EACxB,yBAAyB,EAAE,iBAAiB,KAAA,GAAW;EACxD;AAGH,QAAO;EACL,SAAS,YAAY,WAAW,IAAI,CAAC,KAAK,IAAI,OAAO,QAAQ,eAAe,CAAC,GAAG;EAChF,mBAAmB,EAAE,OAAO,KAAK,eAAe;GAC9C,iBAAiB,KAAA;GACjB,cAAc,YAAY,WAAW,IAAI,KAAA,IAAY,yBAAyB,OAAO,IAAI;GACzF,WAAW;GACX,GAAG,qBAAqB,QAAQ;IAAE;IAAO;IAAK,EAAE,YAAY,OAAO;GACpE;EACF"}
@@ -1,5 +1,5 @@
1
1
  import type { Plugin } from '@pdfme/common';
2
2
  import type { Schema } from '@pdfme/common';
3
- type ImageSchema = Schema;
3
+ export type ImageSchema = Schema;
4
4
  declare const imageSchema: Plugin<ImageSchema>;
5
5
  export default imageSchema;
@@ -1,4 +1,4 @@
1
1
  import type { Plugin, Schema } from '@pdfme/common';
2
- type SignatureSchema = Schema;
2
+ export type SignatureSchema = Schema;
3
3
  declare const signature: Plugin<SignatureSchema>;
4
4
  export default signature;
@@ -0,0 +1,40 @@
1
+ import { h as escapeInlineMarkdown } from "./measure-L5diay3k.js";
2
+ //#region src/multiVariableText/helper.ts
3
+ var substituteVariables = (text, variablesIn, valueMapper = (value) => value) => {
4
+ if (!text) return "";
5
+ let substitutedText = text;
6
+ if (variablesIn) {
7
+ let variables;
8
+ try {
9
+ variables = typeof variablesIn === "string" ? JSON.parse(variablesIn || "{}") : variablesIn;
10
+ } catch {
11
+ throw new SyntaxError(`[@pdfme/schemas] MVT: invalid JSON string '${variablesIn}'`);
12
+ }
13
+ Object.keys(variables).forEach((variableName) => {
14
+ const variableForRegex = variableName.replace(/[/\-\\^$*+?.()|[\]{}]/g, "\\$&");
15
+ const regex = new RegExp("\\{" + variableForRegex + "\\}", "g");
16
+ substitutedText = substitutedText.replace(regex, valueMapper(variables[variableName], variableName));
17
+ });
18
+ }
19
+ substitutedText = substitutedText.replace(/{[^{}]+}/g, "");
20
+ return substitutedText;
21
+ };
22
+ var substituteVariablesAsInlineMarkdownLiterals = (text, variablesIn) => substituteVariables(text, variablesIn, escapeInlineMarkdown);
23
+ var validateVariables = (value, schema) => {
24
+ if (schema.variables.length === 0) return true;
25
+ let values;
26
+ try {
27
+ values = value ? JSON.parse(value) : {};
28
+ } catch {
29
+ throw new SyntaxError(`[@pdfme/generator] invalid JSON string '${value}' for variables in field ${schema.name}`);
30
+ }
31
+ for (const variable of schema.variables) if (!values[variable]) {
32
+ if (schema.required) throw new Error(`[@pdfme/generator] variable ${variable} is missing for field ${schema.name}`);
33
+ return false;
34
+ }
35
+ return true;
36
+ };
37
+ //#endregion
38
+ export { substituteVariablesAsInlineMarkdownLiterals as n, validateVariables as r, substituteVariables as t };
39
+
40
+ //# sourceMappingURL=helper-CEme39Uo.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helper-CEme39Uo.js","names":[],"sources":["../src/multiVariableText/helper.ts"],"sourcesContent":["import { MultiVariableTextSchema } from './types.js';\nimport { escapeInlineMarkdown } from '../text/inlineMarkdown.js';\n\nexport const substituteVariables = (\n text: string,\n variablesIn: string | Record<string, string>,\n valueMapper: (value: string, variableName: string) => string = (value) => value,\n): string => {\n if (!text) {\n return '';\n }\n\n let substitutedText = text;\n\n if (variablesIn) {\n let variables: Record<string, string>;\n try {\n variables =\n typeof variablesIn === 'string'\n ? (JSON.parse(variablesIn || '{}') as Record<string, string>)\n : variablesIn;\n } catch {\n throw new SyntaxError(`[@pdfme/schemas] MVT: invalid JSON string '${variablesIn as string}'`);\n }\n\n Object.keys(variables).forEach((variableName) => {\n // handle special characters in variable name\n const variableForRegex = variableName.replace(/[/\\-\\\\^$*+?.()|[\\]{}]/g, '\\\\$&');\n const regex = new RegExp('\\\\{' + variableForRegex + '\\\\}', 'g');\n substitutedText = substitutedText.replace(\n regex,\n valueMapper(variables[variableName], variableName),\n );\n });\n }\n\n // Remove any variables that were not substituted from inputs\n substitutedText = substitutedText.replace(/{[^{}]+}/g, '');\n\n return substitutedText;\n};\n\nexport const substituteVariablesAsInlineMarkdownLiterals = (\n text: string,\n variablesIn: string | Record<string, string>,\n): string => substituteVariables(text, variablesIn, escapeInlineMarkdown);\n\nexport const validateVariables = (value: string, schema: MultiVariableTextSchema): boolean => {\n if (schema.variables.length === 0) {\n return true;\n }\n\n let values;\n try {\n values = value ? (JSON.parse(value) as Record<string, string>) : {};\n } catch {\n throw new SyntaxError(\n `[@pdfme/generator] invalid JSON string '${value}' for variables in field ${schema.name}`,\n );\n }\n\n for (const variable of schema.variables) {\n if (!values[variable]) {\n if (schema.required) {\n throw new Error(\n `[@pdfme/generator] variable ${variable} is missing for field ${schema.name}`,\n );\n }\n // If not required, then simply don't render this field if an input is missing\n return false;\n }\n }\n\n return true;\n};\n"],"mappings":";;AAGA,IAAa,uBACX,MACA,aACA,eAAgE,UAAU,UAC/D;AACX,KAAI,CAAC,KACH,QAAO;CAGT,IAAI,kBAAkB;AAEtB,KAAI,aAAa;EACf,IAAI;AACJ,MAAI;AACF,eACE,OAAO,gBAAgB,WAClB,KAAK,MAAM,eAAe,KAAK,GAChC;UACA;AACN,SAAM,IAAI,YAAY,8CAA8C,YAAsB,GAAG;;AAG/F,SAAO,KAAK,UAAU,CAAC,SAAS,iBAAiB;GAE/C,MAAM,mBAAmB,aAAa,QAAQ,0BAA0B,OAAO;GAC/E,MAAM,QAAQ,IAAI,OAAO,QAAQ,mBAAmB,OAAO,IAAI;AAC/D,qBAAkB,gBAAgB,QAChC,OACA,YAAY,UAAU,eAAe,aAAa,CACnD;IACD;;AAIJ,mBAAkB,gBAAgB,QAAQ,aAAa,GAAG;AAE1D,QAAO;;AAGT,IAAa,+CACX,MACA,gBACW,oBAAoB,MAAM,aAAa,qBAAqB;AAEzE,IAAa,qBAAqB,OAAe,WAA6C;AAC5F,KAAI,OAAO,UAAU,WAAW,EAC9B,QAAO;CAGT,IAAI;AACJ,KAAI;AACF,WAAS,QAAS,KAAK,MAAM,MAAM,GAA8B,EAAE;SAC7D;AACN,QAAM,IAAI,YACR,2CAA2C,MAAM,2BAA2B,OAAO,OACpF;;AAGH,MAAK,MAAM,YAAY,OAAO,UAC5B,KAAI,CAAC,OAAO,WAAW;AACrB,MAAI,OAAO,SACT,OAAM,IAAI,MACR,+BAA+B,SAAS,wBAAwB,OAAO,OACxE;AAGH,SAAO;;AAIX,QAAO"}
package/dist/index.d.ts CHANGED
@@ -18,3 +18,4 @@ export { builtInPlugins } from './builtins.js';
18
18
  export { text, multiVariableText, list, image, signature, svg, table, barcodes, line, rectangle, ellipse, dateTime, date, time, select, radioGroup, checkbox, };
19
19
  export { getDynamicHeightsForTable, getDynamicLayoutForTable } from './tables.js';
20
20
  export { getDynamicLayoutForList } from './lists.js';
21
+ export { BUILT_IN_DYNAMIC_LAYOUT_SPLIT_UNITS, LIST_ITEM_SPLIT_UNIT, TABLE_BODY_SPLIT_UNIT, TEXT_LINE_SPLIT_UNIT, createListItemSplitRange, createTableBodySplitRange, createTextLineSplitRange, getListItemRange, getTableBodyRange, getTextLineRange, type BuiltInDynamicLayoutSplitUnit, } from './splitRange.js';