Initial commit

This commit is contained in:
Phenom 2021-01-28 17:01:16 +08:00
commit 6c7b0d8a07
22 changed files with 1274 additions and 0 deletions

2
.gitattributes vendored Normal file
View File

@ -0,0 +1,2 @@
# Auto detect text files and perform LF normalization
* text=auto

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
node_modules

2
README.md Normal file
View File

@ -0,0 +1,2 @@
# StructV2

14
atlconfig.json Normal file
View File

@ -0,0 +1,14 @@
{
"compilerOptions": {
"target": "ES2015",
"module": "commonJS",
"removeComments": true
},
"exclude": [
"node_modules"
]
}

1
dist/sv.js vendored Normal file

File diff suppressed because one or more lines are too long

14
package.json Normal file
View File

@ -0,0 +1,14 @@
{
"dependencies": {
"awesome-typescript-loader": "^5.2.1",
"typescript": "^3.2.2",
"webpack": "^4.28.2",
"zrender": "^5.0.3"
},
"devDependencies": {
"webpack-cli": "^3.2.3"
},
"scripts": {
"build": "tsc && webpack"
}
}

116
src/Common/util.ts Normal file
View File

@ -0,0 +1,116 @@
import * as zrender from "zrender";
/**
*
*/
export const Util = {
/**
* id
*/
generateId(): string {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
        let r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8);
        return v.toString(16);
    });
},
/**
*
* @param origin
* @param ext
*/
extends(origin, ext) {
zrender.util.extend(origin, ext);
},
/**
*
* @param origin
* @param dest
*/
merge(origin, dest) {
zrender.util.merge(origin, dest, true);
},
/**
*
* @param list
* @param fn
*/
removeFromList<T>(list: T[], fn: (item: T) => boolean) {
for(let i = 0; i < list.length; i++) {
fn(list[i]) && list.splice(i, 1) && i--;
}
},
/**
*
* @param path
*/
getPathCenter(path: Array<[number, number]>): [number, number] {
let maxX = -Infinity,
minX = Infinity,
maxY = -Infinity,
minY = Infinity;
path.map(item => {
if(item[0] > maxX) maxX = item[0];
if(item[0] < minX) minX = item[0];
if(item[1] > maxY) maxY = item[1];
if(item[1] < minY) minY = item[1];
});
return [(maxX + minX) / 2, (maxY + minY) / 2];
},
/**
*
* @param assertFn
* @param errorText
*/
assert(condition: boolean, errorText: string): void | never {
if(condition) {
throw errorText;
}
},
/**
*
* @param classConstructor
*/
getClassName(classConstructor): string {
return classConstructor.prototype.constructor.toString().split(' ')[1];
},
/**
*
* @param text
*/
textParser(text: string): string[] | string {
let fieldReg = /\[[^\]]*\]/g;
if(fieldReg.test(text)) {
let contents = text.match(fieldReg),
values = contents.map(item => item.replace(/\[|\]/g, ''));
return values;
}
else {
return text;
}
},
/**
*
* @param value
*/
clamp(value: number, max: number, min: number): number {
if(value <= max && value >= min) return value;
if(value > max) return max;
if(value < min) return min;
}
};

219
src/Common/vector.ts Normal file
View File

