refactor: refactor scripts

This commit is contained in:
chenshenhai 2022-12-31 23:21:57 +08:00
parent ed1fb05e84
commit 7e0e0b765a
52 changed files with 3888 additions and 5518 deletions

11
.prettierrc.json Normal file
View file

@ -0,0 +1,11 @@
{
"tabWidth": 2,
"useTabs": false,
"endOfLine": "auto",
"singleQuote": true,
"semi": true,
"trailingComma": "none",
"bracketSpacing": true
}

7
.vscode/extensions.json vendored Normal file
View file

@ -0,0 +1,7 @@
{
"recommendations": [
"rvest.vs-code-prettier-eslint",
"dbaeumer.vscode-eslint",
"esbenp.prettier-vscode"
]
}

14
.vscode/settings.json vendored Normal file
View file

@ -0,0 +1,14 @@
{
"editor.formatOnSave": true,
"eslint.format.enable": true,
"prettier.configPath": ".prettierrc.json",
"[typescript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[typescriptreact]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[json]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
}
}

View file

@ -1,15 +1,15 @@
{
"name": "root",
"private": false,
"type": "module",
"scripts": {
"postinstall": "npm run build",
"dev": "node ./scripts/dev.js",
"dev:rollup": "node ./scripts/dev-rollup.js",
"dev": "vite-node ./scripts/dev.ts",
"dev:rollup": "vite-node ./scripts/dev-rollup.ts",
"build": "npm run build:mod && npm run build:bundle && npm run build:min",
"build:bundle": "NODE_ENV=production BUILD_MODE=reset node ./scripts/build-bundle.js",
"build:mod": "node ./scripts/build-module.js",
"build:min": "node ./scripts/minify.js",
"snapshot": "npm run build:bundle && node ./scripts/snapshot.js",
"build:bundle": "vite-node ./scripts/build-bundle.ts",
"build:mod": "vite-node ./scripts/build-module.ts",
"build:min": "vite-node ./scripts/minify.ts",
"snapshot": "npm run build:bundle && vite-node ./scripts/snapshot.ts",
"e2e": "mocha --exit ./__tests__/e2e.test.js",
"init": "lerna bootstrap",
"init:cnpm": "lerna bootstrap --npm-client=cnpm",
@ -26,51 +26,53 @@
"clear:jest": "rm -rf ./packages/*/__tests__/__snapshots__",
"pu": "npm run build && lerna publish --force-publish",
"pu2": "lerna version && npm run build && lerna publish from-git --force-publish",
"hello": "node ./scripts/hello.js"
"hello": "vite-node ./scripts/hello.js"
},
"devDependencies": {
"@babel/core": "^7.13.14",
"@babel/preset-env": "^7.13.12",
"@babel/preset-typescript": "^7.13.0",
"@microsoft/api-extractor": "^7.13.2",
"@rollup/plugin-json": "^4.1.0",
"@rollup/plugin-node-resolve": "^11.2.1",
"@rollup/plugin-typescript": "^8.3.0",
"@rollup/pluginutils": "^4.1.1",
"@types/jest": "^29.2.0",
"@typescript-eslint/eslint-plugin": "^4.25.0",
"@typescript-eslint/parser": "^4.25.0",
"babel-jest": "^26.6.3",
"canvas": "^2.8.0",
"chalk": "^4.1.2",
"@babel/core": "^7.20.7",
"@babel/preset-env": "^7.20.2",
"@babel/preset-typescript": "^7.18.6",
"@microsoft/api-extractor": "^7.33.7",
"@rollup/plugin-json": "^6.0.0",
"@rollup/plugin-node-resolve": "^15.0.1",
"@rollup/plugin-typescript": "^10.0.1",
"@rollup/pluginutils": "^5.0.2",
"@types/jest": "^29.2.5",
"@types/node": "^18.11.18",
"@typescript-eslint/eslint-plugin": "^5.47.1",
"@typescript-eslint/parser": "^5.47.1",
"babel-jest": "^29.3.1",
"canvas": "^2.11.0",
"chalk": "^5.2.0",
"enquirer": "^2.3.6",
"eslint": "^7.27.0",
"execa": "^5.0.0",
"fs-extra": "^9.1.0",
"glob": "^7.2.0",
"http-server": "^0.12.3",
"husky": "^6.0.0",
"jest": "^26.6.3",
"jest-canvas-mock": "^2.3.1",
"jimp": "^0.16.1",
"eslint": "^8.31.0",
"execa": "^6.1.0",
"fs-extra": "^11.1.0",
"glob": "^8.0.3",
"http-server": "^14.1.1",
"husky": "^8.0.2",
"jest": "^29.3.1",
"jest-canvas-mock": "^2.4.0",
"jimp": "^0.16.2",
"koa-compose": "^4.1.0",
"lerna": "^3.22.1",
"less": "^4.1.1",
"mocha": "^8.3.2",
"pixelmatch": "^5.2.1",
"lerna": "^6.3.0",
"less": "^4.1.3",
"mocha": "^10.2.0",
"pixelmatch": "^5.3.0",
"pngjs": "^6.0.0",
"postcss": "^8.2.9",
"puppeteer": "^8.0.0",
"rollup": "^2.40.0",
"postcss": "^8.4.20",
"puppeteer": "^19.4.1",
"rollup": "^3.9.0",
"rollup-plugin-cleanup": "^3.2.1",
"rollup-plugin-postcss": "^4.0.0",
"rollup-plugin-postcss": "^4.0.2",
"rollup-plugin-terser": "^7.0.2",
"rollup-plugin-typescript2": "^0.31.0",
"serve-handler": "^6.1.3",
"terser": "^5.9.0",
"ts-node": "^9.1.1",
"tslib": "^2.3.1",
"typescript": "^4.5.4",
"vite": "^2.7.10"
"rollup-plugin-typescript2": "^0.34.1",
"serve-handler": "^6.1.5",
"terser": "^5.16.1",
"ts-node": "^10.9.1",
"tslib": "^2.4.1",
"typescript": "^4.9.4",
"vite": "^4.0.3",
"vite-node": "^0.26.2"
}
}

View file

@ -1,4 +1,4 @@
import { Board } from './../src/esm';
import Board from './../src/esm';
function drawBoard(board) {
const ctx = board.getContext();
@ -28,9 +28,9 @@ const opts = {
contextWidth: 300,
contextHeight: 200,
devicePixelRatio: 4,
canScroll: true,
}
const board = new Board(mount, opts);
canScroll: true
};
const board = new Board(mount, opts);
drawBoard(board);
board.draw();
@ -39,7 +39,7 @@ board.resetSize({
height: 180,
contextWidth: 400,
contextHeight: 320,
devicePixelRatio: 4,
devicePixelRatio: 4
});
drawBoard(board);
board.draw();
board.draw();

View file

