mirror of
https://gitee.com/antv/g6.git
synced 2024-11-30 02:38:20 +08:00
feat(utils): add print util (#6020)
* feat(utils): add print util * refactor: migrate console to print
This commit is contained in:
parent
9ec96d0cc2
commit
e3b1d48745
@ -8,6 +8,6 @@ describe('bugs:continuous-invoke', () => {
|
||||
await graph.render();
|
||||
});
|
||||
|
||||
expect(fn).rejects.toThrow('Graph has been destroyed');
|
||||
expect(fn).rejects.toThrow();
|
||||
});
|
||||
});
|
||||
|
52
packages/g6/__tests__/unit/utils/print.spec.ts
Normal file
52
packages/g6/__tests__/unit/utils/print.spec.ts
Normal file
@ -0,0 +1,52 @@
|
||||
import { version } from '@/src';
|
||||
import { print } from '@/src/utils/print';
|
||||
|
||||
describe('print', () => {
|
||||
it('print', () => {
|
||||
const spy = jest.spyOn(console, 'debug').mockImplementation();
|
||||
print.debug('debug message');
|
||||
expect(spy).toHaveBeenCalledWith(`[G6 v${version}] debug message`);
|
||||
spy.mockRestore();
|
||||
|
||||
const spy2 = jest.spyOn(console, 'info').mockImplementation();
|
||||
print.info('info message');
|
||||
expect(spy2).toHaveBeenCalledWith(`[G6 v${version}] info message`);
|
||||
spy2.mockRestore();
|
||||
|
||||
const spy3 = jest.spyOn(console, 'warn').mockImplementation();
|
||||
print.warn('warn message');
|
||||
expect(spy3).toHaveBeenCalledWith(`[G6 v${version}] warn message`);
|
||||
spy3.mockRestore();
|
||||
|
||||
const spy4 = jest.spyOn(console, 'error').mockImplementation();
|
||||
print.error('error message');
|
||||
expect(spy4).toHaveBeenCalledWith(`[G6 v${version}] error message`);
|
||||
spy4.mockRestore();
|
||||
});
|
||||
|
||||
it('print mute', () => {
|
||||
print.mute = true;
|
||||
|
||||
const spy = jest.spyOn(console, 'debug').mockImplementation();
|
||||
print.debug('debug message');
|
||||
expect(spy).not.toHaveBeenCalled();
|
||||
spy.mockRestore();
|
||||
|
||||
const spy2 = jest.spyOn(console, 'info').mockImplementation();
|
||||
print.info('info message');
|
||||
expect(spy2).not.toHaveBeenCalled();
|
||||
spy2.mockRestore();
|
||||
|
||||
const spy3 = jest.spyOn(console, 'warn').mockImplementation();
|
||||
print.warn('warn message');
|
||||
expect(spy3).not.toHaveBeenCalled();
|
||||
spy3.mockRestore();
|
||||
|
||||
const spy4 = jest.spyOn(console, 'error').mockImplementation();
|
||||
print.error('error message');
|
||||
expect(spy4).not.toHaveBeenCalled();
|
||||
spy4.mockRestore();
|
||||
|
||||
print.mute = false;
|
||||
});
|
||||
});
|
@ -1,6 +1,7 @@
|
||||
import type { ID, IElementDragEvent, Point } from '../types';
|
||||
import { idOf } from '../utils/id';
|
||||
import { getLayoutProperty, invokeLayoutMethod } from '../utils/layout';
|
||||
import { print } from '../utils/print';
|
||||
import { add } from '../utils/vector';
|
||||
import type { DragElementOptions } from './drag-element';
|
||||
import { DragElement } from './drag-element';
|
||||
@ -37,7 +38,7 @@ export class DragElementForce extends DragElement {
|
||||
|
||||
// 未使用力导布局 / The force layout is not used
|
||||
if (!this.forceLayoutInstance) {
|
||||
console.warn('DragElementForce only works with d3-force or d3-force-3d layout');
|
||||
print.warn('DragElementForce only works with d3-force or d3-force-3d layout');
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
import type { RuntimeContext } from '../../runtime/types';
|
||||
import { print } from '../../utils/print';
|
||||
import type { ShortcutKey } from '../../utils/shortcut';
|
||||
import { Shortcut } from '../../utils/shortcut';
|
||||
import type { BasePluginOptions } from '../base-plugin';
|
||||
@ -123,7 +124,7 @@ export class Fullscreen extends BasePlugin<FullscreenOptions> {
|
||||
public request() {
|
||||
if (document.fullscreenElement || !isFullscreenEnabled()) return;
|
||||
this.$el.requestFullscreen().catch((err: Error) => {
|
||||
console.debug(`Error attempting to enable full-screen: ${err.message} (${err.name})`);
|
||||
print.warn(`Error attempting to enable full-screen: ${err.message} (${err.name})`);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -5,6 +5,7 @@ import type { RuntimeContext } from '../../runtime/types';
|
||||
import type { IEvent } from '../../types';
|
||||
import { arrayDiff } from '../../utils/diff';
|
||||
import { parseExtensions } from '../../utils/extension';
|
||||
import { print } from '../../utils/print';
|
||||
import type { STDExtensionOption } from './types';
|
||||
|
||||
export abstract class ExtensionController<E extends BaseExtension<any>> {
|
||||
@ -42,7 +43,7 @@ export abstract class ExtensionController<E extends BaseExtension<any>> {
|
||||
|
||||
const { key, type } = extension;
|
||||
const Ctor = getExtension(category, type);
|
||||
if (!Ctor) return;
|
||||
if (!Ctor) return print.warn(`The extension ${type} of ${category} is not registered.`);
|
||||
|
||||
const instance = new Ctor(this.context, extension);
|
||||
this.extensionMap[key] = instance as E;
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { ExtensionCategory } from '../constants';
|
||||
import type { Loosen } from '../types';
|
||||
import { print } from '../utils/print';
|
||||
import { BUILT_IN_EXTENSIONS } from './build-in';
|
||||
import type { ExtensionRegistry } from './types';
|
||||
|
||||
@ -58,7 +59,7 @@ export function register<T extends ExtensionCategory>(
|
||||
) {
|
||||
const ext = EXTENSION_REGISTRY[category][type];
|
||||
if (ext) {
|
||||
if (ext !== Ctor) console.error(`The extension ${type} of ${category} has been registered before.`);
|
||||
if (ext !== Ctor) print.warn(`The extension ${type} of ${category} has been registered before.`);
|
||||
} else Object.assign(EXTENSION_REGISTRY[category]!, { [type]: Ctor });
|
||||
}
|
||||
|
||||
|
@ -25,6 +25,7 @@ import { arrayDiff } from '../utils/diff';
|
||||
import { toG6Data, toGraphlibData } from '../utils/graphlib';
|
||||
import { idOf, parentIdOf } from '../utils/id';
|
||||
import { positionOf } from '../utils/position';
|
||||
import { format, print } from '../utils/print';
|
||||
import { dfs } from '../utils/traverse';
|
||||
import { add } from '../utils/vector';
|
||||
|
||||
@ -188,7 +189,7 @@ export class DataController {
|
||||
public getParentData(id: ID, hierarchyKey: HierarchyKey): NodeLikeData | undefined {
|
||||
const { model } = this;
|
||||
if (!hierarchyKey) {
|
||||
console.error('The hierarchy structure key is not specified');
|
||||
print.warn('The hierarchy structure key is not specified');
|
||||
return undefined;
|
||||
}
|
||||
if (!model.hasNode(id) || !model.hasTreeStructure(hierarchyKey)) return undefined;
|
||||
@ -761,7 +762,7 @@ export class DataController {
|
||||
|
||||
if (this.model.hasEdge(id)) return 'edge';
|
||||
|
||||
throw new Error(`Unknown element type of id: ${id}`);
|
||||
throw new Error(format(`Unknown element type of id: ${id}`));
|
||||
}
|
||||
|
||||
public destroy() {
|
||||
|
@ -31,6 +31,7 @@ import { AnimateEvent, ElementLifeCycleEvent, GraphLifeCycleEvent, emit } from '
|
||||
import { idOf } from '../utils/id';
|
||||
import { assignColorByPalette, parsePalette } from '../utils/palette';
|
||||
import { positionOf } from '../utils/position';
|
||||
import { print } from '../utils/print';
|
||||
import { computeElementCallbackStyle } from '../utils/style';
|
||||
import { themeOf } from '../utils/theme';
|
||||
import type { RuntimeContext } from './types';
|
||||
@ -366,7 +367,7 @@ export class ElementController {
|
||||
|
||||
// get shape constructor
|
||||
const Ctor = getExtension(elementType, type);
|
||||
if (!Ctor) return;
|
||||
if (!Ctor) return print.warn(`The element ${type} of ${elementType} is not registered.`);
|
||||
|
||||
this.emit(new ElementLifeCycleEvent(GraphEvent.BEFORE_ELEMENT_CREATE, elementType, datum), context);
|
||||
|
||||
@ -791,7 +792,7 @@ export interface DrawContext {
|
||||
animation: boolean;
|
||||
/** <zh/> 当前绘制阶段 | <en/> Current draw stage */
|
||||
stage?: AnimationStage;
|
||||
/** <zh/> 是否不抛出事件 | <en/> Whether not to throw events */
|
||||
/** <zh/> 是否不抛出事件 | <en/> Whether not to dispatch events */
|
||||
silence?: boolean;
|
||||
/** <zh/> 收起/展开的对象 ID | <en/> ID of the object to collapse/expand */
|
||||
collapseExpandTarget?: ID;
|
||||
|
@ -45,6 +45,7 @@ import { sizeOf } from '../utils/dom';
|
||||
import { GraphLifeCycleEvent, emit } from '../utils/event';
|
||||
import { idOf } from '../utils/id';
|
||||
import { parsePoint, toPointObject } from '../utils/point';
|
||||
import { format } from '../utils/print';
|
||||
import { subtract } from '../utils/vector';
|
||||
import { Animation } from './animation';
|
||||
import { BatchController } from './batch';
|
||||
@ -1078,7 +1079,7 @@ export class Graph extends EventEmitter {
|
||||
// Wait for synchronous tasks to complete, to avoid problems caused by calling destroy immediately after render
|
||||
await Promise.resolve();
|
||||
|
||||
if (this.destroyed) throw new Error('Graph has been destroyed');
|
||||
if (this.destroyed) throw new Error(format('The graph instance has been destroyed'));
|
||||
|
||||
await this.initCanvas();
|
||||
this.initRuntime();
|
||||
|
@ -15,6 +15,7 @@ import { GraphLifeCycleEvent, emit } from '../utils/event';
|
||||
import { createTreeStructure } from '../utils/graphlib';
|
||||
import { idOf } from '../utils/id';
|
||||
import { isTreeLayout, layoutAdapter, layoutMapping2GraphData } from '../utils/layout';
|
||||
import { print } from '../utils/print';
|
||||
import { parseSize } from '../utils/size';
|
||||
import { dfs } from '../utils/traverse';
|
||||
import type { RuntimeContext } from './types';
|
||||
@ -103,6 +104,8 @@ export class LayoutController {
|
||||
const { animation, enableWorker, iterations = 300 } = options;
|
||||
|
||||
const layout = this.initGraphLayout(options);
|
||||
if (!layout) return {};
|
||||
|
||||
this.instances[index] = layout;
|
||||
this.instance = layout;
|
||||
|
||||
@ -142,7 +145,7 @@ export class LayoutController {
|
||||
// @ts-expect-error @antv/hierarchy 布局格式与 @antv/layout 不一致,其导出的是一个方法,而非 class
|
||||
// The layout format of @antv/hierarchy is inconsistent with @antv/layout, it exports a method instead of a class
|
||||
const layout = getExtension('layout', type) as (tree: TreeData, options: STDLayoutOptions) => TreeData;
|
||||
if (!layout) throw new Error(`The layout type ${type} is not found`);
|
||||
if (!layout) return {};
|
||||
|
||||
const { nodes = [], edges = [] } = data;
|
||||
|
||||
@ -256,7 +259,7 @@ export class LayoutController {
|
||||
});
|
||||
|
||||
const Ctor = getExtension('layout', type);
|
||||
if (!Ctor) throw new Error(`The layout type ${type} is not found`);
|
||||
if (!Ctor) return print.warn(`The layout of ${type} is not registered.`);
|
||||
|
||||
const STDCtor =
|
||||
Object.getPrototypeOf(Ctor.prototype) === BaseLayout.prototype
|
||||
|
@ -1,11 +1,12 @@
|
||||
import type { IAnimation } from '@antv/g';
|
||||
import { isEqual, isNil, isObject, isString } from '@antv/util';
|
||||
import { isEqual, isNil, isObject } from '@antv/util';
|
||||
import type { AnimationEffectTiming, AnimationOptions, STDAnimation } from '../animations/types';
|
||||
import { DEFAULT_ANIMATION_OPTIONS, DEFAULT_ELEMENTS_ANIMATION_OPTIONS, ExtensionCategory } from '../constants';
|
||||
import { getExtension } from '../registry';
|
||||
import type { GraphOptions } from '../spec';
|
||||
import type { AnimationStage } from '../spec/element/animation';
|
||||
import type { ElementType, Keyframe } from '../types';
|
||||
import { print } from './print';
|
||||
import { themeOf } from './theme';
|
||||
|
||||
export function createAnimationsProxy(animations: IAnimation[]): IAnimation | null;
|
||||
@ -161,7 +162,13 @@ export function getAnimationOptions(
|
||||
* @returns <zh/> 动画配置 | <en/> animation configuration
|
||||
*/
|
||||
function animationOf(options: string | AnimationOptions[]): STDAnimation {
|
||||
if (isString(options)) return getExtension(ExtensionCategory.ANIMATION, options) || [];
|
||||
if (typeof options === 'string') {
|
||||
const animation = getExtension(ExtensionCategory.ANIMATION, options);
|
||||
if (animation) return animation;
|
||||
|
||||
print.warn(`The animation of ${options} is not registered.`);
|
||||
return [];
|
||||
}
|
||||
return options;
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
import type { ComboData, EdgeData, GraphData, NodeData } from '../spec';
|
||||
import type { DataID, ID } from '../types';
|
||||
import { format } from './print';
|
||||
|
||||
/**
|
||||
* <zh/> 获取节点/边/Combo 的 ID
|
||||
@ -12,7 +13,7 @@ export function idOf(data: Partial<NodeData | EdgeData | ComboData>): ID {
|
||||
if (data.id !== undefined) return data.id;
|
||||
if (data.source !== undefined && data.target !== undefined) return `${data.source}-${data.target}`;
|
||||
|
||||
throw new Error('The data does not have available id.');
|
||||
throw new Error(format('The datum does not have available id.'));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -5,6 +5,7 @@ import type { PaletteOptions, STDPaletteOptions } from '../spec/element/palette'
|
||||
import type { ID } from '../types';
|
||||
import type { ElementData, ElementDatum } from '../types/data';
|
||||
import { idOf } from './id';
|
||||
import { format } from './print';
|
||||
|
||||
/**
|
||||
* <zh/> 解析色板配置
|
||||
@ -99,7 +100,7 @@ export function assignColorByPalette(data: ElementData, palette?: STDPaletteOpti
|
||||
const [min, max] = data.reduce(
|
||||
([min, max], datum) => {
|
||||
const value = parseField(field, datum);
|
||||
if (typeof value !== 'number') throw new Error(`Palette field ${field} is not a number`);
|
||||
if (typeof value !== 'number') throw new Error(format(`Palette field ${field} is not a number`));
|
||||
return [Math.min(min, value), Math.max(max, value)];
|
||||
},
|
||||
[Infinity, -Infinity],
|
||||
|
30
packages/g6/src/utils/print.ts
Normal file
30
packages/g6/src/utils/print.ts
Normal file
@ -0,0 +1,30 @@
|
||||
import { version } from '../version';
|
||||
|
||||
const BRAND = 'G6';
|
||||
|
||||
/**
|
||||
* <zh/> 格式化打印
|
||||
*
|
||||
* <en/> Format print
|
||||
* @param message - <zh/> 消息 | <en/> Message
|
||||
* @returns <zh/> 格式化后的消息 | <en/> Formatted message
|
||||
*/
|
||||
export function format(message: string) {
|
||||
return `[${BRAND} v${version}] ${message}`;
|
||||
}
|
||||
|
||||
export const print = {
|
||||
mute: false,
|
||||
debug: (message: string): void => {
|
||||
!print.mute && console.debug(format(message));
|
||||
},
|
||||
info: (message: string): void => {
|
||||
!print.mute && console.info(format(message));
|
||||
},
|
||||
warn: (message: string): void => {
|
||||
!print.mute && console.warn(format(message));
|
||||
},
|
||||
error: (message: string): void => {
|
||||
!print.mute && console.error(format(message));
|
||||
},
|
||||
};
|
@ -1,6 +1,7 @@
|
||||
import { ExtensionCategory } from '../constants';
|
||||
import { getExtension } from '../registry';
|
||||
import type { GraphOptions } from '../spec';
|
||||
import { print } from './print';
|
||||
|
||||
/**
|
||||
* <zh/> 获取主题配置
|
||||
@ -14,5 +15,9 @@ export function themeOf(options: GraphOptions) {
|
||||
if (!theme) return {};
|
||||
|
||||
const themeOptions = getExtension(ExtensionCategory.THEME, theme);
|
||||
return themeOptions ?? {};
|
||||
|
||||
if (themeOptions) return themeOptions;
|
||||
|
||||
print.warn(`The theme of ${theme} is not registered.`);
|
||||
return {};
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user