@ -0,0 +1,219 @@
// 二维向量 {x, y}
export class Vector {
public x: number;
public y: number;
constructor(x?: number, y?: number) {
this.x = 0;
this.y = 0;
if(x !== undefined && y !== undefined) {
this.set(x, y);
}
}
//-------------操作----------------
/**
*
* @param x
* @param y
*/
set(x: number, y: number) {
this.x = x;
this.y = y;
}
/**
*
* @param v
*/
add(v: Vector, out?: Vector): Vector {
out = out || new Vector();
out.x = this.x + v.x;
out.y = this.y + v.y;
return out;
}
/**
*
* @param v
*/
sub(v: Vector, out?: Vector): Vector {
out = out || new Vector();
out.x = this.x - v.x;
out.y = this.y - v.y;
return out;
}
/**
*
* @param v
*/
dot(v: Vector): number {
return this.x * v.x + this.y * v.y;
}
/**
*
* @param v
*/
cro(v: Vector): number {
return this.x * v.y - v.x * this.y;
}
/**
*
* @param n
*/
croNum(n: number, out?: Vector): Vector {
out = out || new Vector();
out.x = -n * this.y;
out.y = n * this.x;
return out;
}
/**
*
* @param v
*/
pro(v: Vector): number {
return this.dot(v) / v.len();
}
/**
*
*/
nor(out?: Vector): Vector {
out = out || new Vector();
out.x = this.y;
out.y = -this.x;
return out;
}
/**
*
*/
len(): number {
return Math.hypot(this.x, this.y);
}
/**
*
*/
len_s(): number {
return this.x * this.x + this.y * this.y;
}
/**
*
*/
nol(): Vector {
let len = this.len();
if(len === 0) {
return new Vector();
}
this.x = this.x / len;
this.y = this.y / len;
return this;
}
/**
*
* @param n
*/
scl(n: number, out?: Vector): Vector {
out = out || new Vector();
out.x = n * this.x;
out.y = n * this.y;
return out;
}
/**
*
*/
inv(out?: Vector): Vector {
out = out || new Vector();
out.x = -this.x;
out.y = -this.y;
return out;
}
/**
*
* @param v
*/
eql(v: Vector): boolean {
return this.x === v.x && this.y === v.y;
}
/**
* ()
* @param v
*/
ang(v: Vector): number {
return Math.acos(this.dot(v) / (this.len() * v.len()));
}
/**
*
*/
col(): Vector {
return new Vector(this.x, this.y);
}
/**
*
* @param radian
* @param point
*/
rot(radian: number, point: Vector, out?: Vector): Vector {
out = out || new Vector();
let cos = Math.cos(radian),
sin = Math.sin(radian),
dx = this.x - point.x,
dy = this.y - point.y;
out.x = point.x + (dx * cos - dy * sin);
out.y = point.y + (dx * sin + dy * cos);
return out;
}
/**
* direction方向len长度后的坐标
* @param direction
* @param len
*/
loc(direction: Vector, len: number, out?: Vector): Vector {
out = out || new Vector();
direction = direction.nol();
out.x = this.x + direction.x * len;
out.y = this.y + direction.y * len;
return out;
}
};
export const _tempVector1 = new Vector();
export const _tempVector2 = new Vector();
export const _tempVector3 = new Vector();
export const _tempVector4 = new Vector();

163
src/Model/element.ts Normal file
View File

@ -0,0 +1,163 @@
import { Util } from "../Common/util";
import { SourceElement } from "../sources";
import { Shape, ShapeStatus } from "../View/shape";
import { zrShape } from "../View/shapeScheduler";
import { Link } from "./link";
import { Pointer } from "./pointer";
export interface Style {
// 填充颜色
fill: string;
// 图形文本
text: string;
// 文本颜色
textFill: string;
// 字体大小
fontSize: number;
// 字重
fontWeight: number;
// 描边样式
stroke: string;
// 透明度
opacity: number;
// 线宽
lineWidth: number;
// 其余属性免得每次新增属性都要声明一个新的子interface
[key: string]: any;
}
export interface ElementStatus {
x: number;
y: number;
rotation: number;
width: number;
height: number;
zIndex: number;
content: string;
style: Style;
};
export class Element {
id: any;
elementId: string = null;
elementLabel: string = null;
elementStatus: ElementStatus = null;
zrShape: zrShape[] = [];
relativeLinks: Link[] = [];
relativePointers: Pointer[] = [];
isDirty: boolean= false;
// 给sourceElement的部分
[key: string]: any;
constructor(elementLabel: string, sourceElement: SourceElement) {
this.elementLabel = elementLabel;
Object.keys(sourceElement).map(prop => {
this[prop] = sourceElement[prop];
});
this.elementStatus = {
x: 0, y: 0,
rotation: 0,
width: 0,
height: 0,
zIndex: 1,
content: '',
style: {
fill: '#000',
text: '',
textFill: '#000',
fontSize: 15,
fontWeight: null,
stroke: null,
opacity: 1,
transformText: true,
lineWidth: 1
}
};
}
/**
* set方法elementStatus的值
* @param propName
* @param value
*/
set(propName: string, value: any) {
if(this.elementStatus[propName] !== undefined) {
this.elementStatus[propName] = value;
}
this.setDirty(true);
}
/**
*
* @param isDirty
*/
setDirty(isDirty: boolean) {
this.isDirty = isDirty;
}
/**
* element映射的图形
* @param shapes
* @param elementStatus
* @override
*/
renderShape(shapes: Shape[] | Shape, elementStatus: ElementStatus) { }
/**
* shapeOptions
* @param shapeOptions
*/
applyShapeOptions(shapeOptions: Partial<ShapeStatus>) {
Util.extends(this.elementStatus, shapeOptions);
}
// ------------------------------- 钩子方法 ------------------------------
onClick(event: any) { }
/**
*
* @param targetEle
*/
onLinkTo(targetEle: Element) {};
/**
*
* @param emitEle
*/
onLinkFrom(emitEle: Element) {};
/**
*
* @param targetEle
*/
onUnLinkTo(targetEle: Element) {}
/**
*
* @param emitEle
*/
onUnLinkFrom(emitEle: Element) {}
/**
*
*/
onRefer() {}
/**
*
*/
onUnRefer() {}
};

