Просмотр исходного кода

fix: refactor rendering attribute handling for auto-scroll functionality

Shun Miyazawa 1 месяц назад
Родитель
Сommit
fe73718c23

+ 6 - 2
apps/app/src/components/PageView/PageView.tsx

@@ -8,6 +8,10 @@ import {
   useRef,
   useRef,
 } from 'react';
 } from 'react';
 import dynamic from 'next/dynamic';
 import dynamic from 'next/dynamic';
+import {
+  GROWI_RENDERING_ATTR,
+  GROWI_RENDERING_ATTR_SELECTOR,
+} from '@growi/core/dist/consts';
 import { isDeepEquals } from '@growi/core/dist/utils/is-deep-equals';
 import { isDeepEquals } from '@growi/core/dist/utils/is-deep-equals';
 import { isUsersHomepage } from '@growi/core/dist/utils/page-path-utils';
 import { isUsersHomepage } from '@growi/core/dist/utils/page-path-utils';
 import { useSlidesByFrontmatter } from '@growi/presentation/dist/services';
 import { useSlidesByFrontmatter } from '@growi/presentation/dist/services';
@@ -160,7 +164,7 @@ const PageViewComponent = (props: Props): JSX.Element => {
 
 
       const renderingObserver = new MutationObserver(() => {
       const renderingObserver = new MutationObserver(() => {
         const hasRendering =
         const hasRendering =
-          contentContainer.querySelector('[data-growi-rendering]') != null;
+          contentContainer.querySelector(GROWI_RENDERING_ATTR_SELECTOR) != null;
 
 
         if (hasRendering) {
         if (hasRendering) {
           // At least one component is still rendering
           // At least one component is still rendering
@@ -180,7 +184,7 @@ const PageViewComponent = (props: Props): JSX.Element => {
         childList: true,
         childList: true,
         subtree: true,
         subtree: true,
         attributes: true,
         attributes: true,
-        attributeFilter: ['data-growi-rendering'],
+        attributeFilter: [GROWI_RENDERING_ATTR],
       });
       });
 
 
       return renderingObserver;
       return renderingObserver;

+ 1 - 0
packages/core/src/consts/index.ts

@@ -1,4 +1,5 @@
 export * from './accepted-upload-file-type';
 export * from './accepted-upload-file-type';
 export * from './growi-plugin';
 export * from './growi-plugin';
+export * from './renderer';
 export * from './system';
 export * from './system';
 export * from './ydoc-status';
 export * from './ydoc-status';

+ 10 - 0
packages/core/src/consts/renderer.ts

@@ -0,0 +1,10 @@
+/**
+ * HTML attribute name applied to elements that are currently being rendered
+ * (e.g. Drawio, Mermaid diagrams). Removed once rendering is complete.
+ * Used by PageView to detect in-progress renders before auto-scrolling.
+ */
+export const GROWI_RENDERING_ATTR = 'data-growi-rendering' as const;
+
+/** CSS attribute selector for elements with {@link GROWI_RENDERING_ATTR}. */
+export const GROWI_RENDERING_ATTR_SELECTOR =
+  `[${GROWI_RENDERING_ATTR}]` as const;

+ 4 - 3
packages/remark-drawio/src/components/DrawioViewer.tsx

@@ -8,6 +8,7 @@ import {
   useRef,
   useRef,
   useState,
   useState,
 } from 'react';
 } from 'react';
+import { GROWI_RENDERING_ATTR } from '@growi/core/dist/consts';
 import { debounce } from 'throttle-debounce';
 import { debounce } from 'throttle-debounce';
 
 
 import type { IGraphViewerGlobal } from '..';
 import type { IGraphViewerGlobal } from '..';
@@ -127,7 +128,7 @@ export const DrawioViewer = memo((props: DrawioViewerProps): JSX.Element => {
   useEffect(() => {
   useEffect(() => {
     if (error != null) {
     if (error != null) {
       onRenderingUpdated?.(null);
       onRenderingUpdated?.(null);
-      drawioContainerRef.current?.removeAttribute('data-growi-rendering');
+      drawioContainerRef.current?.removeAttribute(GROWI_RENDERING_ATTR);
     }
     }
   }, [error, onRenderingUpdated]);
   }, [error, onRenderingUpdated]);
 
 
@@ -144,7 +145,7 @@ export const DrawioViewer = memo((props: DrawioViewerProps): JSX.Element => {
         if (mxgraphData != null) {
         if (mxgraphData != null) {
           const mxgraph = JSON.parse(mxgraphData);
           const mxgraph = JSON.parse(mxgraphData);
           onRenderingUpdated?.(mxgraph.xml);
           onRenderingUpdated?.(mxgraph.xml);
-          drawioContainerRef.current?.removeAttribute('data-growi-rendering');
+          drawioContainerRef.current?.removeAttribute(GROWI_RENDERING_ATTR);
         }
         }
       }
       }
     };
     };
@@ -184,7 +185,7 @@ export const DrawioViewer = memo((props: DrawioViewerProps): JSX.Element => {
       className={`drawio-viewer ${styles['drawio-viewer']} p-2`}
       className={`drawio-viewer ${styles['drawio-viewer']} p-2`}
       data-begin-line-number-of-markdown={bol}
       data-begin-line-number-of-markdown={bol}
       data-end-line-number-of-markdown={eol}
       data-end-line-number-of-markdown={eol}
-      data-growi-rendering="true"
+      {...{ [GROWI_RENDERING_ATTR]: 'true' }}
     >
     >
       {/* show error */}
       {/* show error */}
       {error != null && (
       {error != null && (

+ 3 - 2
packages/remark-drawio/src/services/renderer/remark-drawio.ts

@@ -1,3 +1,4 @@
+import { GROWI_RENDERING_ATTR } from '@growi/core/dist/consts';
 import type { Properties } from 'hast';
 import type { Properties } from 'hast';
 import type { Schema as SanitizeOption } from 'hast-util-sanitize';
 import type { Schema as SanitizeOption } from 'hast-util-sanitize';
 import type { Code, Node, Paragraph } from 'mdast';
 import type { Code, Node, Paragraph } from 'mdast';
@@ -9,7 +10,7 @@ const SUPPORTED_ATTRIBUTES = [
   'bol',
   'bol',
   'eol',
   'eol',
   'isDarkMode',
   'isDarkMode',
-  'data-growi-rendering',
+  GROWI_RENDERING_ATTR,
 ];
 ];
 
 
 interface Data {
 interface Data {
@@ -40,7 +41,7 @@ function rewriteNode(node: Node, index: number, isDarkMode?: boolean) {
     eol: node.position?.end.line,
     eol: node.position?.end.line,
     isDarkMode: isDarkMode ? 'true' : 'false',
     isDarkMode: isDarkMode ? 'true' : 'false',
     key: `drawio-${index}`,
     key: `drawio-${index}`,
-    'data-growi-rendering': 'true',
+    [GROWI_RENDERING_ATTR]: 'true',
   };
   };
 }
 }