@abgov/jsonforms-components 2.47.3 → 2.47.5

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/index.esm.js CHANGED
@@ -14,6 +14,8 @@ import merge from 'lodash/merge';
14
14
  import isEmpty from 'lodash/isEmpty';
15
15
  import range from 'lodash/range';
16
16
  import pluralize from 'pluralize';
17
+ import dompurify from 'dompurify';
18
+ import * as xss from 'xss';
17
19
  import { evaluateSync, compileSync } from '@mdx-js/mdx';
18
20
  import { Parser } from 'expr-eval-fork';
19
21
  import addErrors from 'ajv-errors';
@@ -10894,23 +10896,22 @@ const renderCellColumn = ({
10894
10896
  }) => {
10895
10897
  const renderWarningCell = data => {
10896
10898
  return jsx(HilightCellWarning, {
10897
- children: jsxs(ObjectArrayWarningIconDiv, {
10898
- children: [jsx(GoabIcon, {
10899
+ children: jsx(ObjectArrayWarningIconDiv, {
10900
+ children: jsx(GoabIcon, {
10899
10901
  type: "warning",
10900
10902
  title: "warning",
10901
10903
  size: "small",
10902
10904
  theme: "filled",
10903
10905
  ml: "2xs",
10904
10906
  mt: "2xs"
10905
- }), data]
10907
+ })
10906
10908
  })
10907
10909
  });
10908
10910
  };
10909
10911
  if (data === undefined && isRequired || error !== '' && error !== undefined) {
10910
- const message = error || (isRequired && data === undefined ? 'Required' : data);
10911
- return renderWarningCell(message);
10912
+ return renderWarningCell();
10912
10913
  } else if (data !== undefined && isRequired && error) {
10913
- return renderWarningCell(error);
10914
+ return renderWarningCell();
10914
10915
  }
10915
10916
  const path = `/${rowPath}/${index}/${element}/${index === 0 ? index : index - 1}`;
10916
10917
  const nestedErrors = errors == null ? void 0 : errors.filter(e => e.instancePath.includes(path));
@@ -11111,10 +11112,6 @@ const NonEmptyCellComponent = /*#__PURE__*/React.memo(function NonEmptyCellCompo
11111
11112
  }, 0)
11112
11113
  }), jsx("tbody", {
11113
11114
  children: range(count || 0).map((num, i) => {
11114
- // Skip rendering empty rows in review mode
11115
- if (isInReview === true && (data === undefined || data[num] === undefined || Object.keys(data[num]).length === 0)) {
11116
- return null;
11117
- }
11118
11115
  const errorRow = errors == null ? void 0 : errors.find(error => error.instancePath.includes(`/${props.rowPath.replace(/\./g, '/')}/${i}`));
11119
11116
  return jsxs("tr", {
11120
11117
  children: [Object.keys(properties).map((element, ix) => {
@@ -11166,7 +11163,7 @@ const NonEmptyCellComponent = /*#__PURE__*/React.memo(function NonEmptyCellCompo
11166
11163
  children: renderCellColumn({
11167
11164
  data: currentData !== '' && currentData !== null && currentData !== undefined ? currentData : undefined,
11168
11165
  error: humanMessage,
11169
- isRequired: (_required$includes = required == null ? void 0 : required.includes(tableKeys[element])) != null ? _required$includes : false,
11166
+ isRequired: (_required$includes = required == null ? void 0 : required.includes(element)) != null ? _required$includes : false,
11170
11167
  errors: errors !== undefined ? errors : [],
11171
11168
  element,
11172
11169
  rowPath,
@@ -12043,11 +12040,19 @@ const AddressLoopUpControlTableReview = props => {
12043
12040
  "data-testid": "address-lookup-table-review",
12044
12041
  children: jsx(PageReviewContainer, {
12045
12042
  colSpan: 3,
12046
- children: jsx(ReviewLabel, {
12047
- children: `${isAlbertaAddress ? 'Alberta' : 'Canada'} postal address`
12043
+ children: jsxs(ReviewHeader, {
12044
+ children: [jsx(ReviewLabel, {
12045
+ children: `${isAlbertaAddress ? 'Alberta' : 'Canada'} postal address`
12046
+ }), stepId !== undefined && jsx(GoabButton, {
12047
+ type: "tertiary",
12048
+ size: "compact",
12049
+ onClick: () => formStepperCtx == null ? void 0 : formStepperCtx.goToPage(stepId, targetScope),
12050
+ testId: "address-change-btn",
12051
+ children: "Change"
12052
+ })]
12048
12053
  })
12049
12054
  })
12050
- }), renderRow('Address line 1', data == null ? void 0 : data.addressLine1, 'addressLine1', true), (data == null ? void 0 : data.addressLine2) && renderRow('Address line 2', data.addressLine2, 'addressLine2', false), renderRow('City', data == null ? void 0 : data.municipality, 'municipality', false), renderRow('Postal Code', data == null ? void 0 : data.postalCode, 'postalCode', false), renderRow('Province', provinceLabel, 'subdivisionCode', false), renderRow('Country', 'Canada', 'country', false)]
12055
+ }), renderRow('Address line 1', data == null ? void 0 : data.addressLine1, 'addressLine1', false), (data == null ? void 0 : data.addressLine2) && renderRow('Address line 2', data.addressLine2, 'addressLine2', false), renderRow('City', data == null ? void 0 : data.municipality, 'municipality', false), renderRow('Postal Code', data == null ? void 0 : data.postalCode, 'postalCode', false), renderRow('Province', provinceLabel, 'subdivisionCode', false), renderRow('Country', 'Canada', 'country', false)]
12051
12056
  });
12052
12057
  };
12053
12058
 
@@ -13190,6 +13195,81 @@ const SummaryRow = ({
13190
13195
  });
13191
13196
  };
13192
13197
 
13198
+ const options = {
13199
+ whiteList: {
13200
+ html: ['lang'],
13201
+ meta: ['name', 'content', 'charset'],
13202
+ div: ['style', 'class'],
13203
+ style: [],
13204
+ a: ['href', 'title', 'target', 'style', 'class'],
13205
+ em: [],
13206
+ main: [],
13207
+ footer: ['style'],
13208
+ header: ['style'],
13209
+ head: [],
13210
+ abbr: ['title', 'style'],
13211
+ title: [],
13212
+ address: ['style'],
13213
+ area: ['shape', 'coords', 'href', 'alt', 'style'],
13214
+ article: [],
13215
+ blockquote: [],
13216
+ aside: [],
13217
+ details: [],
13218
+ h1: [],
13219
+ h2: [],
13220
+ h3: [],
13221
+ h4: [],
13222
+ h5: [],
13223
+ h6: [],
13224
+ hr: [],
13225
+ i: [],
13226
+ img: ['src', 'alt', 'title', 'width', 'height'],
13227
+ ins: ['datetime'],
13228
+ li: [],
13229
+ mark: [],
13230
+ nav: [],
13231
+ ol: [],
13232
+ p: [],
13233
+ pre: [],
13234
+ s: [],
13235
+ section: [],
13236
+ small: [],
13237
+ span: ['class', 'style'],
13238
+ sub: [],
13239
+ summary: [],
13240
+ sup: [],
13241
+ select: [],
13242
+ optgroup: [],
13243
+ form: [],
13244
+ strong: [],
13245
+ label: [],
13246
+ strike: [],
13247
+ table: ['width', 'border', 'align', 'valign', 'class', 'style'],
13248
+ tbody: ['align', 'valign', 'class', 'style'],
13249
+ body: ['class', 'style'],
13250
+ td: ['width', 'rowspan', 'colspan', 'align', 'valign', 'class', 'style'],
13251
+ tfoot: ['align', 'valign', 'class', 'style'],
13252
+ th: ['width', 'rowspan', 'colspan', 'align', 'valign', 'class', 'style'],
13253
+ thead: ['align', 'valign'],
13254
+ tr: ['rowspan', 'align', 'valign'],
13255
+ tt: [],
13256
+ u: [],
13257
+ ul: [],
13258
+ br: [],
13259
+ b: [],
13260
+ option: []
13261
+ }
13262
+ }; // Custom rules
13263
+ new xss.FilterXSS(options);
13264
+ const sanitizeHtml = dompurify.sanitize;
13265
+ dompurify.addHook('afterSanitizeAttributes', function (node) {
13266
+ // set all elements owning target to target=_blank
13267
+ if ('target' in node) {
13268
+ node.setAttribute('target', '_blank');
13269
+ node.setAttribute('rel', 'noopener noreferrer');
13270
+ }
13271
+ });
13272
+
13193
13273
  const _excluded$1 = ["type"];
13194
13274
  const AdditionalInstructionsRow = ({
13195
13275
  additionalInstructions,
@@ -13200,6 +13280,7 @@ const AdditionalInstructionsRow = ({
13200
13280
  const type = validTypes.includes(calloutType) ? calloutType : 'information';
13201
13281
  const _ref = componentProps || {},
13202
13282
  otherProps = _objectWithoutPropertiesLoose(_ref, _excluded$1);
13283
+ const sanitizedHtml = sanitizeHtml(additionalInstructions);
13203
13284
  return jsx("tr", {
13204
13285
  children: jsx("td", {
13205
13286
  colSpan: 2,
@@ -13208,7 +13289,11 @@ const AdditionalInstructionsRow = ({
13208
13289
  mt: "xl",
13209
13290
  mb: "l"
13210
13291
  }, otherProps, {
13211
- children: additionalInstructions
13292
+ children: jsx("div", {
13293
+ dangerouslySetInnerHTML: {
13294
+ __html: sanitizedHtml
13295
+ }
13296
+ })
13212
13297
  }))
13213
13298
  })
13214
13299
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@abgov/jsonforms-components",
3
- "version": "2.47.3",
3
+ "version": "2.47.5",
4
4
  "license": "Apache-2.0",
5
5
  "description": "Government of Alberta - React renderers for JSON Forms based on the design system.",
6
6
  "repository": "https://github.com/GovAlta/adsp-monorepo",
@@ -10,6 +10,8 @@
10
10
  "@jsonforms/core": "^3.1.0",
11
11
  "@jsonforms/react": "^3.1.0",
12
12
  "react": "^18.0.0",
13
+ "dompurify": "^3.2.4",
14
+ "xss": "^1.0.15",
13
15
  "ajv": "^8.6.1",
14
16
  "ajv-errors": "^3.0.0",
15
17
  "ajv-formats": "^3.0.1",
@@ -0,0 +1,19 @@
1
+ import dompurify from 'dompurify';
2
+ export declare const sanitizeHtml: {
3
+ (dirty: string | Node, cfg: dompurify.Config & {
4
+ RETURN_TRUSTED_TYPE: true;
5
+ }): import("trusted-types/lib").TrustedHTML;
6
+ (dirty: Node, cfg: dompurify.Config & {
7
+ IN_PLACE: true;
8
+ }): Node;
9
+ (dirty: string | Node, cfg: dompurify.Config & {
10
+ RETURN_DOM: true;
11
+ }): Node;
12
+ (dirty: string | Node, cfg: dompurify.Config & {
13
+ RETURN_DOM_FRAGMENT: true;
14
+ }): DocumentFragment;
15
+ (dirty: string | Node, cfg?: dompurify.Config): string;
16
+ };
17
+ export declare function hasXSS(html: string): boolean;
18
+ export declare const htmlSanitized: (html: string) => string;
19
+ export declare const XSSErrorMessage = "The template contains content that could expose users to Cross Site Scripting attacks. Remove risky elements like <script> to save the template.";