View File

@ -0,0 +1,155 @@
import { Engine } from "../engine";
import { SourceElement, Sources } from "../sources";
import { Shape, ShapeStatus } from "../View/shape";
import { ZrShapeConstructor } from "../View/shapeScheduler";
import { Element } from "./element";
// 元素集类型
export type ElementContainer = { [key: string]: Element[] };
export type ElementConstructor = { new(elementLabel: string, sourceElement: SourceElement): Element };
export class ElementScheduler {
private engine: Engine;
// 元素队列
private elementList: Element[] = [];
// 元素容器即源数据经element包装后的结构
private elementContainer: ElementContainer = {};
private elementMap: {
[key: string]: {
elementConstructor: ElementConstructor,
zrShapeConstructors: ZrShapeConstructor[] | ZrShapeConstructor,
shapeOptions: Partial<ShapeStatus>
}
};
constructor(engine: Engine) {
this.engine = engine;
}
/**
*
* @param elementLabel
* @param elementConstructor
* @param zrShapeConstructors
* @param shapeOptions
*/
setElementMap(
elementLabel: string,
elementConstructor: ElementConstructor,
zrShapeConstructors: ZrShapeConstructor[] | ZrShapeConstructor,
shapeOptions: Partial<ShapeStatus>
) {
this.elementMap[elementLabel] = {
elementConstructor,
zrShapeConstructors,
shapeOptions
};
}
/**
* element
*
* - SourceElement Element
* -
* -
* @param sourceData
*/
constructElements(sourceData: Sources) {
if(Array.isArray(sourceData)) {
this.elementContainer['element'] = [];
sourceData.forEach(item => {
if(item) {
let ele = this.createElement(item, 'element');
this.elementContainer['element'].push(ele);
this.elementList.push(ele);
}
});
}
else {
Object.keys(sourceData).forEach(prop => {
this.elementContainer[prop] = [];
sourceData[prop].forEach(item => {
if(item) {
let ele = this.createElement(item, prop);
this.elementContainer[prop].push(ele);
this.elementList.push(ele);
}
});
});
}
}
/**
* Element
* @param sourceElement
* @param elementLabel
*/
private createElement(sourceElement: SourceElement, elementLabel: string): Element {
let elementInfo = this.elementMap[elementLabel],
shapes: Shape[] | Shape;
if(elementInfo === undefined) {
return null;
}
let { elementConstructor, zrShapeConstructors, shapeOptions } = elementInfo,
element: Element = null,
elementId = `${elementLabel}#${sourceElement.id}`;
element = new elementConstructor(elementLabel, sourceElement);
element.applyShapeOptions(shapeOptions);
if(Array.isArray(zrShapeConstructors)) {
shapes = zrShapeConstructors.map((item, index) => new Shape(`${elementId}(${index})`, item, element));
}
else {
shapes = new Shape(`elementId`, zrShapeConstructors, element);
}
element.defineShape(shapes, element.elementStatus);
return element;
}
public updateShapes() {
for(let i = 0; i < this.elementList.length; i++) {
let ele = this.elementList[i];
if(ele.isDirty) {
ele.renderShape();
}
}
}
/**
* element元素
*/
public getElementContainer(): ElementContainer | Element[] {
let keys = Object.keys(this.elementContainer);
if(keys.length === 1 && keys[0] === 'element') {
return this.elementContainer['element'];
}
return this.elementContainer;
}
/**
* element列表
*/
public getElementList(): Element[] {
return this.elementList;
}
/**
*
*/
public reset() {
this.elementList.length = 0;
this.elementContainer = {};
}
};

43
src/Model/link.ts Normal file
View File

