You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@superset.apache.org by jo...@apache.org on 2023/03/13 19:11:23 UTC

[superset] branch master updated: fix(dashboard): deepmerge htmlSchemaOverrides (#23329)

This is an automated email from the ASF dual-hosted git repository.

johnbodley pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/superset.git


The following commit(s) were added to refs/heads/master by this push:
     new 3919ca6060 fix(dashboard): deepmerge htmlSchemaOverrides (#23329)
3919ca6060 is described below

commit 3919ca60608e1c2d3cfef99d5a8d9d2aef227843
Author: JUST.in DO IT <ju...@airbnb.com>
AuthorDate: Mon Mar 13 12:11:12 2023 -0700

    fix(dashboard): deepmerge htmlSchemaOverrides (#23329)
---
 .../src/components/SafeMarkdown.tsx                | 16 +++++++--
 .../test/components/SafeMarkdown.test.ts           | 39 ++++++++++++++++++++++
 2 files changed, 53 insertions(+), 2 deletions(-)

diff --git a/superset-frontend/packages/superset-ui-core/src/components/SafeMarkdown.tsx b/superset-frontend/packages/superset-ui-core/src/components/SafeMarkdown.tsx
index 4db48d4265..8be73295b4 100644
--- a/superset-frontend/packages/superset-ui-core/src/components/SafeMarkdown.tsx
+++ b/superset-frontend/packages/superset-ui-core/src/components/SafeMarkdown.tsx
@@ -20,7 +20,7 @@ import React, { useMemo } from 'react';
 import ReactMarkdown from 'react-markdown';
 import rehypeSanitize, { defaultSchema } from 'rehype-sanitize';
 import rehypeRaw from 'rehype-raw';
-import { merge } from 'lodash';
+import { mergeWith, isArray } from 'lodash';
 import { FeatureFlag, isFeatureEnabled } from '../utils';
 
 interface SafeMarkdownProps {
@@ -29,6 +29,15 @@ interface SafeMarkdownProps {
   htmlSchemaOverrides?: typeof defaultSchema;
 }
 
+export function getOverrideHtmlSchema(
+  originalSchema: typeof defaultSchema,
+  htmlSchemaOverrides: SafeMarkdownProps['htmlSchemaOverrides'],
+) {
+  return mergeWith(originalSchema, htmlSchemaOverrides, (objValue, srcValue) =>
+    isArray(objValue) ? objValue.concat(srcValue) : undefined,
+  );
+}
+
 function SafeMarkdown({
   source,
   htmlSanitization = true,
@@ -42,7 +51,10 @@ function SafeMarkdown({
     if (displayHtml && !escapeHtml) {
       rehypePlugins.push(rehypeRaw);
       if (htmlSanitization) {
-        const schema = merge(defaultSchema, htmlSchemaOverrides);
+        const schema = getOverrideHtmlSchema(
+          defaultSchema,
+          htmlSchemaOverrides,
+        );
         rehypePlugins.push([rehypeSanitize, schema]);
       }
     }
diff --git a/superset-frontend/packages/superset-ui-core/test/components/SafeMarkdown.test.ts b/superset-frontend/packages/superset-ui-core/test/components/SafeMarkdown.test.ts
new file mode 100644
index 0000000000..4b4c826923
--- /dev/null
+++ b/superset-frontend/packages/superset-ui-core/test/components/SafeMarkdown.test.ts
@@ -0,0 +1,39 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+import { getOverrideHtmlSchema } from '../../src/components/SafeMarkdown';
+
+describe('getOverrideHtmlSchema', () => {
+  it('should append the override items', () => {
+    const original = {
+      attributes: {
+        '*': ['size'],
+      },
+      clobberPrefix: 'original-prefix',
+      tagNames: ['h1', 'h2', 'h3'],
+    };
+    const result = getOverrideHtmlSchema(original, {
+      attributes: { '*': ['src'], h1: ['style'] },
+      clobberPrefix: 'custom-prefix',
+      tagNames: ['iframe'],
+    });
+    expect(result.clobberPrefix).toEqual('custom-prefix');
+    expect(result.attributes).toEqual({ '*': ['size', 'src'], h1: ['style'] });
+    expect(result.tagNames).toEqual(['h1', 'h2', 'h3', 'iframe']);
+  });
+});