diff --git a/NOTICE.md b/NOTICE.md
index ee0f75d15c..41e8ed91c4 100644
--- a/NOTICE.md
+++ b/NOTICE.md
@@ -52,7 +52,6 @@ Code copied from project eclipse-theia/theia
- Source:
- https://github.com/opensumi/core/blob/main/packages/core-browser/src/keyboard/keyboard-layout-service.ts
- https://github.com/opensumi/core/blob/main/packages/core-browser/src/keyboard/keys.ts
- - https://github.com/opensumi/core/blob/main/packages/core-browser/src/utils/parse.ts
- https://github.com/opensumi/core/blob/main/packages/core-common/src/problem-matcher.ts
- https://github.com/opensumi/core/blob/main/packages/core-common/src/problem-pattern.ts
- https://github.com/opensumi/core/blob/main/packages/core-common/src/keyboard/keyboard-layout-provider.ts
diff --git a/packages/core-browser/__tests__/utils/parse.test.ts b/packages/core-browser/__tests__/utils/parse.test.ts
deleted file mode 100644
index b6ee612447..0000000000
--- a/packages/core-browser/__tests__/utils/parse.test.ts
+++ /dev/null
@@ -1,34 +0,0 @@
-import { LabelIcon, parseLabel } from '../../src/utils/parse';
-
-describe('it can parse', () => {
- it('can parse label with icon', () => {
- const labels = parseLabel('$(hello) world');
- expect(labels).toHaveLength(2);
- expect((labels[0] as LabelIcon).name).toEqual('hello');
- });
- it('can parse label with multiple icon', () => {
- const labels = parseLabel('$(hello) world $(qwq)');
- expect(labels).toHaveLength(3);
- expect((labels[0] as LabelIcon).name).toEqual('hello');
- expect((labels[2] as LabelIcon).name).toEqual('qwq');
- });
-
- it('can parse label with icon animation', () => {
- const labels = parseLabel('$(hello~spin) world $(qwq)');
- expect(labels).toHaveLength(3);
- expect((labels[0] as LabelIcon).name).toEqual('hello');
- expect((labels[0] as LabelIcon).owner).toBeUndefined();
- expect((labels[0] as LabelIcon).animation).toEqual('spin');
- expect((labels[2] as LabelIcon).name).toEqual('qwq');
- expect((labels[2] as LabelIcon).owner).toBeUndefined();
- });
- it('can parse label with icon owner', () => {
- const labels = parseLabel('$(kt/hello~spin) world $(qwq)');
- expect(labels).toHaveLength(3);
- expect((labels[0] as LabelIcon).name).toEqual('hello');
- expect((labels[0] as LabelIcon).animation).toEqual('spin');
- expect((labels[0] as LabelIcon).owner).toEqual('kt');
- expect((labels[2] as LabelIcon).name).toEqual('qwq');
- expect((labels[2] as LabelIcon).owner).toBeUndefined();
- });
-});
diff --git a/packages/core-browser/src/utils/index.ts b/packages/core-browser/src/utils/index.ts
index 38522f32a6..606c2f53f3 100644
--- a/packages/core-browser/src/utils/index.ts
+++ b/packages/core-browser/src/utils/index.ts
@@ -2,6 +2,5 @@ export * from './env';
export * from './electron';
export * from './react-hooks';
export * from './icon';
-export * from './parse';
export * from './json';
export * from './label';
diff --git a/packages/core-browser/src/utils/label.tsx b/packages/core-browser/src/utils/label.tsx
index f0aeb597e6..f90e3311e7 100644
--- a/packages/core-browser/src/utils/label.tsx
+++ b/packages/core-browser/src/utils/label.tsx
@@ -1,3 +1,4 @@
+import clx from 'classnames';
import React, { CSSProperties } from 'react';
import { Icon } from '@opensumi/ide-components/lib/icon/icon';
@@ -7,30 +8,42 @@ const SEPERATOR = ' ';
export function transformLabelWithCodicon(
label: string,
- iconStyles: CSSProperties = {},
+ iconStyleProps: CSSProperties | string = {},
transformer?: (str: string) => string | undefined,
renderText?: (str: string, index: number) => React.ReactNode,
) {
const ICON_REGX = /\$\(([a-z.]+\/)?([a-z-]+)(~[a-z]+)?\)/gi;
const ICON_WITH_ANIMATE_REGX = /\$\(([a-z.]+\/)?([a-z-]+)~([a-z]+)\)/gi;
+ // some string like $() $(~spin)
+ const ICON_ERROR_REGX = /\$\(([a-z.]+\/)?([a-z-]+)?(~[a-z]+)?\)/gi;
+
+ const generateIconStyle = (icon?: string, styleProps?: CSSProperties | string) =>
+ typeof styleProps === 'string' ? { className: clx(icon, styleProps) } : { className: icon, style: styleProps };
+
return label.split(SEPERATOR).map((e, index) => {
if (!transformer) {
return e;
}
const icon = transformer(e);
if (icon) {
- return ;
+ return ;
} else if (ICON_REGX.test(e)) {
if (e.includes('~')) {
const [, , icon, animate] = ICON_WITH_ANIMATE_REGX.exec(e) || [];
if (animate && icon) {
return (
-
+
);
}
}
const newStr = e.replaceAll(ICON_REGX, (e) => `${SEPERATOR}${e}${SEPERATOR}`);
- return transformLabelWithCodicon(newStr, iconStyles, transformer);
+ return transformLabelWithCodicon(newStr, iconStyleProps, transformer);
+ } else if (ICON_ERROR_REGX.test(e)) {
+ return transformLabelWithCodicon(e.replaceAll(ICON_ERROR_REGX, ''), iconStyleProps, transformer, renderText);
} else {
return isFunction(renderText) ? renderText(e, index) : {e};
}
diff --git a/packages/core-browser/src/utils/parse.ts b/packages/core-browser/src/utils/parse.ts
deleted file mode 100644
index 879de8fb70..0000000000
--- a/packages/core-browser/src/utils/parse.ts
+++ /dev/null
@@ -1,82 +0,0 @@
-/** ******************************************************************************
- * Copyright (C) 2018 Red Hat, Inc. and others.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v. 2.0 which is available at
- * http://www.eclipse.org/legal/epl-2.0.
- *
- * This Source Code may also be made available under the following Secondary
- * Licenses when the conditions for such availability set forth in the Eclipse
- * Public License v. 2.0 are satisfied: GNU General Public License, version 2
- * with the GNU Classpath Exception which is available at
- * https://www.gnu.org/software/classpath/license.html.
- *
- * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
- ********************************************************************************/
-// Some code copied and modified from https://github.com/eclipse-theia/theia/tree/v1.14.0/packages/core/src/browser/label-parser.ts
-
-export interface LabelIcon {
- name: string;
- owner?: string;
- animation?: string;
-}
-
-export namespace LabelIcon {
- export function is(val: object): val is LabelIcon {
- return 'name' in val;
- }
-}
-
-export type LabelPart = string | LabelIcon;
-
-export function parseLabel(text: string): LabelPart[] {
- const parserArray: LabelPart[] = [];
- let arrPointer = 0;
- let potentialIcon = '';
-
- for (let idx = 0; idx < text.length; idx++) {
- const char = text.charAt(idx);
- parserArray[arrPointer] = parserArray[arrPointer] || '';
- if (potentialIcon === '') {
- if (char === '$') {
- potentialIcon += char;
- } else {
- parserArray[arrPointer] += char;
- }
- } else if (potentialIcon === '$') {
- if (char === '(') {
- potentialIcon += char;
- } else {
- parserArray[arrPointer] += potentialIcon + char;
- potentialIcon = '';
- }
- } else {
- if (char === ')') {
- const iconClassArr = potentialIcon.substring(2, potentialIcon.length).split('~');
- let name = iconClassArr[0];
- let owner: string | undefined;
- if (name) {
- const index = name.indexOf('/');
- if (index !== -1) {
- owner = name.substring(0, index);
- name = name.substring(index + 1);
- }
- }
- if (parserArray[arrPointer] !== '') {
- arrPointer++;
- }
- parserArray[arrPointer] = { name, owner, animation: iconClassArr[1] };
- arrPointer++;
- potentialIcon = '';
- } else {
- potentialIcon += char;
- }
- }
- }
-
- if (potentialIcon !== '') {
- parserArray[arrPointer] += potentialIcon;
- }
-
- return parserArray;
-}
diff --git a/packages/quick-open/src/browser/components/highlight-label/index.tsx b/packages/quick-open/src/browser/components/highlight-label/index.tsx
index d071c72d94..b89ed4081b 100644
--- a/packages/quick-open/src/browser/components/highlight-label/index.tsx
+++ b/packages/quick-open/src/browser/components/highlight-label/index.tsx
@@ -1,18 +1,9 @@
-import React from 'react';
+import React, { ReactChild } from 'react';
-import { getExternalIcon, LabelIcon, LabelPart, parseLabel } from '@opensumi/ide-core-browser';
+import { transformLabelWithCodicon } from '@opensumi/ide-core-browser';
import { Highlight } from '@opensumi/ide-core-browser/lib/quick-open';
-import { strings } from '@opensumi/ide-core-common';
-
-const { escape } = strings;
-
-const labelWithIcons = (str: string, iconClassName?: string) =>
- parseLabel(escape(str)).reduce((pre: string | LabelPart, cur: LabelPart) => {
- if (!(typeof cur === 'string') && LabelIcon.is(cur)) {
- return pre + ``;
- }
- return pre + cur;
- }, '');
+import { useInjectable } from '@opensumi/ide-core-browser/lib/react-hooks';
+import { IIconService } from '@opensumi/ide-theme';
export interface HighlightLabelProp {
text?: string;
@@ -33,8 +24,10 @@ export const HighlightLabel: React.FC = ({
hightLightClassName = '',
OutElementType = 'span',
}) => {
+ const iconService = useInjectable(IIconService);
+
const renderLabel = React.useMemo(() => {
- const children: string[] = [];
+ const children: ReactChild[] = [];
let pos = 0;
for (const highlight of highlights) {
@@ -43,26 +36,36 @@ export const HighlightLabel: React.FC = ({
}
if (pos < highlight.start) {
const substring = text.substring(pos, highlight.start);
- children.push(`${labelWithIcons(substring, labelIconClassName)}`);
+ children.push(
+
+ {transformLabelWithCodicon(substring, labelIconClassName, iconService.fromString.bind(iconService))}
+ ,
+ );
pos = highlight.end;
}
const substring = text.substring(highlight.start, highlight.end);
- children.push(`${labelWithIcons(substring, labelIconClassName)}`);
+ children.push(
+
+ {transformLabelWithCodicon(substring, labelIconClassName, iconService.fromString.bind(iconService))}
+ ,
+ );
pos = highlight.end;
}
if (pos < text.length) {
const substring = text.substring(pos);
- children.push(`${labelWithIcons(substring, labelIconClassName)}`);
+ children.push(
+
+ {transformLabelWithCodicon(substring, labelIconClassName, iconService.fromString.bind(iconService))}
+ ,
+ );
}
- return children.join('');
+ return children;
}, [text, highlights]);
return (
-
+ // @ts-ignore
+
+ {renderLabel}
+
);
};
diff --git a/packages/quick-open/src/browser/quick-open.view.tsx b/packages/quick-open/src/browser/quick-open.view.tsx
index df2b162bde..6ca80ab9df 100644
--- a/packages/quick-open/src/browser/quick-open.view.tsx
+++ b/packages/quick-open/src/browser/quick-open.view.tsx
@@ -257,6 +257,8 @@ const QuickOpenItemView: React.FC = observer(({ data, index
{iconClass && }
= observer(({ data, index
= observer(({ data, index
OutElementType='div'
className={styles.item_label_detail}
labelClassName={clx(styles.label_icon_container, styles.item_label_description_label)}
- labelIconClassName={styles.label_has_icon}
+ labelIconClassName={clx(styles.label_has_icon, styles.item_label_detail_icon)}
hightLightClassName={clx(styles.item_label_description_highlight)}
text={detail}
highlights={detailHighlights}
diff --git a/packages/quick-open/src/browser/styles.module.less b/packages/quick-open/src/browser/styles.module.less
index bc96f27c59..1a245d16d6 100644
--- a/packages/quick-open/src/browser/styles.module.less
+++ b/packages/quick-open/src/browser/styles.module.less
@@ -117,6 +117,10 @@
white-space: pre;
}
+ .item_label_name_icon {
+ font-size: 14px;
+ }
+
.item_label_description_label {
color: var(--descriptionForeground);
}
@@ -134,7 +138,9 @@
}
.item_label_description,
- .item_label_detail {
+ .item_label_detail,
+ .itam_label_description_icon,
+ .item_label_detail_icon {
font-size: 12px;
}