@ -0,0 +1,43 @@
import { LinkTarget } from "../sources";
import { zrShape } from "../View/shapeScheduler";
import { Element, Style } from "./element";
import { LabelStyle } from "./pointer";
export interface LinkOptions {
style: Style;
labelStyle: LabelStyle;
};
export class Link {
// 连线 id
id: string;
// 连线起始 element
element: Element;
// 连线目标 element
target: Element;
// 连线类型名称
linkName: string;
// 连线图形实例
zrShapes: zrShape[];
// 连线序号
index: number;
// 连线在源数据的声明
sourceLinkTarget: LinkTarget;
isDirty: boolean = false;
constructor() {
}
/**
*
* @param isDirty
*/
setDirty(isDirty: boolean) {
this.isDirty = isDirty;
}
};

View File

@ -0,0 +1,53 @@
import { ShapeStatus } from "../View/shape";
import { ZrShapeConstructor } from "../View/shapeScheduler";
import { Element, Style } from "./element";
import { Link } from "./link";
export interface LinkOptions {
style: Style;
};
export class LinkScheduler {
private links: Link[] = [];
private prevLinks: Link[] = [];
private linkMap: {
[key: string]: {
linkConstructor: { new(): Link },
zrShapeConstructors: ZrShapeConstructor[] | ZrShapeConstructor,
shapeOptions: Partial<ShapeStatus>
}
};
constructor() {
}
/**
*
* @param elementList
*/
constructLinks(elementList: Element[]) {
}
setLinkMap(
linkLabel: string,
linkConstructor: { new(): Link },
zrShapeConstructors: ZrShapeConstructor[] | ZrShapeConstructor,
shapeOptions: Partial<ShapeStatus>
) {
this.linkMap[linkLabel] = {
linkConstructor,
zrShapeConstructors,
shapeOptions
};
}
reset() {
this.links.length = 0;
}
}

53
src/Model/pointer.ts Normal file
View File

@ -0,0 +1,53 @@
import { zrShape } from "../View/shapeScheduler";
import { Style } from "./element";
export interface LabelStyle extends Style {
textBackgroundColor: 'rgba(0, 0, 0, 1)',
textFill: '#fff',
textPadding: [4, 4, 4, 4]
};
export interface PointerOptions {
labelStyle: LabelStyle;
style: Style;
};
export class Pointer {
// 指针 id
id: string;
// 指针图形实例
zrShapes: zrShape[];
// 指针类型名称
pointerLabel: string;
// 被该指针合并的其他指针
branchPointer: Pointer[];
// 若该指针是一个被合并的指针,保存合并这个指针的主指针
masterPointer: Pointer;
// 指针标签内容
text: string;
// 指针标签图形实例
textZrShapes: Text[];
// 逗号图形实例
commaShapes: Text[];
// 目标 element
target: Element;
isDirty: boolean = false;
constructor() {
}
/**
*
* @param isDirty
*/
setDirty(isDirty: boolean) {
this.isDirty = isDirty;
}
};

View File

@ -0,0 +1,55 @@
import { ShapeStatus } from "../View/shape";
import { ZrShapeConstructor } from "../View/shapeScheduler";
import { Element, Style } from "./element";
import { Pointer } from "./pointer";
export interface PointerOptions {
style: Style;
};
export class PointerScheduler {
private pointers: Pointer[] = [];
private prevPointers: Pointer[] = [];
private pointerMap: {
[key: string]: {
pointerConstructor: { new(): Pointer },
zrShapeConstructors: ZrShapeConstructor[] | ZrShapeConstructor,
shapeOptions: Partial<ShapeStatus>
}
};
constructor() {
}
/**
*
* @param elementList
*/
constructPointers(elementList: Element[]) {
}
setPointerMap(
pointerLabel: string,
pointerConstructor: { new(): Pointer },
zrShapeConstructors: ZrShapeConstructor[] | ZrShapeConstructor,
shapeOptions: Partial<ShapeStatus>
) {
this.pointerMap[pointerLabel] = {
pointerConstructor,
zrShapeConstructors,
shapeOptions
};
}
reset() {
this.pointers.length = 0;
}
};

18
src/StructV.ts Normal file
View File

@ -0,0 +1,18 @@
import { Engine } from "./engine";
export const SV = {
createEngine(engineName: string): Engine {
return new Engine(engineName);
},
};

0
src/View/renderer.ts Normal file
View File

81
src/View/shape.ts Normal file
View File

