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

Merge pull request #10707 from growilabs/copilot/restore-semantic-html-tags

imprv: Restore semantic HTML tags lost in v7.0.10 refactoring
mergify[bot] 2 месяцев назад
Родитель
Сommit
44e221b025

+ 100 - 1
apps/app/src/services/renderer/recommended-whitelist.spec.ts

@@ -1,4 +1,4 @@
-import { notDeepEqual } from 'assert';
+import assert from 'assert';
 
 import { attributes, tagNames } from './recommended-whitelist';
 
@@ -80,4 +80,103 @@ describe('recommended-whitelist', () => {
       'data-footnote-backref',
     ]);
   });
+
+  // Tests for restored semantic HTML tags
+  describe('semantic HTML tags restored from v6.3.5', () => {
+    test('.tagNames should include abbr tag', () => {
+      expect(tagNames).toContain('abbr');
+    });
+
+    test('.tagNames should include bdo tag', () => {
+      expect(tagNames).toContain('bdo');
+    });
+
+    test('.tagNames should include caption tag', () => {
+      expect(tagNames).toContain('caption');
+    });
+
+    test('.tagNames should include cite tag', () => {
+      expect(tagNames).toContain('cite');
+    });
+
+    test('.tagNames should include dfn tag', () => {
+      expect(tagNames).toContain('dfn');
+    });
+
+    test('.tagNames should include figure tag', () => {
+      expect(tagNames).toContain('figure');
+    });
+
+    test('.tagNames should include figcaption tag', () => {
+      expect(tagNames).toContain('figcaption');
+    });
+
+    test('.tagNames should include mark tag', () => {
+      expect(tagNames).toContain('mark');
+    });
+
+    test('.tagNames should include small tag', () => {
+      expect(tagNames).toContain('small');
+    });
+
+    test('.tagNames should include time tag', () => {
+      expect(tagNames).toContain('time');
+    });
+
+    test('.tagNames should include wbr tag', () => {
+      expect(tagNames).toContain('wbr');
+    });
+  });
+
+  describe('attributes for semantic HTML tags', () => {
+    test('.attributes should have abbr with title attribute', () => {
+      expect(attributes).not.toBeNull();
+      assert(attributes != null);
+      expect(Object.keys(attributes)).toContain('abbr');
+      expect(attributes.abbr).toContain('title');
+    });
+
+    test('.attributes should have bdo with dir attribute', () => {
+      expect(attributes).not.toBeNull();
+      assert(attributes != null);
+      expect(Object.keys(attributes)).toContain('bdo');
+      expect(attributes.bdo).toContain('dir');
+    });
+
+    test('.attributes should have dfn with title attribute', () => {
+      expect(attributes).not.toBeNull();
+      assert(attributes != null);
+      expect(Object.keys(attributes)).toContain('dfn');
+      expect(attributes.dfn).toContain('title');
+    });
+
+    test('.attributes should have time with datetime attribute', () => {
+      expect(attributes).not.toBeNull();
+      assert(attributes != null);
+      expect(Object.keys(attributes)).toContain('time');
+      expect(attributes.time).toContain('datetime');
+    });
+
+    test('.attributes should have empty arrays for tags without specific attributes', () => {
+      expect(attributes).not.toBeNull();
+
+      // Tags that should have empty attribute arrays
+      const tagsWithEmptyAttributes = [
+        'caption',
+        'cite',
+        'figure',
+        'figcaption',
+        'mark',
+        'small',
+        'wbr',
+      ];
+
+      tagsWithEmptyAttributes.forEach((tag) => {
+        assert(attributes != null);
+
+        expect(Object.keys(attributes)).toContain(tag);
+        expect(attributes[tag]).toEqual([]);
+      });
+    });
+  });
 });

+ 23 - 1
apps/app/src/services/renderer/recommended-whitelist.ts

@@ -47,21 +47,43 @@ relaxedSchemaAttributes.li = excludeRestrictedClassAttributes(
 export const tagNames: Array<string> = [
   ...(defaultSchema.tagNames ?? []),
   '-',
+  'abbr',
+  'bdo',
   'bdi',
   'button',
+  'caption',
+  'cite',
   'col',
   'colgroup',
   'data',
+  'dfn',
+  'figure',
+  'figcaption',
   'iframe',
-  'video',
+  'mark',
   'rb',
+  'small',
+  'time',
   'u',
+  'video',
+  'wbr',
 ];
 
 export const attributes: Attributes = deepmerge(relaxedSchemaAttributes, {
   a: ['target'],
+  abbr: ['title'],
+  bdo: ['dir'],
+  caption: [],
+  cite: [],
+  dfn: ['title'],
+  figure: [],
+  figcaption: [],
   iframe: ['allow', 'referrerpolicy', 'sandbox', 'src'],
+  mark: [],
+  small: [],
+  time: ['datetime'],
   video: ['controls', 'src', 'muted', 'preload', 'width', 'height', 'autoplay'],
+  wbr: [],
   // The special value 'data*' as a property name can be used to allow all data properties.
   // see: https://github.com/syntax-tree/hast-util-sanitize/
   '*': ['key', 'class', 'className', 'style', 'role', 'data*'],