Răsfoiți Sursa

add codeblock sanitize

reiji-h 1 an în urmă
părinte
comite
1d245b9e31

+ 5 - 0
apps/app/src/client/services/renderer/renderer.tsx

@@ -26,6 +26,7 @@ import * as addLineNumberAttribute from '~/services/renderer/rehype-plugins/add-
 import * as keywordHighlighter from '~/services/renderer/rehype-plugins/keyword-highlighter';
 import * as relocateToc from '~/services/renderer/rehype-plugins/relocate-toc';
 import * as attachment from '~/services/renderer/remark-plugins/attachment';
+import * as codeBlock from '~/services/renderer/remark-plugins/codeblock';
 import * as plantuml from '~/services/renderer/remark-plugins/plantuml';
 import * as xsvToTable from '~/services/renderer/remark-plugins/xsv-to-table';
 import {
@@ -80,6 +81,7 @@ export const generateViewOptions = (
       attachment.sanitizeOption,
       lsxGrowiDirective.sanitizeOption,
       refsGrowiDirective.sanitizeOption,
+      codeBlock.sanitizeOption,
     )]
     : () => {};
 
@@ -132,6 +134,7 @@ export const generateTocOptions = (config: RendererConfig, tocNode: HtmlElementN
   const rehypeSanitizePlugin: Pluggable | (() => void) = config.isEnabledXssPrevention
     ? [sanitize, deepmerge(
       getCommonSanitizeOption(config),
+      codeBlock.sanitizeOption,
     )]
     : () => {};
 
@@ -185,6 +188,7 @@ export const generateSimpleViewOptions = (
       attachment.sanitizeOption,
       lsxGrowiDirective.sanitizeOption,
       refsGrowiDirective.sanitizeOption,
+      codeBlock.sanitizeOption,
     )]
     : () => {};
 
@@ -274,6 +278,7 @@ export const generatePreviewOptions = (config: RendererConfig, pagePath: string)
       lsxGrowiDirective.sanitizeOption,
       refsGrowiDirective.sanitizeOption,
       addLineNumberAttribute.sanitizeOption,
+      codeBlock.sanitizeOption,
     )]
     : () => {};
 

+ 10 - 2
apps/app/src/components/ReactMarkdownComponents/CodeBlock.tsx

@@ -65,10 +65,18 @@ function CodeBlockSubstance({ lang, children }: { lang: string, children: ReactN
     </PrismAsyncLight>
   );
 }
-export const CodeBlock = ({ className, children }: {className: string, children: JSX.Element}): JSX.Element => {
+
+type CodeBlockProps = {
+  children: JSX.Element,
+  className?: string,
+  inline?: string, // "" or undefined
+}
+
+export const CodeBlock = (props: CodeBlockProps): JSX.Element => {
 
   // TODO: set border according to the value of 'customize:highlightJsStyleBorder'
-  if (className === 'inline') {
+  const { className, children, inline } = props;
+  if (inline != null) {
     return <code className={`code-inline ${className ?? ''}`}>{children}</code>;
   }
 

+ 8 - 16
apps/app/src/services/renderer/remark-plugins/codeblock.ts

@@ -1,31 +1,23 @@
-
-import type { Root } from 'hast';
-import { selectAll } from 'hast-util-select';
+import type { Schema as SanitizeOption } from 'hast-util-sanitize';
 import type { InlineCode } from 'mdast';
 import type { Plugin } from 'unified';
 import { visit } from 'unist-util-visit';
 
-import { addClassToProperties } from '../rehype-plugins/add-class';
+
+const SUPPORTED_CODE = ['inline'];
 
 export const remarkPlugin: Plugin = () => {
   return (tree) => {
     visit(tree, 'inlineCode', (node: InlineCode) => {
       const data = node.data || (node.data = {});
-      // setting inline for rehypePlugin
       data.hProperties = { inline: true };
     });
   };
 };
 
-export const rehypePlugin: Plugin = () => {
-  return (tree: Root) => {
-    const codeElements = selectAll('code', tree);
-    codeElements.forEach((element) => {
-      // if inlineCode, properties.inline exists.
-      if (element.properties?.inline != null) {
-        element.properties.inline = true;
-        addClassToProperties(element.properties, 'inline');
-      }
-    });
-  };
+export const sanitizeOption: SanitizeOption = {
+  tagNames: ['code'],
+  attributes: {
+    code: SUPPORTED_CODE,
+  },
 };

+ 2 - 3
apps/app/src/services/renderer/renderer.tsx

@@ -25,7 +25,7 @@ import { tagNames as recommendedTagNames, attributes as recommendedAttributes }
 import * as addClass from './rehype-plugins/add-class';
 import { relativeLinks } from './rehype-plugins/relative-links';
 import { relativeLinksByPukiwikiLikeLinker } from './rehype-plugins/relative-links-by-pukiwiki-like-linker';
-import * as codeBlocks from './remark-plugins/codeblock';
+import * as codeBlock from './remark-plugins/codeblock';
 import { pukiwikiLikeLinker } from './remark-plugins/pukiwiki-like-linker';
 import * as xsvToTable from './remark-plugins/xsv-to-table';
 
@@ -97,7 +97,7 @@ export const generateCommonOptions = (pagePath: string|undefined): RendererOptio
       pukiwikiLikeLinker,
       growiDirective,
       remarkFrontmatter,
-      codeBlocks.remarkPlugin,
+      codeBlock.remarkPlugin,
     ],
     remarkRehypeOptions: {
       clobberPrefix: '', // remove clobber prefix
@@ -110,7 +110,6 @@ export const generateCommonOptions = (pagePath: string|undefined): RendererOptio
       [addClass.rehypePlugin, {
         table: 'table table-bordered',
       }],
-      codeBlocks.rehypePlugin,
     ],
     components: {
       a: NextLink,

+ 1 - 2
apps/app/src/stores/renderer.tsx

@@ -5,11 +5,10 @@ import useSWR, { type SWRConfiguration, type SWRResponse } from 'swr';
 
 import { getGrowiFacade } from '~/features/growi-plugin/client/utils/growi-facade-utils';
 import type { RendererOptions } from '~/interfaces/renderer-options';
-
-
 import {
   useRendererConfig,
 } from '~/stores-universal/context';
+
 import { useCurrentPagePath } from './page';
 import { useCurrentPageTocNode } from './ui';