@ -0,0 +1,81 @@
import { Util } from "../Common/util";
import { Element, Style } from "../Model/element";
import { zrShape, ZrShapeConstructor } from "./shapeScheduler";
export interface ShapeStatus {
x: number;
y: number;
rotation: number;
zIndex: number;
width: number;
height: number;
content: string;
style: Style;
};
export class Shape {
id: string = '';
type: string = '';
zrConstructor: ZrShapeConstructor = null;
zrShape: zrShape = null;
targetElement: Element = null;
shapeStatus: ShapeStatus = {
x: 0, y: 0,
rotation: 0,
width: 0,
height: 0,
zIndex: 1,
content: '',
style: {
fill: '#000',
text: '',
textFill: '#000',
fontSize: 15,
fontWeight: null,
stroke: null,
opacity: 1,
transformText: true,
lineWidth: 1
}
};
constructor(id: string, zrConstructor: ZrShapeConstructor, element: Element) {
this.id = id;
this.type = Util.getClassName(zrConstructor);
this.targetElement = element;
this.zrConstructor = zrConstructor;
this.zrShape = new zrConstructor();
}
/**
*
* @param propName
* @param props
* @param sync
*/
attr(propName: string, props: any, sync: boolean = false) {
if(this.shapeStatus[propName] === undefined) return;
if(propName === 'style') {
Util.merge(this.shapeStatus.style, props);
}
else {
this.shapeStatus[propName] = props;
}
if(sync) {
this.zrShape.attr(propName, props);
}
}
updateShape() {
}
};

View File

@ -0,0 +1,96 @@
import { Util } from "../Common/util";
import { Engine } from "../engine";
import { Shape } from "./shape";
import * as zrender from "zrender";
import { Element } from "../Model/element";
export type zrShape = any;
export type ZrShapeConstructor = { new(): zrShape };
export class ShapeScheduler {
private engine: Engine;
private shapeList: Shape[] = [];
private shapeTable: { [key: string]: Shape[] } = {};
private appendList: Shape[] = [];
private removeList: Shape[] = [];
constructor(engine: Engine) {
this.engine = engine;
}
/**
*
* @param id
* @param zrShapeConstructors
* @param element
*/
createShape(id: string, zrShapeConstructors: ZrShapeConstructor, element: Element): Shape {
let shapeType = Util.getClassName(zrShapeConstructors),
shape = this.getReuseShape(id, shapeType);
if(shape === null) {
shape = new Shape(id, zrShapeConstructors, element);
}
return shape;
}
/**
*
* @param shape
*/
private appendShape(shape: Shape) {
let shapeType = shape.type;
if(this.shapeTable[shapeType] === undefined) {
this.shapeTable[shapeType] = [];
}
this.shapeTable[shapeType].push(shape);
this.shapeList.push(shape);
this.appendList.push(shape);
}
/**
*
* @param shape
*/
private removeShape(shape: Shape) {
let shapeType = shape.type;
Util.removeFromList(this.shapeTable[shapeType], item => item.id === shape.id);
if(this.shapeTable[shapeType].length === 0) {
delete this.shapeTable[shapeType];
}
Util.removeFromList(this.shapeList, item => item.id === shape.id);
this.removeList.push(shape);
}
/**
*
* @param id
* @param shapeType
*/
private getReuseShape(id: string, shapeType: string): Shape {
if(this.shapeTable[shapeType] !== undefined) {
let reuseShape = this.shapeTable[shapeType].find(item => item.id === id);
if(reuseShape) return reuseShape;
}
return null;
}
/**
*
*/
public reset() {
this.appendList.length = 0;
this.removeList.length = 0;
}
};

117
src/engine.ts Normal file
View File