@ -2,18 +2,13 @@
"name": "@idraw/board",
"version": "0.3.0-alpha.6",
"description": "",
"main": "dist/index.cjs.js",
"module": "dist/index.esm.js",
"main": "dist/esm/index.js",
"module": "dist/esm/index.js",
"unpkg": "dist/index.global.js",
"types": "dist/index.d.ts",
"scripts": {
"dev": "vite dev"
},
"types": "dist/esm/index.d.ts",
"files": [
"dist/*.ts",
"dist/*.js",
"esm/*.ts",
"esm/*.js"
"dist/**/*.ts",
"dist/**/*.js"
],
"repository": {
"type": "git",

View file

@ -1 +0,0 @@
export * as default from './index';

View file

@ -1,3 +0,0 @@
export * from './index';
export * as default from './index';

View file

@ -1,6 +1,12 @@
import {
TypeScreenPosition, TypeScreenSize, TypeScreenContext, TypePoint, TypePointCursor,
TypeBoardOptions, TypeBoardSizeOptions, TypeContext,
import {
TypeScreenPosition,
TypeScreenSize,
TypeScreenContext,
TypePoint,
TypePointCursor,
TypeBoardOptions,
TypeBoardSizeOptions,
TypeContext
} from '@idraw/types';
import util from '@idraw/util';
import { ScreenWatcher } from './lib/screen-watcher';
@ -13,18 +19,32 @@ import { Screen } from './lib/screen';
const { throttle, Context } = util;
import {
_canvas, _displayCanvas, _mount, _opts, _hasRendered, _ctx,
_watcher, _render, _parsePrivateOptions, _scroller, _helperCanvas, _helperCtx,
_initEvent, _doScrollX, _doScrollY, _doMoveScroll, _resetContext,
_screen, _tempData
_canvas,
_displayCanvas,
_mount,
_opts,
_hasRendered,
_ctx,
_watcher,
_render,
_parsePrivateOptions,
_scroller,
_helperCanvas,
_helperCtx,
_initEvent,
_doScrollX,
_doScrollY,
_doMoveScroll,
_resetContext,
_screen,
_tempData
} from './names';
type PrivateOptions = TypeBoardOptions & {
devicePixelRatio: number
}
export class Board {
devicePixelRatio: number;
};
export default class Board {
private [_hasRendered] = false;
private [_canvas]: HTMLCanvasElement;
@ -50,21 +70,26 @@ export class Board {
this[_mount].appendChild(this[_displayCanvas]);
this[_opts] = this[_parsePrivateOptions](opts);
const originCtx2d = this[_canvas].getContext('2d') as CanvasRenderingContext2D;
const displayCtx2d = this[_displayCanvas].getContext('2d') as CanvasRenderingContext2D;
const helperCtx2d = this[_helperCanvas].getContext('2d') as CanvasRenderingContext2D;
const originCtx2d = this[_canvas].getContext(
'2d'
) as CanvasRenderingContext2D;
const displayCtx2d = this[_displayCanvas].getContext(
'2d'
) as CanvasRenderingContext2D;
const helperCtx2d = this[_helperCanvas].getContext(
'2d'
) as CanvasRenderingContext2D;
this[_ctx] = new Context(originCtx2d, this[_opts]);
this[_helperCtx] = new Context(helperCtx2d, this[_opts]);
this[_screen] = new Screen(this[_ctx], this[_opts]);
// this[_watcher] = new Watcher(this[_displayCanvas]);
this[_watcher] = new ScreenWatcher(this[_displayCanvas], this[_ctx]);
this[_scroller] = new Scroller(
displayCtx2d, {
width: opts.width,
height: opts.height,
devicePixelRatio: opts.devicePixelRatio || 1,
scrollConfig: opts.scrollConfig,
});
this[_scroller] = new Scroller(displayCtx2d, {
width: opts.width,
height: opts.height,
devicePixelRatio: opts.devicePixelRatio || 1,
scrollConfig: opts.scrollConfig
});
this[_render]();
}
@ -94,7 +119,7 @@ export class Board {
this[_helperCtx].setTransform({ scale: scaleRatio });
}
const { position, size } = this[_screen].calcScreen();
return { position, size};
return { position, size };
}
scrollX(x: number) {
@ -102,20 +127,27 @@ export class Board {
canScrollYPrev: true,
canScrollYNext: true,
canScrollXPrev: true,
canScrollXNext: true,
})
canScrollXNext: true
});
if (x >= 0 || x < 0) {
this[_ctx].setTransform({ scrollX: x });
this[_helperCtx].setTransform({ scrollX: x })
this[_helperCtx].setTransform({ scrollX: x });
}
const { position, size, canScrollXNext, canScrollYNext, canScrollXPrev, canScrollYPrev } = this[_screen].calcScreen();
const {
position,
size,
canScrollXNext,
canScrollYNext,
canScrollXPrev,
canScrollYPrev
} = this[_screen].calcScreen();
this[_watcher].setStatusMap({
canScrollYPrev,
canScrollYNext,
canScrollXPrev,
canScrollXNext,
})
return { position, size};
canScrollXNext
});
return { position, size };
}
scrollY(y: number): TypeScreenContext {
@ -123,20 +155,27 @@ export class Board {
canScrollYPrev: true,
canScrollYNext: true,
canScrollXPrev: true,
canScrollXNext: true,
})
canScrollXNext: true
});
if (y >= 0 || y < 0) {
this[_ctx].setTransform({ scrollY: y });
this[_helperCtx].setTransform({ scrollY: y });
}
const { position, size, canScrollXNext, canScrollYNext, canScrollXPrev, canScrollYPrev } = this[_screen].calcScreen();
const {
position,
size,
canScrollXNext,
canScrollYNext,
canScrollXPrev,
canScrollYPrev
} = this[_screen].calcScreen();
this[_watcher].setStatusMap({
canScrollYPrev,
canScrollYNext,
canScrollXPrev,
canScrollXNext,
})
return { position, size};
canScrollXNext
});
return { position, size };
}
getTransform() {
@ -148,10 +187,18 @@ export class Board {
const { position, deviceSize, size } = this[_screen].calcScreen();
const displayCtx = this[_displayCanvas].getContext('2d');
displayCtx?.drawImage(
this[_canvas], deviceSize.x, deviceSize.y, deviceSize.w, deviceSize.h
this[_canvas],
deviceSize.x,
deviceSize.y,
deviceSize.w,
deviceSize.h
);
displayCtx?.drawImage(
this[_helperCanvas], deviceSize.x, deviceSize.y, deviceSize.w, deviceSize.h
this[_helperCanvas],
deviceSize.x,
deviceSize.y,
deviceSize.w,
deviceSize.h
);
if (this[_opts].canScroll === true) {
this[_scroller].draw(position);
@ -161,21 +208,36 @@ export class Board {
clear() {
const displayCtx = this[_displayCanvas].getContext('2d');
displayCtx?.clearRect(0, 0, this[_displayCanvas].width, this[_displayCanvas].height);
displayCtx?.clearRect(
0,
0,
this[_displayCanvas].width,
this[_displayCanvas].height
);
}
on<T extends keyof TypeBoardEventArgMap >(name: T, callback: (p: TypeBoardEventArgMap[T]) => void) {
on<T extends keyof TypeBoardEventArgMap>(
name: T,
callback: (p: TypeBoardEventArgMap[T]) => void
) {
this[_watcher].on(name, callback);
}
off<T extends keyof TypeBoardEventArgMap >(name: T, callback: (p: TypeBoardEventArgMap[T]) => void) {
off<T extends keyof TypeBoardEventArgMap>(
name: T,
callback: (p: TypeBoardEventArgMap[T]) => void
) {
this[_watcher].off(name, callback);
}
getScreenInfo(): {
size: TypeScreenSize, position: TypeScreenPosition, deviceSize: TypeScreenSize,
width: number, height: number, devicePixelRatio: number
} {
size: TypeScreenSize;
position: TypeScreenPosition;
deviceSize: TypeScreenSize;
width: number;
height: number;
devicePixelRatio: number;
} {
return this[_screen].calcScreen();
}
@ -213,7 +275,7 @@ export class Board {
const { scrollX, scrollY, scale } = this.getTransform();
const ctxPoint = {
x: (screenPoint.x - scrollX) / scale,
y: (screenPoint.y - scrollY) / scale,
y: (screenPoint.y - scrollY) / scale
};
return ctxPoint;
}
@ -222,12 +284,11 @@ export class Board {
const { scrollX, scrollY, scale } = this.getTransform();
const screenPoint = {
x: ctxPoint.x * scale + scrollX,
y: ctxPoint.y * scale + scrollY,
y: ctxPoint.y * scale + scrollY
};
return screenPoint;
}
private [_render]() {
if (this[_hasRendered] === true) {
return;
@ -237,8 +298,9 @@ export class Board {
this[_hasRendered] = true;
}
private [_resetContext] () {
const { width, height, contextWidth, contextHeight, devicePixelRatio } = this[_opts];
private [_resetContext]() {
const { width, height, contextWidth, contextHeight, devicePixelRatio } =
this[_opts];
this[_canvas].width = contextWidth * devicePixelRatio;
this[_canvas].height = contextHeight * devicePixelRatio;
@ -250,13 +312,13 @@ export class Board {
setStyle(this[_displayCanvas], {
width: `${width}px`,
height: `${height}px`,
height: `${height}px`
});
}
private [_parsePrivateOptions](opts: TypeBoardOptions): PrivateOptions {
const defaultOpts = {
devicePixelRatio: 1,
devicePixelRatio: 1
};
return { ...defaultOpts, ...opts };
}
@ -266,35 +328,49 @@ export class Board {
return;
}
if (this[_opts].canScroll === true) {
this.on('wheelX', throttle((deltaX) => {
this[_doScrollX](deltaX);
}, 16));
this.on('wheelY', throttle((deltaY: number) => {
this[_doScrollY](deltaY);
}, 16));
this.on(
'wheelX',
throttle((deltaX) => {
this[_doScrollX](deltaX);
}, 16)
);
this.on(
'wheelY',
throttle((deltaY: number) => {
this[_doScrollY](deltaY);
}, 16)
);
let scrollType: 'x' | 'y' | null = null;
this.on('moveStart', throttle((p: TypePoint) => {
if (this[_scroller].isPointAtScrollX(p)) {
scrollType = 'x';
} else if (this[_scroller].isPointAtScrollY(p)) {
scrollType = 'y';
}
}, 16));
this.on(
'moveStart',
throttle((p: TypePoint) => {
if (this[_scroller].isPointAtScrollX(p)) {
scrollType = 'x';
} else if (this[_scroller].isPointAtScrollY(p)) {
scrollType = 'y';
}
}, 16)
);
this.on('move', throttle((p: TypePoint) => {
if (scrollType) {
this[_doMoveScroll](scrollType, p);
}
}, 16));
this.on(
'move',
throttle((p: TypePoint) => {
if (scrollType) {
this[_doMoveScroll](scrollType, p);
}
}, 16)
);
this.on('moveEnd', throttle((p: TypePoint) => {
if (scrollType) {
this[_doMoveScroll](scrollType, p);
}
scrollType = null;
}, 16));
this.on(
'moveEnd',
throttle((p: TypePoint) => {
if (scrollType) {
this[_doMoveScroll](scrollType, p);
}
scrollType = null;
}, 16)
);
// this.on('doubleClick', (p: TypePoint) => {})
}
@ -308,7 +384,13 @@ export class Board {
}
const { position } = this[_screen].calcScreen();
const { xSize } = this[_scroller].calc(position);
const moveX = this[_screen].calcScreenScroll(position.left, position.right, xSize, width, dx);
const moveX = this[_screen].calcScreenScroll(
position.left,
position.right,
xSize,
width,
dx
);
this.scrollX(scrollX + moveX);
this.draw();
}
@ -321,7 +403,13 @@ export class Board {
}
const { position } = this[_screen].calcScreen();
const { ySize } = this[_scroller].calc(position);
const moveY = this[_screen].calcScreenScroll(position.top, position.bottom, ySize, height, dy);
const moveY = this[_screen].calcScreenScroll(
position.top,
position.bottom,
ySize,
height,
dy
);
this.scrollY(scrollY + moveY);
this.draw();
}
@ -338,9 +426,4 @@ export class Board {
this[_doScrollY](point.y - ySize / 2, 0);
}
}
}

View file

@ -1,15 +1,15 @@
import { Core } from './../src/index';
import Core from './../src/index';
import { getData } from './data.js';
console.log('Core =', Core)
console.log('Core =', Core);
var opts = {
width: 300,
height: 200,
contextWidth: 300,
contextHeight: 200,
devicePixelRatio: 4,
}
devicePixelRatio: 4
};
// var config = {
// elementWrapper: {
// controllerSize: 4,
@ -22,12 +22,12 @@ const core = new Core(
mount,
Object.assign({}, opts, {
contextWidth: 500,
contextHeight: 400,
contextHeight: 400
}),
{
scrollWrapper: {
use: true,
},
use: true
}
}
);
core.setData(data);

View file

@ -2,18 +2,13 @@
"name": "@idraw/core",
"version": "0.3.0-alpha.6",
"description": "",
"main": "dist/index.cjs.js",
"module": "dist/index.esm.js",
"main": "dist/esm/index.js",
"module": "dist/esm/index.js",
"unpkg": "dist/index.global.js",
"types": "dist/index.d.ts",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"types": "dist/esm/index.d.ts",
"files": [
"dist/*.ts",
"dist/*.js",
"esm/*.ts",
"esm/*.js"
"dist/**/*.ts",
"dist/**/*.js"
],
"repository": {
"type": "git",

View file

@ -1,2 +0,0 @@
export * as default from './index';

View file

@ -1,3 +0,0 @@
export * from './index';
export * as default from './index';

View file

@ -1,31 +1,71 @@
import {
TypeData, TypePoint, TypeBoardSizeOptions,
TypeConfig, TypeConfigStrict, TypeElementBase,
TypeElement, TypeElemDesc, TypeContext, TypeCoreOptions, TypeScreenContext, TypeScreenData,
} from '@idraw/types';
import { Board } from '@idraw/board';
TypeData,
TypePoint,
TypeBoardSizeOptions,
TypeConfig,
TypeConfigStrict,
TypeElementBase,
TypeElement,
TypeElemDesc,
TypeContext,
TypeCoreOptions,
TypeScreenContext,
TypeScreenData
} from '@idraw/types';
import Board from '@idraw/board';
import { deepClone } from '@idraw/util';
import { Renderer } from '@idraw/renderer';
import Renderer from '@idraw/renderer';
import is, { TypeIs } from './lib/is';
import check, { TypeCheck } from './lib/check';
import {
Element, mergeConfig, CoreEvent,
TypeCoreEventArgMap, parseData, TempData, diffElementResourceChangeList,
Element,
mergeConfig,
CoreEvent,
TypeCoreEventArgMap,
parseData,
TempData,
diffElementResourceChangeList
} from './lib';
import {
_board, _data, _opts, _config, _renderer, _element, _tempData, _draw, _coreEvent,
_mapper, _emitChangeScreen, _emitChangeData, _engine,
_board,
_data,
_opts,
_config,
_renderer,
_element,
_tempData,
_draw,
_coreEvent,
_mapper,
_emitChangeScreen,
_emitChangeData,
_engine
} from './names';
import { getSelectedElements, updateElement, selectElementByIndex, getElement, getElementByIndex,
selectElement, moveUpElement, moveDownElement, addElement, deleteElement,
insertElementBefore, insertElementBeforeIndex, insertElementAfter, insertElementAfterIndex,
import {
getSelectedElements,
updateElement,
selectElementByIndex,
getElement,
getElementByIndex,
selectElement,
moveUpElement,
moveDownElement,
addElement,
deleteElement,
insertElementBefore,
insertElementBeforeIndex,
insertElementAfter,
insertElementAfterIndex
} from './mixins/element';
// import { initEvent } from './mixins/event';
import { Engine } from './lib/engine';
import { drawElementWrapper, drawAreaWrapper, drawElementListWrappers } from './lib/draw/wrapper'
export class Core {
import {
drawElementWrapper,
drawAreaWrapper,
drawElementListWrappers
} from './lib/draw/wrapper';
export default class Core {
private [_board]: Board;
private [_data]: TypeData;
private [_opts]: TypeCoreOptions;
@ -39,7 +79,11 @@ export class Core {
static is: TypeIs = is;
static check: TypeCheck = check;
constructor(mount: HTMLDivElement, opts: TypeCoreOptions, config?: TypeConfig) {
constructor(
mount: HTMLDivElement,
opts: TypeCoreOptions,
config?: TypeConfig
) {
this[_data] = { elements: [] };
this[_opts] = opts;
this[_config] = mergeConfig(config || {});
@ -48,27 +92,32 @@ export class Core {
canScroll: config?.scrollWrapper?.use,
scrollConfig: {
color: config?.scrollWrapper?.color || '#a0a0a0',
lineWidth: config?.scrollWrapper?.lineWidth || 12,
lineWidth: config?.scrollWrapper?.lineWidth || 12
}
});
this[_renderer] = new Renderer();
this[_renderer] = new Renderer();
const drawFrame = () => {
const helperCtx = this[_board].getHelperContext();
const helperConfig = this[_engine].getHelperConfig();
this[_board].clear();
const { contextWidth, contextHeight, devicePixelRatio } = this[_opts];
helperCtx.clearRect(0, 0, contextWidth * devicePixelRatio, contextHeight * devicePixelRatio)
helperCtx.clearRect(
0,
0,
contextWidth * devicePixelRatio,
contextHeight * devicePixelRatio
);
drawElementWrapper(helperCtx, helperConfig);
drawAreaWrapper(helperCtx, helperConfig);
drawElementListWrappers(helperCtx, helperConfig);
this[_board].draw();
}
};
this[_renderer].on('drawFrame', (e) => {
drawFrame();
})
});
this[_renderer].on('drawFrameComplete', (e) => {
drawFrame();
})
});
this[_element] = new Element(this[_board].getContext());
this[_engine] = new Engine({
coreEvent: this[_coreEvent],
@ -79,7 +128,7 @@ export class Core {
getDataFeekback: () => this[_data],
selectElementByIndex: this.selectElementByIndex.bind(this),
emitChangeScreen: this[_emitChangeScreen].bind(this),
emitChangeData: this[_emitChangeData].bind(this),
emitChangeData: this[_emitChangeData].bind(this)
});
this[_engine].init();
@ -88,20 +137,16 @@ export class Core {
});
this[_renderer].on('drawFrameComplete', () => {
this[_coreEvent].trigger('drawFrameComplete', undefined);
})
});
this[_tempData].set('hasInited', true);
}
[_draw](
opts?: {
resourceChangeUUIDs?: string[],
}
): void {
[_draw](opts?: { resourceChangeUUIDs?: string[] }): void {
this[_engine].updateHelperConfig({
width: this[_opts].width,
height: this[_opts].height,
devicePixelRatio: this[_opts].devicePixelRatio,
devicePixelRatio: this[_opts].devicePixelRatio
});
this[_renderer].thaw();
@ -119,7 +164,7 @@ export class Core {
}
selectElementByIndex(index: number, opts?: { useMode?: boolean }): void {
return selectElementByIndex(this, index, opts)
return selectElementByIndex(this, index, opts);
}
selectElement(uuid: string, opts?: { useMode?: boolean }): void {
@ -146,24 +191,36 @@ export class Core {
return deleteElement(this, uuid);
}
insertElementBefore(elem: TypeElementBase<keyof TypeElemDesc>, beforeUUID: string) {
insertElementBefore(
elem: TypeElementBase<keyof TypeElemDesc>,
beforeUUID: string
) {
return insertElementBefore(this, elem, beforeUUID);
}
insertElementBeforeIndex(elem: TypeElementBase<keyof TypeElemDesc>, index: number) {
return insertElementBeforeIndex(this, elem, index)
insertElementBeforeIndex(
elem: TypeElementBase<keyof TypeElemDesc>,
index: number
) {
return insertElementBeforeIndex(this, elem, index);
}
getSelectedElements() {
return getSelectedElements(this);
}
insertElementAfter(elem: TypeElementBase<keyof TypeElemDesc>, beforeUUID: string) {
insertElementAfter(
elem: TypeElementBase<keyof TypeElemDesc>,
beforeUUID: string
) {
return insertElementAfter(this, elem, beforeUUID);
}
insertElementAfterIndex(elem: TypeElementBase<keyof TypeElemDesc>, index: number) {
return insertElementAfterIndex(this, elem, index)
insertElementAfterIndex(
elem: TypeElementBase<keyof TypeElemDesc>,
index: number
) {
return insertElementAfterIndex(this, elem, index);
}
resetSize(opts: TypeBoardSizeOptions) {
@ -198,8 +255,8 @@ export class Core {
return {
scale: transform.scale,
scrollTop: Math.max(0, 0 - transform.scrollY),
scrollLeft: Math.max(0, 0 - transform.scrollX),
}
scrollLeft: Math.max(0, 0 - transform.scrollX)
};
}
getData(): TypeData {
@ -207,7 +264,10 @@ export class Core {
}
setData(data: any | TypeData, opts?: { triggerChangeEvent: boolean }): void {
const resourceChangeUUIDs = diffElementResourceChangeList(this[_data], data);
const resourceChangeUUIDs = diffElementResourceChangeList(
this[_data],
data
);
this[_data] = this[_element].initData(deepClone(parseData(data)));
if (opts && opts.triggerChangeEvent === true) {
this[_emitChangeData]();
@ -220,11 +280,17 @@ export class Core {
this[_draw]();
}
on<T extends keyof TypeCoreEventArgMap >(key: T, callback: (p: TypeCoreEventArgMap[T]) => void) {
on<T extends keyof TypeCoreEventArgMap>(
key: T,
callback: (p: TypeCoreEventArgMap[T]) => void
) {
this[_coreEvent].on(key, callback);
}
off<T extends keyof TypeCoreEventArgMap >(key: T, callback: (p: TypeCoreEventArgMap[T]) => void) {
off<T extends keyof TypeCoreEventArgMap>(
key: T,
callback: (p: TypeCoreEventArgMap[T]) => void
) {
this[_coreEvent].off(key, callback);
}
@ -248,11 +314,10 @@ export class Core {
return this[_board].getOriginContext2D();
}
private [_emitChangeScreen]() {
if (this[_coreEvent].has('changeScreen')) {
this[_coreEvent].trigger('changeScreen', {
...this.getScreenTransform(),
...this.getScreenTransform()
});
}
}

View file

@ -2,18 +2,13 @@
"name": "idraw",
"version": "0.3.0-alpha.6",
"description": "",
"main": "dist/index.cjs.js",
"module": "dist/index.esm.js",
"main": "dist/esm/index.js",
"module": "dist/esm/index.js",
"unpkg": "dist/index.global.js",
"types": "dist/index.d.ts",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"types": "dist/esm/index.d.ts",
"files": [
"dist/*.ts",
"dist/*.js",
"esm/*.ts",
"esm/*.js"
"dist/**/*.ts",
"dist/**/*.js"
],
"repository": {
"type": "git",

View file

@ -1,3 +0,0 @@
import iDraw from './index';
export default iDraw;

View file

@ -1,3 +0,0 @@
import iDraw from './index';
export default iDraw;

View file

@ -1,47 +1,64 @@
import { Core } from '@idraw/core';
import { TypeData, TypeConfig, } from '@idraw/types';
import Core from '@idraw/core';
import { TypeData, TypeConfig } from '@idraw/types';
import { Options, PrivateOptions } from './types';
import { defaultOptions } from './config';
import { TempData } from './lib/temp';
import { KeyboardWatcher } from './lib/keyboard-watcher';
import {
_opts, _hasInited, _initEvent, _tempData,
_createOpts, _pushRecord, _keyboardWatcher,
_opts,
_hasInited,
_initEvent,
_tempData,
_createOpts,
_pushRecord,
_keyboardWatcher
} from './names';
import { redo, undo } from './mixins/record';
import { exportDataURL, toDataURL } from './mixins/file';
import { copyElements, pasteElements, cutElements, deleteElements,
keyArrowUp, keyArrowDown, keyArrowLeft, keyArrowRight, keyUndo,
import {
copyElements,
pasteElements,
cutElements,
deleteElements,
keyArrowUp,
keyArrowDown,
keyArrowLeft,
keyArrowRight,
keyUndo
} from './mixins/keyboard';
// import { version } from './../package.json';
export default class iDraw extends Core {
private [_opts]: PrivateOptions;
private [_hasInited] = false;
private [_hasInited] = false;
private [_tempData] = new TempData();
private [_keyboardWatcher] = new KeyboardWatcher();
// static version = version;
constructor(mount: HTMLDivElement, opts: Options, config?: TypeConfig) {
super(mount, {
width: opts.width || defaultOptions.width,
height: opts.height || defaultOptions.height,
contextWidth: opts.contextWidth || defaultOptions.contextWidth,
contextHeight: opts.contextHeight || defaultOptions.contextHeight,
devicePixelRatio: opts.devicePixelRatio || defaultOptions.devicePixelRatio,
onlyRender: opts.onlyRender || defaultOptions.onlyRender,
}, config || {});
super(
mount,
{
width: opts.width || defaultOptions.width,
height: opts.height || defaultOptions.height,
contextWidth: opts.contextWidth || defaultOptions.contextWidth,
contextHeight: opts.contextHeight || defaultOptions.contextHeight,
devicePixelRatio:
opts.devicePixelRatio || defaultOptions.devicePixelRatio,
onlyRender: opts.onlyRender || defaultOptions.onlyRender
},
config || {}
);
this[_opts] = this[_createOpts](opts);
this[_initEvent]();
}
undo(): { doRecordCount: number, data: TypeData | null, } {
undo(): { doRecordCount: number; data: TypeData | null } {
return undo(this);
}
redo(): { undoRecordCount: number, data: TypeData | null, } {
redo(): { undoRecordCount: number; data: TypeData | null } {
return redo(this);
}
@ -49,7 +66,10 @@ export default class iDraw extends Core {
return toDataURL(this, type, quality);
}
async exportDataURL(type: 'image/png' | 'image/jpeg', quality?: number ): Promise<string> {
async exportDataURL(
type: 'image/png' | 'image/jpeg',
quality?: number
): Promise<string> {
return exportDataURL(this, type, quality);
}
@ -94,5 +114,4 @@ export default class iDraw extends Core {
private [_createOpts](opts: Options): PrivateOptions {
return { ...{}, ...defaultOptions, ...opts };
}
}
}

View file

@ -2,18 +2,13 @@
"name": "@idraw/renderer",
"version": "0.3.0-alpha.6",
"description": "",
"main": "dist/index.cjs.js",
"module": "dist/index.esm.js",
"main": "dist/esm/index.js",
"module": "dist/esm/index.js",
"unpkg": "dist/index.global.js",
"types": "dist/index.d.ts",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"types": "dist/esm/index.d.ts",
"files": [
"dist/*.ts",
"dist/*.js",
"esm/*.ts",
"esm/*.js"
"dist/**/*.ts",
"dist/**/*.js"
],
"repository": {
"type": "git",

View file

@ -1 +0,0 @@
export * as default from './index';

View file

@ -1,3 +0,0 @@
export * from './index';
export * as default from './index';

View file

@ -5,8 +5,14 @@ import { TypeLoadDataItem } from './lib/loader-event';
import Loader from './lib/loader';
import { RendererEvent } from './lib/renderer-event';
import {
_queue, _ctx, _status, _loader, _opts, _freeze,
_drawFrame, _retainQueueOneItem
_queue,
_ctx,
_status,
_loader,
_opts,
_freeze,
_drawFrame,
_retainQueueOneItem
} from './names';
const { requestAnimationFrame } = window;
@ -16,23 +22,22 @@ enum DrawStatus {
NULL = 'null',
FREE = 'free',
DRAWING = 'drawing',
FREEZE = 'freeze',
FREEZE = 'freeze'
// STOP = 'stop',
}
type Options = {
width: number,
height: number,
width: number;
height: number;
contextWidth?: number;
contextHeight?: number;
devicePixelRatio: number,
}
export class Renderer extends RendererEvent {
devicePixelRatio: number;
};
export default class Renderer extends RendererEvent {
private [_queue]: QueueItem[] = [];
private [_ctx]: TypeContext | null = null;
private [_status]: DrawStatus = DrawStatus.NULL;
private [_status]: DrawStatus = DrawStatus.NULL;
private [_loader]: Loader;
private [_opts]?: Options;
@ -50,20 +55,24 @@ export class Renderer extends RendererEvent {
this.trigger('error', { element: res.element, error: res.error });
});
this[_loader].on('complete', () => {
this.trigger('loadComplete', { t: Date.now() })
this.trigger('loadComplete', { t: Date.now() });
});
}
render(target: HTMLCanvasElement | TypeContext, originData: TypeData, opts?: {
// forceUpdate?: boolean,
changeResourceUUIDs?: string[]
}): void {
render(
target: HTMLCanvasElement | TypeContext,
originData: TypeData,
opts?: {
// forceUpdate?: boolean,
changeResourceUUIDs?: string[];
}
): void {
// if ([DrawStatus.STOP, DrawStatus.FREEZE].includes(this[_status])) {
// return;
// }
// this[_status] = DrawStatus.FREE;
const { changeResourceUUIDs = []} = opts || {};
const { changeResourceUUIDs = [] } = opts || {};
this[_status] = DrawStatus.FREE;
const data = deepClone(originData);
@ -77,8 +86,12 @@ export class Renderer extends RendererEvent {
if (!this[_ctx]) {
// TODO
if (this[_opts] && Object.prototype.toString.call(target) === '[object HTMLCanvasElement]') {
const { width, height, contextWidth, contextHeight, devicePixelRatio } = this[_opts] as Options;
if (
this[_opts] &&
Object.prototype.toString.call(target) === '[object HTMLCanvasElement]'
) {
const { width, height, contextWidth, contextHeight, devicePixelRatio } =
this[_opts] as Options;
const canvas = target as HTMLCanvasElement;
canvas.width = width * devicePixelRatio;
canvas.height = height * devicePixelRatio;
@ -89,17 +102,17 @@ export class Renderer extends RendererEvent {
contextWidth: contextWidth || width,
contextHeight: contextHeight || height,
devicePixelRatio
})
});
} else if (target) {
// TODO
this[_ctx] = target as TypeContext;
}
}
if ([DrawStatus.FREEZE].includes(this[_status])) {
return;
}
const _data: QueueItem = deepClone({ data, }) as QueueItem;
const _data: QueueItem = deepClone({ data }) as QueueItem;
this[_queue].push(_data);
// if (this[_status] !== DrawStatus.DRAWING) {
// this[_status] = DrawStatus.DRAWING;
@ -110,7 +123,7 @@ export class Renderer extends RendererEvent {
}
getContext(): TypeContext | null {
return this[_ctx]
return this[_ctx];
}
thaw() {
@ -130,7 +143,7 @@ export class Renderer extends RendererEvent {
return;
}
const ctx = this[_ctx];
let item: QueueItem | undefined = this[_queue][0];
let isLastFrame = false;
if (this[_queue].length > 1) {
@ -158,9 +171,13 @@ export class Renderer extends RendererEvent {
} else {
this[_status] = DrawStatus.FREE;
}
this.trigger('drawFrame', { t: Date.now() })
this.trigger('drawFrame', { t: Date.now() });
if (this[_loader].isComplete() === true && this[_queue].length === 1 && this[_status] === DrawStatus.FREE) {
if (
this[_loader].isComplete() === true &&
this[_queue].length === 1 &&
this[_status] === DrawStatus.FREE
) {
if (ctx && this[_queue][0] && this[_queue][0].data) {
drawContext(ctx, this[_queue][0].data, this[_loader]);
}
@ -177,7 +194,4 @@ export class Renderer extends RendererEvent {
const lastOne = deepClone(this[_queue][this[_queue].length - 1]);
this[_queue] = [lastOne];
}
}

View file

@ -2,18 +2,13 @@
"name": "@idraw/util",
"version": "0.3.0-alpha.6",
"description": "",
"main": "dist/index.cjs.js",
"module": "dist/index.esm.js",
"main": "dist/esm/index.js",
"module": "dist/esm/index.js",
"unpkg": "dist/index.global.js",
"types": "dist/index.d.ts",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"types": "dist/esm/index.d.ts",
"files": [
"dist/*.ts",
"dist/*.js",
"esm/*.js",
"esm/*.ts"
"dist/**/*.ts",
"dist/**/*.js"
],
"repository": {
"type": "git",

View file

@ -1 +0,0 @@
export * as default from './index';

View file

@ -1,3 +0,0 @@
export * from './index';
export * as default from './index';

View file

@ -7,8 +7,7 @@ import istype from './lib/istype';
import { loadImage, loadSVG, loadHTML } from './lib/loader';
import Context from './lib/context';
import is from './lib/is';
import check from './lib/check';
import check from './lib/check';
export {
is,
@ -26,5 +25,24 @@ export {
createUUID,
istype,
deepClone,
Context,
}
Context
};
export default {
is,
check,
delay,
compose,
throttle,
loadImage,
loadSVG,
loadHTML,
downloadImageFromCanvas,
toColorHexStr,
toColorHexNum,
isColorStr,
createUUID,
istype,
deepClone,
Context
};

File diff suppressed because it is too large Load diff

View file

@ -1,41 +1,39 @@
function click(opts){
const { x,y } = opts;
function click(opts) {
const { x, y } = opts;
const event = new MouseEvent('click', {
screenX: x,
screenY: y,
clientX: x,
clientY: y,
clientY: y
});
const elem = document.elementFromPoint(x,y);
const elem = document.elementFromPoint(x, y);
elem.dispatchEvent(event);
}
function mouseDown(opts){
const { x,y } = opts;
function mouseDown(opts) {
const { x, y } = opts;
const event = new MouseEvent('mousedown', {
screenX: x,
screenY: y,
clientX: x,
clientY: y,
clientY: y
});
const elem = document.elementFromPoint(x,y);
const elem = document.elementFromPoint(x, y);
elem.dispatchEvent(event);
}
function mouseMove(opts){
const { x,y } = opts;
function mouseMove(opts) {
const { x, y } = opts;
const event = new MouseEvent('mousemove', {
screenX: x,
screenY: y,
clientX: x,
clientY: y,
clientY: y
});
const elem = document.elementFromPoint(x,y);
const elem = document.elementFromPoint(x, y);
elem.dispatchEvent(event);
}
// function mouseOver(opts){
// const { x,y } = opts;
// const event = new MouseEvent('mouseover', {
@ -48,21 +46,19 @@ function mouseMove(opts){
// elem.dispatchEvent(event);
// }
function mouseUp(opts){
const { x,y } = opts;
function mouseUp(opts) {
const { x, y } = opts;
const event = new MouseEvent('mouseup', {
screenX: x,
screenY: y,
clientX: x,
clientY: y,
clientY: y
});
const elem = document.elementFromPoint(x,y);
const elem = document.elementFromPoint(x, y);
elem.dispatchEvent(event);
}
function wheelX(x, opts = { clientX: 0, clientY: 0 }){
function wheelX(x, opts = { clientX: 0, clientY: 0 }) {
const event = new WheelEvent('wheel', {
deltaX: x,
deltaY: 0,
@ -73,7 +69,7 @@ function wheelX(x, opts = { clientX: 0, clientY: 0 }){
elem.dispatchEvent(event);
}
function wheelY(y, opts = { clientX: 0, clientY: 0 }){
function wheelY(y, opts = { clientX: 0, clientY: 0 }) {
const event = new WheelEvent('wheel', {
deltaX: 0,
deltaY: y,
@ -84,7 +80,6 @@ function wheelY(y, opts = { clientX: 0, clientY: 0 }){
elem.dispatchEvent(event);
}
export default {
click,
mouseDown,
@ -92,5 +87,5 @@ export default {
mouseMove,
// mouseOver,
wheelX,
wheelY,
}
wheelY
};

View file

@ -1,32 +0,0 @@
const path = require('path');
const fs = require('fs-extra');
const execa = require('execa');
const chalk = require('chalk');
// const { Extractor, ExtractorConfig } = require('@microsoft/api-extractor');
const { packages } = require('./config');
const pkgNames = packages.map((pkg) => {
return pkg.dirName
})
async function main() {
if (process.env.BUILD_MODE === 'reset' && !process.argv[2]) {
pkgNames.forEach(async (name) => {
const target = name;
const pkgDir = path.resolve(`packages/${target}`);
// const pkg = require(`${pkgDir}/package.json`)
await fs.remove(`${pkgDir}/dist`);
});
}
await
execa(
'rollup',
[
'-c',
'./scripts/rollup.config.js',
], { stdio: 'inherit' });
}
main();

38
scripts/build-bundle.ts Normal file
View file

@ -0,0 +1,38 @@
import { build } from 'vite';
import type { InlineConfig } from 'vite';
import { resolvePackagePath } from './util/project';
import { packages } from './config';
async function buildBundle(opts: { dirName: string; globalName: string }) {
const { dirName, globalName } = opts;
const filePath = resolvePackagePath(dirName, 'src', 'index.ts');
const distDir = resolvePackagePath(dirName, 'dist');
const config: InlineConfig = {
plugins: [],
build: {
minify: false,
emptyOutDir: false,
lib: {
name: globalName,
entry: filePath,
formats: ['iife'],
fileName: () => {
return 'index.global.js';
}
},
outDir: distDir
}
};
console.log(`Start build bundle [${dirName}] ...`);
await build(config);
console.log(`Build bundle [${dirName}] successfully!`);
}
async function run() {
for (let i = 0; i < packages.length; i++) {
const pkg = packages[i];
await buildBundle(pkg);
}
}
run();

View file

@ -1,42 +0,0 @@
const ts = require('typescript');
const path = require('path');
const fs = require('fs-extra');
// const babel = require('@babel/core');
const glob = require("glob");
const { packages } = require('./config');
const { resolvePackagePath, getTsConfig } = require('./util/project');
build();
async function build() {
packages.forEach(async (pkg) => {
const target = pkg.dirName;
const pkgDir = path.resolve(`packages/${target}`);
await fs.remove(`${pkgDir}/esm`);
buildPackage(pkg.dirName);
});
}
function buildPackage(dirName) {
const pattern = '**/*.ts';
const cwd = resolvePackagePath(dirName, 'src');
const files = glob.sync(pattern, { cwd, });
const targetFiles = files.map((file) => {
return resolvePackagePath(dirName, 'src', file);
});
// build ts -> esm
{
const tsConfig = getTsConfig();
const compilerOptions = tsConfig.compilerOptions;
compilerOptions.target = ts.ScriptTarget.ES2015;
compilerOptions.moduleResolution = ts.ModuleResolutionKind.NodeJs;
compilerOptions.declaration = true;
compilerOptions.outDir = resolvePackagePath(dirName, 'esm');
compilerOptions.rootDir = resolvePackagePath(dirName, 'src');
const program = ts.createProgram(targetFiles, compilerOptions);
program.emit();
}
}

44
scripts/build-module.ts Normal file
View file

@ -0,0 +1,44 @@
import ts from 'typescript';
import path from 'path';
import fs from 'fs-extra';
import glob from 'glob';
import { packages } from './config';
import { resolvePackagePath, getTsConfig } from './util/project';
build();
async function build() {
for (let i = 0; i < packages.length; i++) {
const pkg = packages[i];
const { dirName } = pkg;
const pkgDir = path.resolve(`packages/${dirName}`);
console.log(`Start to build ESM for ${dirName}`);
console.log(`Remove packages/${dirName}/dist/`);
await fs.remove(`${pkgDir}/dist`);
buildPackage(dirName);
console.log(`Build ESM of ${dirName} successfully!`);
}
}
function buildPackage(dirName) {
const pattern = '**/*.ts';
const cwd = resolvePackagePath(dirName, 'src');
const files = glob.sync(pattern, { cwd });
const targetFiles = files.map((file) => {
return resolvePackagePath(dirName, 'src', file);
});
// build ts -> esm
{
const tsConfig = getTsConfig();
const compilerOptions = tsConfig.compilerOptions;
compilerOptions.target = ts.ScriptTarget.ES2015;
compilerOptions.moduleResolution = ts.ModuleResolutionKind.NodeJs;
compilerOptions.declaration = true;
compilerOptions.outDir = resolvePackagePath(dirName, 'dist', 'esm');
compilerOptions.rootDir = resolvePackagePath(dirName, 'src');
const program = ts.createProgram(targetFiles, compilerOptions);
program.emit();
}
}

View file

@ -1,15 +1,17 @@
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-nocheck
const packages = [
{
dirName: 'util',
globalName: 'iDrawUtil',
globalName: 'iDrawUtil'
},
{
dirName: 'board',
globalName: 'iDrawBoard',
globalName: 'iDrawBoard'
},
{
dirName: 'renderer',
globalName: 'iDrawRenderer',
globalName: 'iDrawRenderer'
},
// {
// dirName: 'kernal',
@ -17,22 +19,22 @@ const packages = [
// },
{
dirName: 'core',
globalName: 'iDrawCore',
globalName: 'iDrawCore'
},
{
dirName: 'idraw',
globalName: 'iDraw',
},
globalName: 'iDraw'
}
];
function getTargetPackage(cmdTarget = '') {
let target = '';
if (typeof cmdTarget === 'string') {
target = cmdTarget.replace(/^--target-pkg\=/ig, '');
target = cmdTarget.replace(/^--target-pkg\=/gi, '');
}
let pkgs = [];
let targetIndex = -1;
for (let i = 0; i < packages.length; i ++) {
for (let i = 0; i < packages.length; i++) {
if (packages[i] && packages[i].dirName === target) {
targetIndex = i;
break;
@ -43,10 +45,7 @@ function getTargetPackage(cmdTarget = '') {
} else {
pkgs = packages;
}
return pkgs
return pkgs;
}
module.exports = {
packages,
getTargetPackage,
}
export { packages, getTargetPackage };

View file

@ -1,16 +0,0 @@
const execa = require('execa');
const process = require('process');
async function main() {
await execa('rollup',
[
'-w',
'-c',
'./scripts/rollup.config.js',
], { stdio: 'inherit' }
)
}
main();

9
scripts/dev-rollup.ts Normal file
View file

@ -0,0 +1,9 @@
import { execa } from 'execa';
async function main() {
await execa('rollup', ['-w', '-c', './scripts/rollup.config.js'], {
stdio: 'inherit'
});
}
main();

View file

@ -1,60 +0,0 @@
const { AutoComplete } = require('enquirer');
const chalk = require('chalk');
const { createServer, defineConfig } = require('vite');
const { resolvePackagePath } = require('./util/project');
const { packages } = require('./config');
dev();
async function dev() {
const pkgName = await inputPackageName();
const viteConfig = getViteConfig(pkgName);
const server = await createServer(viteConfig)
await server.listen()
server.printUrls();
const { port, host = '127.0.0.1' } = server.config?.server || {}
console.log(
`Open: ` +
chalk.green(
`http://${host}:${port}/index.html`
)
);
}
function getViteConfig(pkgName) {
const viteConfig = defineConfig({
configFile: false,
root: resolvePackagePath(pkgName),
publicDir: resolvePackagePath(pkgName, 'dev'),
server: {
port: 8080,
host: '127.0.0.1',
},
plugins: [],
esbuild: {
include: [
/\.ts$/,
/\.js$/,
],
exclude: [
/\.html$/
]
},
});
return viteConfig;
}
async function inputPackageName() {
choices = packages.map((pkg) => {
return pkg.dirName;
})
const prompt = new AutoComplete({
name: 'Package Name',
message: 'Pick your dev package',
limit: choices.length,
initial: 0,
choices: choices
});
const pkgName = await prompt.run();
return pkgName;
}

56
scripts/dev.ts Normal file
View file

@ -0,0 +1,56 @@
/* eslint-disable @typescript-eslint/ban-ts-comment */
import AutoComplete from 'enquirer/lib/prompts/autocomplete';
import chalk from 'chalk';
import { createServer } from 'vite';
import type { UserConfig } from 'vite';
import { resolvePackagePath } from './util/project';
import { packages } from './config';
dev();
async function dev() {
const pkgName = await inputPackageName();
const viteConfig = getViteConfig(pkgName);
const server = await createServer({
configFile: false,
...viteConfig
});
await server.listen();
server.printUrls();
const { port, host = '127.0.0.1' } = server.config?.server || {};
console.log(`Open: ` + chalk.green(`http://${host}:${port}/dev/index.html`));
}
function getViteConfig(pkgName: string): UserConfig {
const viteConfig: UserConfig = {
root: resolvePackagePath(pkgName),
publicDir: resolvePackagePath(pkgName, 'demo', 'public'),
server: {
port: 8080,
host: '127.0.0.1'
},
plugins: [],
esbuild: {
include: [/\.ts$/, /\.js$/],
exclude: [/\.html$/]
},
optimizeDeps: {}
};
return viteConfig;
}
async function inputPackageName() {
const choices = packages.map((pkg) => {
return pkg.dirName;
});
const prompt = new AutoComplete({
name: 'Package Name',
message: 'Pick your dev package',
limit: choices.length,
initial: 0,
choices: choices
});
// @ts-ignore
const pkgName = await prompt.run();
return pkgName;
}

View file

@ -1,36 +0,0 @@
const path = require('path');
const fs = require('fs');
const compose = require('koa-compose')
const { minify } = require('terser');
const { packages } = require('./config');
async function main() {
const tasks = [];
packages.forEach((p) => {
tasks.push(async (ctx, next) => {
const baseFileName = 'index.global.js';
const targetFileName = 'index.global.min.js';
const moduleBasePath = path.join(__dirname, '..', 'packages', p.dirName, 'dist');
console.log(`minify file: ${path.join(p.dirName, baseFileName)} > ${path.join(p.dirName, targetFileName)}`)
const filePath = path.join(moduleBasePath, baseFileName);
const targetPath = path.join(moduleBasePath, targetFileName);
const code = fs.readFileSync(filePath, { encoding: 'utf8' });
const options = {
output: {
beautify: false,
comments: false,
indent_level: 2,
quote_style: 3,
},
};
const result = await minify(code, options);
fs.writeFileSync(targetPath, result.code);
await next();
})
});
await compose(tasks)();
}
main();

49
scripts/minify.ts Normal file
View file

@ -0,0 +1,49 @@
/* eslint-disable @typescript-eslint/ban-ts-comment */
import path from 'path';
import fs from 'fs';
import compose from 'koa-compose';
import { minify } from 'terser';
import { packages } from './config';
async function main() {
const tasks = [];
packages.forEach((p) => {
// @ts-ignore
tasks.push(async (_ctx: any, next: any) => {
const baseFileName = 'index.global.js';
const targetFileName = 'index.global.min.js';
const moduleBasePath = path.join(
__dirname,
'..',
'packages',
p.dirName,
'dist'
);
console.log(
`minify file: ${path.join(p.dirName, baseFileName)} > ${path.join(
p.dirName,
targetFileName
)}`
);
const filePath = path.join(moduleBasePath, baseFileName);
const targetPath = path.join(moduleBasePath, targetFileName);
const code = fs.readFileSync(filePath, { encoding: 'utf8' });
const options = {
output: {
beautify: false,
comments: false,
indent_level: 2,
quote_style: 3
}
};
const result = await minify(code, options);
fs.writeFileSync(targetPath, result.code as string);
await next();
});
});
await compose(tasks)();
}
main();

View file

@ -1,23 +1,24 @@
const process = require('process');
const path = require('path');
const typescript = require('rollup-plugin-typescript2');
const { terser } = require('rollup-plugin-terser');
const cleanup = require('rollup-plugin-cleanup');
const { nodeResolve } = require('@rollup/plugin-node-resolve');
const json = require('@rollup/plugin-json');
const { packages } = require('./config');
const dtsPlugin = require('./util/dts-plugin');
const stylePlugin = require('./util/style-plugin');
import process from 'process';
import path from 'path';
import * as rollup from 'rollup';
import typescript from 'rollup-plugin-typescript2';
import { terser } from 'rollup-plugin-terser';
import cleanup from 'rollup-plugin-cleanup';
import { nodeResolve } from '@rollup/plugin-node-resolve';
import json from '@rollup/plugin-json';
import { packages } from './config';
import dtsPlugin from './util/dts-plugin';
import stylePlugin from './util/style-plugin';
// const cleanPlugin = require('./util/clean-plugin');
const resolveFile = function(names = []) {
return path.join(__dirname, '..', 'packages', ...names)
}
const resolveFile = function (names = []) {
return path.join(__dirname, '..', 'packages', ...names);
};
const modules = [];
const external = [ '@idraw/types', '@idraw/util', '@idraw/board', '@idraw/core' ];
const external = ['@idraw/types', '@idraw/util', '@idraw/board', '@idraw/core'];
for(let i = 0; i < packages.length; i++) {
for (let i = 0; i < packages.length; i++) {
const pkg = packages[i];
if (process.env.BUILD_MODE === 'mini') {
// modules.push({
@ -50,7 +51,7 @@ for(let i = 0; i < packages.length; i++) {
exports: 'default',
// plugins: [dtsPlugin(pkg.dirName),],
plugins: [],
external,
external
});
modules.push({
input: resolveFile([pkg.dirName, 'src', 'esm.ts']),
@ -59,24 +60,41 @@ for(let i = 0; i < packages.length; i++) {
esModule: true,
format: 'es',
external,
plugins: [dtsPlugin(pkg.dirName),]
plugins: [dtsPlugin(pkg.dirName)]
});
}
}
function createConfigItem(params, opts = {}) {
const { input, output, name, format, plugins = [], esModule, exports} = params;
const {
input,
output,
name,
format,
plugins = [],
esModule,
exports
} = params;
const prodMiniConfig = [
terser({
output: {
beautify: false,
comments: false,
indent_level: 2,
quote_style: 3
}
})
];
return {
input: input,
output: {
file:output,
file: output,
format,
name: name,
esModule: esModule === true,
// sourcemap: true,
exports
},
},
plugins: [
...[
stylePlugin(),
@ -85,7 +103,7 @@ function createConfigItem(params, opts = {}) {
tsconfig: path.resolve(__dirname, '..', 'tsconfig.json'),
tsconfigOverride: {}
}),
json(),
json()
],
...plugins,
...[
@ -93,38 +111,37 @@ function createConfigItem(params, opts = {}) {
// sourcemap: process.env.NODE_ENV === 'development',
// }),
cleanup({
comments: 'none',
}),
],
...(opts.minify === true ? [
terser({
output: {
beautify: false,
comments: false,
indent_level: 2,
quote_style: 3,
}
comments: 'none'
})
] : [])
],
],
...(opts.minify === true ? prodMiniConfig : [])
]
};
}
function createDevConfig(mods) {
const configs = mods.map((mod) => {
const cfg = createConfigItem(mod, {
minify: mod.output.endsWith('.min.js'),
minify: mod.output.endsWith('.min.js')
});
return cfg;
});
return configs;
}
module.exports = createDevConfig(modules);
export async function buildByRollup() {
const configs = createDevConfig(modules);
for (let i = 0; i < configs.length; i++) {
const config = configs[i];
const inputOptions = config;
const outputOptions = config.output;
// create a bundle
const bundle = await rollup.rollup(inputOptions);
console.log(`Start compile ${path.basename(inputOptions.input)}`);
await bundle.generate(outputOptions);
// or write the bundle to disk
await bundle.write(outputOptions);
console.log(`End compile ${path.basename(outputOptions.file)}`);
}
}

View file

@ -1,4 +1,4 @@
const pageList = [
export const pageList = [
{ path: 'board/test/main.html', w: 620, h: 270, delay: 500 },
{ path: 'board/test/scale.html', w: 930, h: 540, delay: 500 },
{ path: 'board/test/scroll.html', w: 620, h: 270, delay: 500 },
@ -7,8 +7,6 @@ const pageList = [
{ path: 'core/test/api.html', w: 930, h: 1570, delay: 800 },
{ path: 'core/test/resource.html', w: 930, h: 540, delay: 800 },
{ path: 'idraw/test/api.html', w: 930, h: 540, delay: 800 },
]
];
module.exports = {
pageList,
}

View file

@ -1,9 +1,9 @@
const jimp = require('jimp');
const path = require('path');
const { delay } = require('./util/time');
const { createScreenshot } = require('./util/screen');
const { removeFullDir } = require('./util/file');
const { pageList } = require('./screen.config');
import jimp from 'jimp';
import path from 'path';
import { delay } from './util/time';
import { createScreenshot } from './util/screen';
import { removeFullDir } from './util/file';
import { pageList } from './screen.config';
const snapshotDir = path.join(__dirname, '..', '__tests__', 'snapshot');
@ -15,13 +15,13 @@ async function main() {
pageList.forEach((p, i) => {
middlewares.push(async (ctx = {}, next) => {
const { page, port } = ctx;
console.log(`[${i+1}/${pageList.length}] Screen: ${p.path}`)
console.log(`[${i+1}/${pageList.length}] Screen: ${p.path}`);
await page.setViewport( { width: p.w, height: p.h } );
const pageUrl = `http://127.0.0.1:${port}/examples/${p.path || ''}`;
const result = await page.goto(pageUrl);
if (result.status() === 404) {
console.error(`404 Not Found: ${pageUrl}`)
throw Error('404 status code found in result')
console.error(`404 Not Found: ${pageUrl}`);
throw Error('404 status code found in result');
}
await delay(p.delay || 100);
const buf = await page.screenshot();

View file

@ -1,39 +0,0 @@
const extname = require("path").extname;
const { createFilter } = require('@rollup/pluginutils');
const MagicString = require('magic-string');
module.exports = function cleanPlugin(options = {}) {
const filter = createFilter(options.include, options.exclude);
const sourcemap = options.sourcemap === true;
return {
name: 'clean-plugin',
transform (code, id) {
if (!filter(id) || !(['.js', '.ts'].indexOf(extname(id)) >= 0)) return;
let codeStr = `${code}`;
const magic = new MagicString(codeStr);
if (sourcemap === true) {
codeStr = codeStr.replace(/\/\*\!([^\\]+)\*\//gi, function(match, offset) {
const start = offset;
const end = offset + match.length;
magic.overwrite(start, end, '');
return '';
});
}
const resultCode = magic.toString();
let resultMap = false;
if (sourcemap === true) {
resultMap = magic.generateMap({
hires: true,
});
}
return {
code: resultCode,
map: resultMap,
};
}
};
}

View file

@ -0,0 +1,47 @@
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-nocheck
import path from 'path';
import { createFilter } from '@rollup/pluginutils';
import MagicString from 'magic-string';
const { extname } = path;
function cleanPlugin(options = {}) {
const filter = createFilter(options.include, options.exclude);
const sourcemap = options.sourcemap === true;
return {
name: 'clean-plugin',
transform(code, id) {
if (!filter(id) || !(['.js', '.ts'].indexOf(extname(id)) >= 0)) return;
let codeStr = `${code}`;
const magic = new MagicString(codeStr);
if (sourcemap === true) {
codeStr = codeStr.replace(
/\/\*\!([^\\]+)\*\//gi,
function (match, offset) {
const start = offset;
const end = offset + match.length;
magic.overwrite(start, end, '');
return '';
}
);
}
const resultCode = magic.toString();
let resultMap = false;
if (sourcemap === true) {
resultMap = magic.generateMap({
hires: true
});
}
return {
code: resultCode,
map: resultMap
};
}
};
}
export default cleanPlugin;

View file

@ -1,55 +1,53 @@
const path = require('path');
const fs = require('fs-extra');
const execa = require('execa');
const chalk = require('chalk');
const { Extractor, ExtractorConfig } = require('@microsoft/api-extractor');
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-nocheck
import path from 'path';
import fs from 'fs-extra';
import chalk from 'chalk';
import { Extractor, ExtractorConfig } from '@microsoft/api-extractor';
module.exports = function myPlugin(pkgName) {
return {
name: 'dts-plugin', // this name will show up in warnings and errors
async closeBundle() {
// build types
const target = pkgName;
const pkgDir = path.join(__dirname, '..', '..', 'packages', `${target}`);
// eslint-disable-next-line @typescript-eslint/no-var-requires
const pkg = require(`${pkgDir}/package.json`);
const extractorConfigPath = path.resolve(pkgDir, `api-extractor.json`)
const extractorConfig = ExtractorConfig.loadFileAndPrepare(
extractorConfigPath
);
const extractorConfigPath = path.resolve(pkgDir, `api-extractor.json`);
const extractorConfig =
ExtractorConfig.loadFileAndPrepare(extractorConfigPath);
const extractorResult = Extractor.invoke(extractorConfig, {
localBuild: true,
showVerboseMessages: true
});
if (extractorResult.succeeded) {
// concat additional d.ts to rolled-up dts
const typesDir = path.resolve(pkgDir, 'types')
const typesDir = path.resolve(pkgDir, 'types');
if (fs.existsSync(typesDir)) {
const dtsPath = path.resolve(pkgDir, pkg.types)
const existing = await fs.readFile(dtsPath, 'utf-8')
const typeFiles = await fs.readdir(typesDir)
const dtsPath = path.resolve(pkgDir, pkg.types);
const existing = await fs.readFile(dtsPath, 'utf-8');
const typeFiles = await fs.readdir(typesDir);
const toAdd = await Promise.all(
typeFiles.map(file => {
return fs.readFile(path.resolve(typesDir, file), 'utf-8')
typeFiles.map((file) => {
return fs.readFile(path.resolve(typesDir, file), 'utf-8');
})
)
await fs.writeFile(dtsPath, existing + '\n' + toAdd.join('\n'))
);
await fs.writeFile(dtsPath, existing + '\n' + toAdd.join('\n'));
}
console.log(
chalk.bold(chalk.green(`API Extractor completed successfully.`))
)
);
} else {
console.error(
`API Extractor completed with ${extractorResult.errorCount} errors` +
` and ${extractorResult.warningCount} warnings`
)
process.exitCode = 1
);
process.exitCode = 1;
}
await fs.remove(`${pkgDir}/dist/packages`)
await fs.remove(`${pkgDir}/dist/packages`);
}
};
}
};

View file

@ -1,14 +1,14 @@
const fs = require('fs');
const path = require('path');
import fs from 'fs';
import path from 'path';
function removeFullDir(dirPath) {
let files = [];
let files: string[] = [];
if (fs.existsSync(dirPath)) {
files = fs.readdirSync(dirPath);
files.forEach((filename) => {
let curPath = path.join(dirPath, filename);
const curPath: string = path.join(dirPath, filename);
const stat = fs.statSync(curPath);
if(stat.isDirectory()) {
if (stat.isDirectory()) {
removeFullDir(curPath);
} else if (stat.isFile()) {
// fs.unlinkSync(curPath);
@ -22,5 +22,5 @@ function removeFullDir(dirPath) {
}
module.exports = {
removeFullDir,
}
removeFullDir
};

View file

@ -1,28 +1,27 @@
const path = require('path');
const fs = require('fs');
import fs from 'fs';
import path from 'path';
function resolvePackagePath() {
const pathList = Array.from(arguments);
export function resolvePackagePath(...args: string[]) {
const pathList = Array.from(args);
const baseDir = path.join(resolveProjectPath(), 'packages');
return path.join(baseDir, ...pathList);
}
function resolveProjectPath() {
const pathList = Array.from(arguments);
export function resolveProjectPath(...args: string[]) {
const pathList = Array.from(args);
const baseDir = path.join(__dirname, '..', '..');
return path.join(baseDir, ...pathList);
}
function getTsConfig() {
const configPath = resolveProjectPath('tsconfig.json')
export function getTsConfig() {
const configPath = resolveProjectPath('tsconfig.json');
const configStr = fs.readFileSync(configPath, { encoding: 'utf8' });
const config = JSON.parse(configStr);
return config;
}
module.exports = {
resolveProjectPath,
resolvePackagePath,
getTsConfig,
}
getTsConfig
};

View file

@ -1,60 +0,0 @@
const path = require('path');
const http = require('http');
const fs = require('fs');
const puppeteer = require('puppeteer');
const serveHandler = require('serve-handler');
const compose = require('koa-compose');
const { delay } = require('./time');
const port = 3001;
const width = 600;
const height = 600;
module.exports = {
createScreenshotBuffer,
createScreenshot,
width,
height,
}
async function createScreenshotBuffer(pagePath) {
const middlewares = [];
let buf;
middlewares.push(async (ctx = {}, next) => {
const { page, port } = ctx;
await page.setViewport( { width: width, height: height } );
const pageUrl = `http://127.0.0.1:${port}/${pagePath || ''}`;
await page.goto(pageUrl);
await delay(1000 * 2);
buf = await page.screenshot();
});
await createScreenshot(middlewares, { baseDir: path.join(__dirname, '..', '..') });
return buf;
}
async function createScreenshot(middlewares, opts = {}) {
return new Promise((resolve, reject) => {
const server = http.createServer((req, res) => serveHandler(req, res, {
public: opts.baseDir,
}));
server.listen(port, async () => {
try {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await compose(middlewares)({ page, port })
await browser.close();
server.close();
resolve();
} catch (err) {
server.close();
console.error(err);
process.exit(-1);
}
});
server.on('SIGINT', () => process.exit(1) );
})
}

61
scripts/util/screen.ts Normal file
View file

@ -0,0 +1,61 @@
import http from 'http';
import path from 'path';
import puppeteer from 'puppeteer';
import serveHandler from 'serve-handler';
import compose from 'koa-compose';
import { delay } from './time';
const port = 3001;
const width = 600;
const height = 600;
module.exports = {
createScreenshotBuffer,
createScreenshot,
width,
height
};
async function createScreenshotBuffer(pagePath) {
const middlewares = [];
let buf;
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
middlewares.push(async (ctx: any) => {
const { page, port } = ctx as { page: any; port: number };
await page.setViewport({ width: width, height: height });
const pageUrl = `http://127.0.0.1:${port}/${pagePath || ''}`;
await page.goto(pageUrl);
await delay(1000 * 2);
buf = await page.screenshot();
});
await createScreenshot(middlewares, {
baseDir: path.join(__dirname, '..', '..')
});
return buf;
}
async function createScreenshot(middlewares, opts: any = {}): Promise<void> {
return new Promise((resolve) => {
const server = http.createServer((req, res) =>
serveHandler(req, res, {
public: opts.baseDir
})
);
server.listen(port, async () => {
try {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await compose(middlewares)({ page, port });
await browser.close();
server.close();
resolve();
} catch (err) {
server.close();
console.error(err);
process.exit(-1);
}
});
server.on('SIGINT', () => process.exit(1));
});
}

View file

@ -1,40 +0,0 @@
const postcss = require('rollup-plugin-postcss');
const less = require('less');
module.exports = function() {
return postcss({
extract: false,
minimize: true,
process: processLess,
})
}
const processLess = function(context, payload) {
return new Promise(( resolve, reject ) => {
less.render({
file: context
}, function(err, result) {
if( !err ) {
resolve(result);
} else {
reject(err);
}
});
less.render(context, {})
.then(function(output) {
// output.css = string of css
// output.map = string of sourcemap
// output.imports = array of string filenames of the imports referenced
if( output && output.css ) {
resolve(output.css);
} else {
reject({})
}
},
function(err) {
reject(err)
});
})
}

View file

@ -0,0 +1,45 @@
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-nocheck
import postcss from 'rollup-plugin-postcss';
import less from 'less';
const processLess = function (context) {
return new Promise((resolve, reject) => {
less.render(
{
file: context
},
function (err, result) {
if (!err) {
resolve(result);
} else {
reject(err);
}
}
);
less.render(context, {}).then(
function (output) {
// output.css = string of css
// output.map = string of sourcemap
// output.imports = array of string filenames of the imports referenced
if (output && output.css) {
resolve(output.css);
} else {
reject({});
}
},
function (err) {
reject(err);
}
);
});
};
export default function () {
return postcss({
extract: false,
minimize: true,
process: processLess
});
}

View file

@ -1,12 +1,7 @@
module.exports = {
delay,
}
function delay(time = 100) {
export function delay(time = 100): Promise<void> {
return new Promise((resolve) => {
setTimeout(() => {
resolve();
}, time);
})
}
});
}