@ -0,0 +1,117 @@
import { Element } from "./Model/element";
import { Sources } from "./sources";
import { Pointer } from "./Model/pointer";
import { ShapeStatus } from "./View/shape";
import { ShapeScheduler, ZrShapeConstructor } from "./View/shapeScheduler";
import { ElementConstructor, ElementContainer, ElementScheduler } from "./Model/elementScheduler";
import { Link } from "./Model/link";
import { LinkScheduler } from "./Model/linkScheduler";
import { PointerScheduler } from "./Model/pointerScheduler";
export type LayoutFunction = (elements: ElementContainer | Element[], containerWidth: number, containerHeight: number) => void;
export class Engine {
// 引擎id
private id: string;
// 引擎名称
private engineName: string;
// HTML容器
private DOMContainer: HTMLElement;
// 当前保存的源数据
private sources: Sources = null;
// 序列化的源数据
private stringifySources: string = null;
private elementScheduler: ElementScheduler = null;
private linkScheduler: LinkScheduler = null;
private pointerScheduler: PointerScheduler = null;
private shapeScheduler: ShapeScheduler = null;
private containerWidth: number;
private containerHeight: number;
private layoutFunction: LayoutFunction;
constructor(DOMContainer: HTMLElement, engineName: string) {
this.engineName = engineName;
this.DOMContainer = DOMContainer;
this.elementScheduler = new ElementScheduler(this);
this.linkScheduler = new LinkScheduler();
this.pointerScheduler = new PointerScheduler();
this.shapeScheduler = new ShapeScheduler(this);
this.containerWidth = this.DOMContainer.offsetWidth;
this.containerHeight = this.DOMContainer.offsetHeight;
}
public render(sourceData: Sources) {
if(sourceData === undefined || sourceData === null) {
return;
}
// 若前后数据没有发生变化什么也不干将json字符串化后比较
let stringifySources = JSON.stringify(sourceData);
if(stringifySources === this.stringifySources) return;
this.sources = sourceData;
this.stringifySources = stringifySources;
this.elementScheduler.constructElements(sourceData);
this.linkScheduler.constructLinks([]);
this.pointerScheduler.constructPointers([]);
this.layoutFunction(this.elementScheduler.getElementContainer(), this.containerWidth, this.containerHeight);
}
/**
*
* @param elementLabel
* @param element
* @param zrShapeConstructors
* @param shapeOptions
*/
public applyElement(
elementLabel: string,
elementConstructor: ElementConstructor,
zrShapeConstructors: ZrShapeConstructor[] | ZrShapeConstructor,
shapeOptions: Partial<ShapeStatus>
) {
this.elementScheduler.setElementMap(elementLabel, elementConstructor, zrShapeConstructors, shapeOptions);
}
public applyLink(
linkLabel: string, linkConstructor: { new(): Link },
zrShapeConstructors: ZrShapeConstructor[] | ZrShapeConstructor,
shapeOptions: Partial<ShapeStatus>
) {
this.linkScheduler.setLinkMap(linkLabel, linkConstructor, zrShapeConstructors, shapeOptions);
}
public applyPointer(
pointerLabel: string, pointerConstructor: { new(): Pointer },
zrShapeConstructors: ZrShapeConstructor[] | ZrShapeConstructor,
shapeOptions: Partial<ShapeStatus>
) {
this.pointerScheduler.setPointerMap(pointerLabel, pointerConstructor, zrShapeConstructors, shapeOptions);
}
/**
*
* @param layoutFunction
*/
public applyLayout(layoutFunction: LayoutFunction) {
this.layoutFunction = layoutFunction;
}
/**
*
*/
private resetData() {
this.elementScheduler.reset();
this.linkScheduler.reset();
this.pointerScheduler.reset();
this.shapeScheduler.reset();
}
};

26
src/sources.ts Normal file
View File

@ -0,0 +1,26 @@
// 连接目标信息
export type LinkTarget = {
element: string;
target: number | string;
[key: string]: any;
} | number | string;
// 结点连接声明
export type LinkData = LinkTarget | LinkTarget[];
// 结点指针声明
export type PointerData = string | string[];
// 源数据单元
export interface SourceElement {
id: string | number;
[key: string]: any | LinkData | PointerData;
}
// 源数据格式
export type Sources = { } | SourceElement[];

17
tsconfig.json Normal file
View File

@ -0,0 +1,17 @@
{
"compilerOptions": {
"target": "ES2015",
"module": "commonJS",
"experimentalDecorators": true,
//"outDir": "./../Demos/src/StructV",
"outDir": "./../Visualizer/src/StructV",
"declaration": true
},
"exclude": [
"node_modules", "examples"
]
}

28
webpack.config.js Normal file
View File

@ -0,0 +1,28 @@
const path = require('path');
module.exports = {
entry: './src/StructV.ts',
output: {
filename: './sv.js',
//path: path.resolve(__dirname, './../Visualizer/src/StructV'),
libraryTarget: 'umd'
},
resolve: {
// 先尝试以ts为后缀的TypeScript源码文件
extensions: ['.ts', '.js']
},
module: {
rules: [
{
test: /\.ts$/,
exclude: /node_modules/,
loader: 'awesome-typescript-loader',
options: {
configFileName: './atlconfig.json'
}
}
]
},
//devtool: 'eval-source-map'
};