ci: init travis config

This commit is contained in:
yuqi.pyq 2019-11-01 17:15:20 +08:00
parent a2a69fad2a
commit 2e37701e1d
21 changed files with 758 additions and 48 deletions

10
.travis.yml Normal file
View File

@ -0,0 +1,10 @@
sudo: false
language: node_js
node_js:
- '8'
branches:
only:
- next
script:
- yarn test
- yarn coveralls

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

View File

@ -0,0 +1,142 @@
# 自动化测试方案
如何测试一个 WebGL 应用渲染结果是否正确呢?常用的做法是进行像素比对,当然这也只能用于一些简单的判断例如渲染是否成功,整体的 Snapshot 比对开销很大。
但不管怎么说,这都意味着我们必须使用 WebGL API 进行真实的渲染。
以上过程在测试用例中描述如下:
```javascript
// 1. 绘制
// 2. 读取像素
const pixels = new Uint8Array(width * height * 4);
gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, pixels);
// 3. 判断某个像素点是否符合预期
```
在与测试框架结合时,常用的方案有:
* Electron 除了 WebGL APIDOM API 等其他浏览器实现对于 WebGL 测试都是多余的,在 CI 时需要安装的依赖过大,所需的启动时间也很长。
* [node-webgl](https://github.com/mikeseven/node-webgl) 不同于 WebGL可以直接调用 OpenGL 驱动,但同样包含了很多 WebGL 之外的特性。
这里我们选择 [headless-gl](https://github.com/stackgl/headless-gl),一个纯粹的 WebGL 1 规范的实现。并且能够很容易集成进现有的 [CI 流程](https://github.com/stackgl/headless-gl#how-can-i-use-headless-gl-with-a-continuous-integration-service)中,例如 [TravisCI](https://travis-ci.org/) 和 [AppVeyor](http://www.appveyor.com/)。
## 测试框架
在配置测试框架前,我们必须解决一个 WebGL 项目中常见的问题。
### 引入 GLSL 文件
如何在测试时正确引入 GLSL 文件是一个问题。目前各个 3D 引擎常用的做法有两种:
* 以字符串形式直接写在 `.js` 文件中。`luma.gl/deck.gl` 使用[这种方式](https://github.com/uber/deck.gl/blob/7.1-release/modules/layers/src/arc-layer/arc-layer-fragment.glsl.js)。
* 使用 `.glsl` 编写,测试前使用构建脚本自动生成对应的 `.js` 文件。`Three.js`、`clay.gl` 使用[这种方式](https://github.com/pissang/claygl/blob/master/build/glsl2js.js)。
前者的好处是测试流程无需做过多修改,坏处则是无法享受编辑器对于 GLSL 的语法高亮,影响开发体验。而后者又需要编写额外的 `glsl2js` 的转换脚本。
我们显然希望如后者一样直接写 GLSL但最好能让测试框架帮助我们完成自动转换的工作。
之前我们选择 `@babel/preset-typescript` 而非官方 `tsc` 的一大原因就是可以使用 `babel` 丰富的插件,`babel-plugin-inline-import` 就能完成类似 webpack 中 `raw-loader` 的功能,直接以字符串形式引入 GLSL 代码:
```javascript
// 以字符串形式引入 GLSL 代码
import circleFrag from '../../shaders/circle_frag.glsl';
```
这样测试框架只需要使用同一套 babel 项目全局配置就行了。我们使用 Jest
```javascript
// jest.config.js
module.exports = {
transform: {
'^.+\\.(ts|tsx)$': 'babel-jest',
},
}
```
下面就可以编写测试用例了。
## 测试用例编写
我们将测试用例分成三类:
* 内部服务的单元测试
* 渲染服务结果的 Snapshot 快照测试
* React 组件测试
将测试用例放在任意路径的 `__tests__` 文件夹下并以 `xxx.spec.ts` 命名就可以帮助框架发现并执行了。
使用 `yarn test` 运行所有测试用例:
![](./screenshots/jest.png)
### 单元测试
这类测试直接使用 Jest API 就好了,我们以 `@l7/core` 模块的 `ShaderModuleService` 为例,编写一个简单的测试用例:
```typescript
// services/shader/__test__/shader.spec.ts
import 'reflect-metadata';
import IShaderModuleService from '../IShaderModuleService';
import ShaderModuleService from '../ShaderModuleService';
describe('ShaderService', () => {
let shaderService: IShaderModuleService;
beforeEach(() => {
shaderService = new ShaderModuleService();
});
it('should register common module correctly and generate fragment/vertex shader code', () => {
const rawShaderCode = `
#define PI 3.14
`;
const commonModule = {
fs: rawShaderCode,
vs: rawShaderCode,
};
shaderService.registerModule('common', commonModule);
const { vs, fs } = shaderService.getModule('common');
expect(vs).toMatch(/3\.14/);
expect(fs).toMatch(/3\.14/);
});
});
```
### 渲染结果测试
得益于 L7 使用的基于 Inversify 的依赖注入方案,我们能够很轻易地将渲染服务替换为基于 headless-gl 的渲染服务。
具体到我们目前的渲染服务实现 `regl`,它能轻易做到这一点。事实上 regl 的[测试用例](https://github.com/regl-project/regl/blob/gh-pages/test/util/create-context.js#L28)也是这样使用的。
### [WIP] React 组件测试
### Coverage Report
我们使用 Coveralls.io
```json
// package.json
"coveralls": "jest --coverage && cat ./tests/coverage/lcov.info | coveralls",
```
运行 `yarn coveralls` 可以查看代码覆盖率,我们为分支、行覆盖率等指标设置了阈值:
```javascript
// jest.config.js
module.exports = {
coverageThreshold: {
global: {
branches: 80,
functions: 80,
lines: 80,
statements: 80,
},
},
};
```
## TravisCI
TravisCI 检测到 `yarn.lock` 就会默认安装 `yarn` 并使用它安装依赖,所以不需要[额外的配置](https://yarnpkg.com/en/docs/install-ci#travis-tab)。
TravisCI 配合之前的 Coveralls.io。

View File

@ -1,6 +1,12 @@
module.exports = {
preset: 'ts-jest',
clearMocks: true,
collectCoverageFrom: [
'packages/**/*.{ts,tsx}',
'!**/node_modules/**',
'!**/__tests__/**',
'!**/*.d.ts'
],
coverageDirectory: 'coverage',
coverageReporters: ['text', 'clover'],
coverageThreshold: {

View File

@ -21,6 +21,7 @@
"@types/dat.gui": "^0.7.1",
"@types/enzyme": "^3.1.14",
"@types/enzyme-adapter-react-16": "^1.0.3",
"@types/gl": "^4.1.0",
"@types/jest": "^24.0.18",
"@types/node": "^12.7.3",
"@types/storybook__react": "^4.0.2",
@ -35,12 +36,14 @@
"clean-webpack-plugin": "^0.1.19",
"commitizen": "^4.0.3",
"copy-webpack-plugin": "^4.5.2",
"coveralls": "^3.0.7",
"css-loader": "^3.2.0",
"cz-conventional-changelog": "^3.0.2",
"dat.gui": "^0.7.2",
"enzyme": "^3.6.0",
"enzyme-adapter-react-16": "^1.5.0",
"enzyme-to-json": "^3.0.0-beta6",
"gl": "^4.4.0",
"html-webpack-plugin": "^3.2.0",
"husky": "^3.0.9",
"jest": "^24.9.0",
@ -93,6 +96,7 @@
"release": "lerna publish from-git",
"storybook": "start-storybook -p 6006",
"test": "jest",
"coveralls": "jest --coverage && cat ./tests/coverage/lcov.info | coveralls",
"tsc": "tsc",
"build:declarations": "lerna exec --stream --no-bail 'tsc --project ./tsconfig.build.json'",
"watch": "lerna exec --parallel 'BABEL_ENV=build babel --watch src --root-mode upward --out-dir dist --source-maps --extensions .ts,.tsx --delete-dir-on-start --no-comments'"

View File

@ -154,35 +154,35 @@ export const lazyMultiInject = (
// 绑定 post processing passes
container
.bind<IPostProcessingPass<unknown>>(TYPES.INewablePostProcessingPass)
.bind<IPostProcessingPass<unknown>>(TYPES.IPostProcessingPass)
.to(CopyPass)
.whenTargetNamed('copy');
container
.bind<IPostProcessingPass<unknown>>(TYPES.INewablePostProcessingPass)
.bind<IPostProcessingPass<unknown>>(TYPES.IPostProcessingPass)
.to(BlurHPass)
.whenTargetNamed('blurH');
container
.bind<IPostProcessingPass<unknown>>(TYPES.INewablePostProcessingPass)
.bind<IPostProcessingPass<unknown>>(TYPES.IPostProcessingPass)
.to(BlurVPass)
.whenTargetNamed('blurV');
container
.bind<IPostProcessingPass<unknown>>(TYPES.INewablePostProcessingPass)
.bind<IPostProcessingPass<unknown>>(TYPES.IPostProcessingPass)
.to(NoisePass)
.whenTargetNamed('noise');
container
.bind<IPostProcessingPass<unknown>>(TYPES.INewablePostProcessingPass)
.bind<IPostProcessingPass<unknown>>(TYPES.IPostProcessingPass)
.to(SepiaPass)
.whenTargetNamed('sepia');
container
.bind<IPostProcessingPass<unknown>>(TYPES.INewablePostProcessingPass)
.bind<IPostProcessingPass<unknown>>(TYPES.IPostProcessingPass)
.to(ColorHalfTonePass)
.whenTargetNamed('colorHalftone');
container
.bind<IPostProcessingPass<unknown>>(TYPES.INewablePostProcessingPass)
.bind<IPostProcessingPass<unknown>>(TYPES.IPostProcessingPass)
.to(HexagonalPixelatePass)
.whenTargetNamed('hexagonalPixelate');
container
.bind<IPostProcessingPass<unknown>>(TYPES.INewablePostProcessingPass)
.bind<IPostProcessingPass<unknown>>(TYPES.IPostProcessingPass)
.to(InkPass)
.whenTargetNamed('ink');
@ -190,13 +190,11 @@ container
.bind<interfaces.Factory<IPostProcessingPass<unknown>>>(
TYPES.IFactoryPostProcessingPass,
)
.toFactory<IPostProcessingPass<unknown>>((context) => {
return (named: string) => {
return context.container.getNamed<IPostProcessingPass<unknown>>(
TYPES.INewablePostProcessingPass,
named,
);
};
});
.toFactory<IPostProcessingPass<unknown>>((context) => (named: string) =>
context.container.getNamed<IPostProcessingPass<unknown>>(
TYPES.IPostProcessingPass,
named,
),
);
export default container;

View File

@ -21,6 +21,16 @@ export default class CameraService implements ICameraService {
*/
private jitteredProjectionMatrix: number[] | undefined;
/**
* ViewMatrix
*/
private viewMatrixInverse: number[];
/**
*
*/
private cameraPosition: number[];
public init() {
//
}
@ -30,6 +40,18 @@ export default class CameraService implements ICameraService {
*/
public update(viewport: IViewport) {
this.viewport = viewport;
// 计算逆矩阵
this.viewMatrixInverse = (mat4.invert(
mat4.create(),
(this.getViewMatrix() as unknown) as mat4,
) as unknown) as number[];
this.cameraPosition = [
this.viewMatrixInverse[12],
this.viewMatrixInverse[13],
this.viewMatrixInverse[14],
];
}
public getProjectionMatrix(): number[] {
@ -70,6 +92,10 @@ export default class CameraService implements ICameraService {
return this.viewport.getFocalDistance();
}
public getCameraPosition() {
return this.cameraPosition;
}
public projectFlat(
lngLat: [number, number],
scale?: number | undefined,

View File

@ -30,6 +30,7 @@ export interface IViewport {
export interface ICameraService extends Omit<IViewport, 'syncWithMapCamera'> {
init(): void;
update(viewport: IViewport): void;
getCameraPosition(): number[];
setViewProjectionMatrix(viewProjectionMatrix: number[] | undefined): void;
jitterProjectionMatrix(x: number, y: number): void;
clearJitterProjectionMatrix(): void;

View File

@ -1,11 +1,11 @@
import { inject, injectable } from 'inversify';
import { injectable } from 'inversify';
import { lazyInject } from '../../../index';
import blendFS from '../../../shaders/post-processing/blend.glsl';
import copyFS from '../../../shaders/post-processing/copy.glsl';
import quadVS from '../../../shaders/post-processing/quad.glsl';
import { TYPES } from '../../../types';
import { ICameraService } from '../../camera/ICameraService';
import { ILayer, ILayerService } from '../../layer/ILayerService';
import { ILayer } from '../../layer/ILayerService';
import { ILogService } from '../../log/ILogService';
import { IShaderModuleService } from '../../shader/IShaderModuleService';
import { gl } from '../gl';
@ -191,8 +191,7 @@ export default class TAAPass<InitializationOptions = {}>
};
this.accumulatingId = accumulatingId++;
// @ts-ignore
this.timer = setTimeout(() => {
this.timer = window.setTimeout(() => {
accumulate(this.accumulatingId);
}, 50);
}

View File

@ -1,11 +1,11 @@
// Blinn-Phong model
// apply lighting in vertex shader instead of fragment shader
// @see https://learnopengl.com/Advanced-Lighting/Advanced-Lighting
uniform float u_ambient : 1.0;
uniform float u_diffuse : 1.0;
uniform float u_specular : 1.0;
uniform int u_num_of_directional_lights : 1;
uniform int u_num_of_spot_lights : 0;
uniform float u_Ambient : 1.0;
uniform float u_Diffuse : 1.0;
uniform float u_Specular : 1.0;
uniform int u_NumOfDirectionalLights : 1;
uniform int u_NumOfSpotLights : 0;
#define SHININESS 32.0
#define MAX_NUM_OF_DIRECTIONAL_LIGHTS 3
@ -32,8 +32,8 @@ struct SpotLight {
float exponent;
};
uniform DirectionalLight u_directional_lights[MAX_NUM_OF_DIRECTIONAL_LIGHTS];
uniform SpotLight u_spot_lights[MAX_NUM_OF_SPOT_LIGHTS];
uniform DirectionalLight u_DirectionalLights[MAX_NUM_OF_DIRECTIONAL_LIGHTS];
uniform SpotLight u_SpotLights[MAX_NUM_OF_SPOT_LIGHTS];
vec3 calc_directional_light(DirectionalLight light, vec3 normal, vec3 viewDir) {
vec3 lightDir = normalize(light.direction);
@ -43,9 +43,9 @@ vec3 calc_directional_light(DirectionalLight light, vec3 normal, vec3 viewDir) {
vec3 halfwayDir = normalize(lightDir + viewDir);
float spec = pow(max(dot(normal, halfwayDir), 0.0), SHININESS);
vec3 ambient = light.ambient * u_ambient;
vec3 diffuse = light.diffuse * diff * u_diffuse;
vec3 specular = light.specular * spec * u_specular;
vec3 ambient = light.ambient * u_Ambient;
vec3 diffuse = light.diffuse * diff * u_Diffuse;
vec3 specular = light.specular * spec * u_Specular;
return ambient + diffuse + specular;
}
@ -62,9 +62,9 @@ vec3 calc_directional_light(DirectionalLight light, vec3 normal, vec3 viewDir) {
// float attenuation = 1.0 / (light.constant + light.linear * distance +
// light.quadratic * (distance * distance));
// vec3 ambient = light.ambient * u_ambient;
// vec3 diffuse = light.diffuse * diff * u_diffuse;
// vec3 specular = light.specular * spec * u_specular;
// vec3 ambient = light.ambient * u_Ambient;
// vec3 diffuse = light.diffuse * diff * u_Diffuse;
// vec3 specular = light.specular * spec * u_Specular;
// float spotEffect = dot(normalize(light.direction), -lightDir);
// float spotCosCutoff = cos(light.angle / 180.0 * PI);
@ -82,16 +82,16 @@ vec3 calc_directional_light(DirectionalLight light, vec3 normal, vec3 viewDir) {
vec3 calc_lighting(vec3 position, vec3 normal, vec3 viewDir) {
vec3 weight = vec3(0.0);
for (int i = 0; i < MAX_NUM_OF_DIRECTIONAL_LIGHTS; i++) {
if (i >= u_num_of_directional_lights) {
if (i >= u_NumOfDirectionalLights) {
break;
}
weight += calc_directional_light(u_directional_lights[i], normal, viewDir);
weight += calc_directional_light(u_DirectionalLights[i], normal, viewDir);
}
// for (int i = 0; i < MAX_NUM_OF_SPOT_LIGHTS; i++) {
// if (i >= u_num_of_spot_lights) {
// if (i >= u_NumOfSpotLights) {
// break;
// }
// weight += calc_spot_light(u_spot_lights[i], normal, position, viewDir);
// weight += calc_spot_light(u_SpotLights[i], normal, position, viewDir);
// }
return weight;
}

View File

@ -26,6 +26,7 @@ uniform vec3 u_PixelsPerMeter;
uniform vec2 u_ViewportSize;
uniform float u_DevicePixelRatio;
uniform float u_FocalDistance;
uniform vec3 u_CameraPosition;
// web mercator coords -> world coords
vec2 project_mercator(vec2 lnglat) {
@ -53,6 +54,15 @@ vec3 project_normal(vec3 normal) {
return normalize(normal_modelspace.xyz * u_PixelsPerMeter);
}
vec3 project_offset_normal(vec3 vector) {
if (u_CoordinateSystem == COORDINATE_SYSTEM_LNGLAT
|| u_CoordinateSystem == COORDINATE_SYSTEM_LNGLAT_OFFSET) {
// normals generated by the polygon tesselator are in lnglat offsets instead of meters
return normalize(vector * u_PixelsPerDegree);
}
return project_normal(vector);
}
vec4 project_position(vec4 position) {
if (u_CoordinateSystem == COORDINATE_SYSTEM_LNGLAT_OFFSET
|| u_CoordinateSystem == COORDINATE_SYSTEM_P20_OFFSET) {

View File

@ -17,7 +17,7 @@ const TYPES = {
IControlService: Symbol.for('IControlService'),
IStyleAttributeService: Symbol.for('IStyleAttributeService'),
ILayerPlugin: Symbol.for('ILayerPlugin'),
INewablePostProcessingPass: Symbol.for('Newable<IPostProcessingPass>'),
IPostProcessingPass: Symbol.for('IPostProcessingPass'),
IFactoryPostProcessingPass: Symbol.for('Factory<IPostProcessingPass>'),
};

View File

@ -14,6 +14,7 @@ import ConfigSchemaValidationPlugin from './plugins/ConfigSchemaValidationPlugin
import DataMappingPlugin from './plugins/DataMappingPlugin';
import DataSourcePlugin from './plugins/DataSourcePlugin';
import FeatureScalePlugin from './plugins/FeatureScalePlugin';
import LightingPlugin from './plugins/LightingPlugin';
import MultiPassRendererPlugin from './plugins/MultiPassRendererPlugin';
import PixelPickingPlugin from './plugins/PixelPickingPlugin';
import RegisterStyleAttributePlugin from './plugins/RegisterStyleAttributePlugin';
@ -57,6 +58,10 @@ container.bind<ILayerPlugin>(TYPES.ILayerPlugin).to(MultiPassRendererPlugin);
*
*/
container.bind<ILayerPlugin>(TYPES.ILayerPlugin).to(ShaderUniformPlugin);
/**
*
*/
container.bind<ILayerPlugin>(TYPES.ILayerPlugin).to(LightingPlugin);
/**
* Encode Highlight
*/

View File

@ -0,0 +1,133 @@
import {
CameraUniform,
CoordinateUniform,
ICameraService,
ICoordinateSystemService,
ILayer,
ILayerPlugin,
IRendererService,
TYPES,
} from '@l7/core';
import { inject, injectable } from 'inversify';
const lightTypeUniformMap = {
directional: {
lights: 'u_DirectionalLights',
num: 'u_NumOfDirectionalLights',
},
spot: {
lights: 'u_SpotLights',
num: 'u_NumOfSpotLights',
},
};
interface IDirectionalLight {
type: 'directional';
direction: [number, number, number];
ambient: [number, number, number];
diffuse: [number, number, number];
specular: [number, number, number];
}
interface ISpotLight {
type: 'spot';
position: [number, number, number];
direction: [number, number, number];
ambient: [number, number, number];
diffuse: [number, number, number];
specular: [number, number, number];
constant: number;
linear: number;
quadratic: number;
angle: number;
exponent: number;
blur: number;
}
const DEFAULT_LIGHT: IDirectionalLight = {
type: 'directional',
direction: [1, 10.5, 12],
ambient: [0.2, 0.2, 0.2],
diffuse: [0.6, 0.6, 0.6],
specular: [0.1, 0.1, 0.1],
};
const DEFAULT_DIRECTIONAL_LIGHT = {
direction: [0, 0, 0],
ambient: [0, 0, 0],
diffuse: [0, 0, 0],
specular: [0, 0, 0],
};
const DEFAULT_SPOT_LIGHT = {
position: [0, 0, 0],
direction: [0, 0, 0],
ambient: [0, 0, 0],
diffuse: [0, 0, 0],
specular: [0, 0, 0],
constant: 1,
linear: 0,
quadratic: 0,
angle: 14,
exponent: 40,
blur: 5,
};
const COLOR_ATTRIBUTES = ['ambient', 'diffuse', 'specular'];
export function generateLightingUniforms(
lights?: Array<Partial<IDirectionalLight | ISpotLight>>,
) {
const lightsMap: {
u_DirectionalLights: IDirectionalLight[];
u_NumOfDirectionalLights: number;
u_SpotLights: ISpotLight[];
u_NumOfSpotLights: number;
} = {
u_DirectionalLights: new Array(3).fill({ ...DEFAULT_DIRECTIONAL_LIGHT }),
u_NumOfDirectionalLights: 0,
u_SpotLights: new Array(3).fill({ ...DEFAULT_SPOT_LIGHT }),
u_NumOfSpotLights: 0,
};
if (!lights || !lights.length) {
lights = [DEFAULT_LIGHT];
}
lights.forEach(({ type = 'directional', ...rest }, i) => {
const lightsUniformName = lightTypeUniformMap[type].lights;
const lightsNumUniformName = lightTypeUniformMap[type].num;
// Object.keys(rest).forEach(key => {
// if (Util.isString(rest[key]) && COLOR_ATTRIBUTES.indexOf(key) > -1) {
// rest[key] = ColorUtil.color2RGBA(rest[key]).slice(0, 3);
// }
// });
// @ts-ignore
const num = lightsMap[lightsNumUniformName];
// @ts-ignore
lightsMap[lightsUniformName][num] = {
// @ts-ignore
...lightsMap[lightsUniformName][num],
...rest,
};
// @ts-ignore
lightsMap[lightsNumUniformName]++;
});
return lightsMap;
}
/**
* & Shadow
*/
@injectable()
export default class LightingPlugin implements ILayerPlugin {
public apply(layer: ILayer) {
layer.hooks.beforeRender.tap('LightingPlugin', () => {
layer.models.forEach((model) =>
model.addUniforms({
//
}),
);
});
}
}

View File

@ -28,7 +28,9 @@ export function normalizePasses(
}
/**
* Layer passes MultiPassRenderer
* 线
* ClearPass -> PixelPickingPass() -> RenderPass/TAAPass -> PostProcessing -> CopyPass
* Layer passes PostProcessing
* @example
* new PolygonLayer({
* enableMultiPassRenderer: true,

View File

@ -45,6 +45,7 @@ export default class ShaderUniformPlugin implements ILayerPlugin {
[CameraUniform.Zoom]: this.cameraService.getZoom(),
[CameraUniform.ZoomScale]: this.cameraService.getZoomScale(),
[CameraUniform.FocalDistance]: this.cameraService.getFocalDistance(),
[CameraUniform.CameraPosition]: this.cameraService.getCameraPosition(),
// 坐标系参数
[CoordinateUniform.CoordinateSystem]: this.coordinateSystemService.getCoordinateSystem(),
[CoordinateUniform.ViewportCenter]: this.coordinateSystemService.getViewportCenter(),

View File

@ -0,0 +1,47 @@
import 'reflect-metadata';
import { generateLightingUniforms } from '../LightingPlugin';
describe('LightingPlugin', () => {
it('should generate proper uniforms for a directional light', () => {
const lightsMap = generateLightingUniforms([
{
type: 'directional',
},
]);
expect(lightsMap.u_NumOfDirectionalLights).toEqual(1);
expect(lightsMap.u_NumOfSpotLights).toEqual(0);
});
it('should generate proper uniforms for directional and spot lights', () => {
const lightsMap = generateLightingUniforms([
{
type: 'directional',
},
{
type: 'spot',
},
]);
expect(lightsMap.u_NumOfDirectionalLights).toEqual(1);
expect(lightsMap.u_NumOfSpotLights).toEqual(1);
});
it('should generate proper uniforms for directional and spot lights', () => {
const lightsMap = generateLightingUniforms([
{
type: 'directional',
ambient: [1, 1, 1],
},
{
type: 'spot',
angle: 10,
},
]);
expect(lightsMap.u_NumOfDirectionalLights).toEqual(1);
expect(lightsMap.u_NumOfSpotLights).toEqual(1);
expect(lightsMap.u_DirectionalLights[0].ambient).toEqual([1, 1, 1]);
expect(lightsMap.u_SpotLights[0].angle).toEqual(10);
});
});

View File

@ -8,12 +8,16 @@ varying vec4 v_Color;
#pragma include "projection"
#pragma include "picking"
#pragma include "lighting"
void main() {
v_Color = vec4(a_Normal,1.0);
vec4 project_pos = project_position(vec4(a_Position.xy,a_Position.z * a_Size, 1.0));
vec4 project_pos = project_position(vec4(a_Position.xy, a_Position.z * a_Size, 1.0));
gl_Position = project_common_position_to_clipspace(vec4(project_pos.xyz, 1.0));
vec3 viewDir = normalize(u_CameraPosition - project_pos.xyz);
vec3 normal = project_offset_normal(a_Normal);
v_Color.rgb *= calc_lighting(a_Position, normal, viewDir);
setPickingColor(a_PickingColor);
}

View File

@ -0,0 +1,76 @@
import 'reflect-metadata';
import regl from 'regl';
import ReglModel from '../ReglModel';
import createContext from './utils/create-context';
describe('ReglModel', () => {
let gl;
let reGL: regl.Regl;
beforeEach(() => {
gl = createContext(1, 1);
reGL = regl(gl);
});
it('should generate model with empty uniforms correctly', () => {
const model = new ReglModel(reGL, {
vs: 'void main() {gl_Position = vec4(0.);}',
fs: 'void main() {gl_FragColor = vec4(0.);}',
attributes: {},
});
// @ts-ignore
expect(model.uniforms).toEqual({});
});
it('should generate model with uniforms correctly', () => {
const model = new ReglModel(reGL, {
vs: 'void main() {gl_Position = vec4(0.);}',
fs: 'void main() {gl_FragColor = vec4(0.);}',
attributes: {},
uniforms: {
u_1: 1,
u_2: [1, 2],
},
});
// @ts-ignore
expect(model.uniforms.u_1).toEqual(1);
// @ts-ignore
expect(model.uniforms.u_2).toEqual([1, 2]);
});
it('should generate model with struct uniforms correctly', () => {
// 支持 struct 结构,例如 'colors[0].r'
// @see https://github.com/regl-project/regl/blob/gh-pages/API.md#uniforms
const model = new ReglModel(reGL, {
vs: 'void main() {gl_Position = vec4(0.);}',
fs: 'void main() {gl_FragColor = vec4(0.);}',
attributes: {},
// @ts-ignore
uniforms: {
u_Struct: [
{
a: 1,
b: [1, 2],
},
{
a: 2,
b: [3, 4],
},
],
},
});
expect(model.uniforms['u_Struct[0].a']).toEqual(undefined);
// // @ts-ignore
// expect(model.uniforms['u_Struct[0].a']).toEqual(1);
// // @ts-ignore
// expect(model.uniforms['u_Struct[0].b']).toEqual([1, 2]);
// // @ts-ignore
// expect(model.uniforms['u_Struct[1].a']).toEqual(2);
// // @ts-ignore
// expect(model.uniforms['u_Struct[1].b']).toEqual([3, 4]);
});
});

View File

@ -0,0 +1,21 @@
import gl from 'gl';
// borrow from regl
// @see https://github.com/regl-project/regl/blob/gh-pages/test/util/create-context.js#L28
const CONTEXT = gl(1, 1, { preserveDrawingBuffer: true });
const RESIZE = CONTEXT.getExtension('STACKGL_resize_drawingbuffer');
export default function(width: number, height: number) {
resize(width, height);
return CONTEXT;
}
export function resize(width: number, height: number) {
if (RESIZE) {
RESIZE.resize(width, height);
}
}
export function destroy() {
//
}

239
yarn.lock
View File

@ -2948,6 +2948,11 @@
resolved "https://registry.yarnpkg.com/@types/gl-matrix/-/gl-matrix-2.4.5.tgz#80630d88fb74ff8897a2a2855a8a700e6ee19d3e"
integrity sha512-0L8Mq1+oaIW0oVzGUDbSW+HnTjCNb4CmoIQE5BkoHt/A7x20z0MJ1PnwfH3atty/vbWLGgvJwVu2Mz3SKFiEFw==
"@types/gl@^4.1.0":
version "4.1.0"
resolved "https://registry.yarnpkg.com/@types/gl/-/gl-4.1.0.tgz#44d48283f1ffb5e6698de145b805fa1bf80ca4aa"
integrity sha512-XdyM2/Q+XAsdw69t23YD812fY3KDw9dYmULZTOGMFM2tLaweBtcVzUnOwsMzF7i0dvFDL0GnawYwEq/+hvUZtw==
"@types/glob@^7.1.1":
version "7.1.1"
resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.1.1.tgz#aa59a1c6e3fbc421e07ccd31a944c30eba521575"
@ -4288,6 +4293,25 @@ binary-extensions@^1.0.0:
resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.1.tgz#598afe54755b2868a5330d2aff9d4ebb53209b65"
integrity sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==
bindings@^1.5.0:
version "1.5.0"
resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df"
integrity sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==
dependencies:
file-uri-to-path "1.0.0"
bit-twiddle@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/bit-twiddle/-/bit-twiddle-1.0.2.tgz#0c6c1fabe2b23d17173d9a61b7b7093eb9e1769e"
integrity sha1-DGwfq+KyPRcXPZpht7cJPrnhdp4=
bl@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/bl/-/bl-3.0.0.tgz#3611ec00579fd18561754360b21e9f784500ff88"
integrity sha512-EUAyP5UHU5hxF8BPT0LKW8gjYLhq1DQIcneOX/pL/m2Alo+OYDQAJlHq+yseMP50Os2nHXOSic6Ss3vSQeyf4A==
dependencies:
readable-stream "^3.0.1"
block-stream@*:
version "0.0.9"
resolved "https://registry.yarnpkg.com/block-stream/-/block-stream-0.0.9.tgz#13ebfe778a03205cfe03751481ebb4b3300c126a"
@ -5437,6 +5461,18 @@ cosmiconfig@^5.0.0, cosmiconfig@^5.1.0, cosmiconfig@^5.2.0, cosmiconfig@^5.2.1:
js-yaml "^3.13.1"
parse-json "^4.0.0"
coveralls@^3.0.7:
version "3.0.7"
resolved "https://registry.yarnpkg.com/coveralls/-/coveralls-3.0.7.tgz#1eca48e47976e9573d6a2f18b97c2fea4026f34a"
integrity sha512-mUuH2MFOYB2oBaA4D4Ykqi9LaEYpMMlsiOMJOrv358yAjP6enPIk55fod2fNJ8AvwoYXStWQls37rA+s5e7boA==
dependencies:
growl "~> 1.10.0"
js-yaml "^3.13.1"
lcov-parse "^0.0.10"
log-driver "^1.2.7"
minimist "^1.2.0"
request "^2.86.0"
create-ecdh@^4.0.0:
version "4.0.3"
resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.3.tgz#c9111b6f33045c4697f144787f9254cdc77c45ff"
@ -5881,6 +5917,13 @@ decode-uri-component@^0.2.0:
resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545"
integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=
decompress-response@^4.2.0:
version "4.2.1"
resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-4.2.1.tgz#414023cc7a302da25ce2ec82d0d5238ccafd8986"
integrity sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==
dependencies:
mimic-response "^2.0.0"
dedent@0.7.0, dedent@^0.7.0:
version "0.7.0"
resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c"
@ -6042,7 +6085,7 @@ detect-indent@^5.0.0:
resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-5.0.0.tgz#3871cc0a6a002e8c3e5b3cf7f336264675f06b9d"
integrity sha1-OHHMCmoALow+Wzz38zYmRnXwa50=
detect-libc@^1.0.2:
detect-libc@^1.0.2, detect-libc@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b"
integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=
@ -6384,7 +6427,7 @@ encoding@^0.1.11:
dependencies:
iconv-lite "~0.4.13"
end-of-stream@^1.0.0, end-of-stream@^1.1.0:
end-of-stream@^1.0.0, end-of-stream@^1.1.0, end-of-stream@^1.4.1:
version "1.4.4"
resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0"
integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==
@ -6774,6 +6817,11 @@ expand-brackets@^2.1.4:
snapdragon "^0.8.1"
to-regex "^3.0.1"
expand-template@^2.0.3:
version "2.0.3"
resolved "https://registry.yarnpkg.com/expand-template/-/expand-template-2.0.3.tgz#6e14b3fcee0f3a6340ecb57d2e8918692052a47c"
integrity sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==
expand-tilde@^2.0.0, expand-tilde@^2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/expand-tilde/-/expand-tilde-2.0.2.tgz#97e801aa052df02454de46b02bf621642cdc8502"
@ -7040,6 +7088,11 @@ file-system-cache@^1.0.5:
fs-extra "^0.30.0"
ramda "^0.21.0"
file-uri-to-path@1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd"
integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==
filesize@3.6.1:
version "3.6.1"
resolved "https://registry.yarnpkg.com/filesize/-/filesize-3.6.1.tgz#090bb3ee01b6f801a8a8be99d31710b3422bb317"
@ -7264,6 +7317,11 @@ from2@^2.1.0:
inherits "^2.0.1"
readable-stream "^2.0.0"
fs-constants@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad"
integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==
fs-extra@8.1.0, fs-extra@^8.0.1, fs-extra@^8.1.0:
version "8.1.0"
resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0"
@ -7529,6 +7587,11 @@ gitconfiglocal@^1.0.0:
dependencies:
ini "^1.3.2"
github-from-package@0.0.0:
version "0.0.0"
resolved "https://registry.yarnpkg.com/github-from-package/-/github-from-package-0.0.0.tgz#97fb5d96bfde8973313f20e8288ef9a167fa64ce"
integrity sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4=
gl-matrix@^3.0.0, gl-matrix@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/gl-matrix/-/gl-matrix-3.1.0.tgz#f5b2de17d8fed95a79e5025b10cded0ab9ccbed0"
@ -7539,6 +7602,18 @@ gl-vec2@^1.0.0, gl-vec2@^1.3.0:
resolved "https://registry.yarnpkg.com/gl-vec2/-/gl-vec2-1.3.0.tgz#83d472ed46034de8e09cbc857123fb6c81c51199"
integrity sha512-YiqaAuNsheWmUV0Sa8k94kBB0D6RWjwZztyO+trEYS8KzJ6OQB/4686gdrf59wld4hHFIvaxynO3nRxpk1Ij/A==
gl@^4.4.0:
version "4.4.0"
resolved "https://registry.yarnpkg.com/gl/-/gl-4.4.0.tgz#3d448769a9222ba809da4db80dd1f3c4b85498a0"
integrity sha512-4FIq5tqiltTsadrLh6DGY4R9+aQwj25OM2WlXEv81N6YN1q1C0qR7ct0SKp1uUJdnBqbKhUJP3zQ1td40AVeJg==
dependencies:
bindings "^1.5.0"
bit-twiddle "^1.0.2"
glsl-tokenizer "^2.0.2"
nan "^2.14.0"
node-gyp "^4.0.0"
prebuild-install "^5.1.0"
glob-parent@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae"
@ -7737,6 +7812,13 @@ globule@^1.0.0:
lodash "~4.17.10"
minimatch "~3.0.2"
glsl-tokenizer@^2.0.2:
version "2.1.5"
resolved "https://registry.yarnpkg.com/glsl-tokenizer/-/glsl-tokenizer-2.1.5.tgz#1c2e78c16589933c274ba278d0a63b370c5fee1a"
integrity sha512-XSZEJ/i4dmz3Pmbnpsy3cKh7cotvFlBiZnDOwnj/05EwNp2XrhQ4XKJxT7/pDt4kp4YcpRSKz8eTV7S+mwV6MA==
dependencies:
through2 "^0.6.3"
gonzales-pe@^4.2.3:
version "4.2.4"
resolved "https://registry.yarnpkg.com/gonzales-pe/-/gonzales-pe-4.2.4.tgz#356ae36a312c46fe0f1026dd6cb539039f8500d2"
@ -7761,6 +7843,11 @@ grid-index@^1.1.0:
resolved "https://registry.yarnpkg.com/grid-index/-/grid-index-1.1.0.tgz#97f8221edec1026c8377b86446a7c71e79522ea7"
integrity sha512-HZRwumpOGUrHyxO5bqKZL0B0GlUpwtCAzZ42sgxUPniu33R1LSFH5yrIcBCHjkctCAh3mtWKcKd9J4vDDdeVHA==
"growl@~> 1.10.0":
version "1.10.5"
resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e"
integrity sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==
growly@^1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081"
@ -8853,6 +8940,11 @@ is-wsl@^1.1.0:
resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-1.1.0.tgz#1f16e4aa22b04d1336b66188a66af3c600c3a66d"
integrity sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=
isarray@0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf"
integrity sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=
isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
@ -9570,6 +9662,11 @@ lcid@^2.0.0:
dependencies:
invert-kv "^2.0.0"
lcov-parse@^0.0.10:
version "0.0.10"
resolved "https://registry.yarnpkg.com/lcov-parse/-/lcov-parse-0.0.10.tgz#1b0b8ff9ac9c7889250582b70b71315d9da6d9a3"
integrity sha1-GwuP+ayceIklBYK3C3ExXZ2m2aM=
left-pad@^1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/left-pad/-/left-pad-1.3.0.tgz#5b8a3a7765dfe001261dde915589e782f8c94d1e"
@ -9879,6 +9976,11 @@ lodash@4.17.15, lodash@^4.0.0, lodash@^4.0.1, lodash@^4.15.0, lodash@^4.17.11, l
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548"
integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==
log-driver@^1.2.7:
version "1.2.7"
resolved "https://registry.yarnpkg.com/log-driver/-/log-driver-1.2.7.tgz#63b95021f0702fedfa2c9bb0a24e7797d71871d8"
integrity sha512-U7KCmLdqsGHBLeWqYlFA0V0Sl6P08EE1ZrmA9cxjUE0WVqT9qnyVDPz1kzpFEP0jdJuFnasWIfSd7fsaNXkpbg==
log-symbols@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-1.0.2.tgz#376ff7b58ea3086a0f09facc74617eca501e1a18"
@ -10377,6 +10479,11 @@ mimic-fn@^2.0.0, mimic-fn@^2.1.0:
resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b"
integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==
mimic-response@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-2.0.0.tgz#996a51c60adf12cb8a87d7fb8ef24c2f3d5ebb46"
integrity sha512-8ilDoEapqA4uQ3TwS0jakGONKXVJqpy+RpM+3b7pLdOjghCrEiGp9SRkFbUHAmZW9vdnrENWHjaweIoTIJExSQ==
min-document@^2.19.0:
version "2.19.0"
resolved "https://registry.yarnpkg.com/min-document/-/min-document-2.19.0.tgz#7bd282e3f5842ed295bb748cdd9f1ffa2c824685"
@ -10605,7 +10712,7 @@ mz@^2.5.0:
object-assign "^4.0.1"
thenify-all "^1.0.0"
nan@^2.12.1, nan@^2.13.2:
nan@^2.12.1, nan@^2.13.2, nan@^2.14.0:
version "2.14.0"
resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.0.tgz#7818f722027b2459a86f0295d434d1fc2336c52c"
integrity sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==
@ -10627,6 +10734,11 @@ nanomatch@^1.2.9:
snapdragon "^0.8.1"
to-regex "^3.0.1"
napi-build-utils@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/napi-build-utils/-/napi-build-utils-1.0.1.tgz#1381a0f92c39d66bf19852e7873432fc2123e508"
integrity sha512-boQj1WFgQH3v4clhu3mTNfP+vOBxorDlE8EKiMjUlLG3C4qAESnn9AxIOkFgTR2c9LtzNjPrjS60cT27ZKBhaA==
natural-compare@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
@ -10684,6 +10796,13 @@ no-case@^2.2.0:
dependencies:
lower-case "^1.1.1"
node-abi@^2.7.0:
version "2.12.0"
resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-2.12.0.tgz#40e9cfabdda1837863fa825e7dfa0b15686adf6f"
integrity sha512-VhPBXCIcvmo/5K8HPmnWJyyhvgKxnHTUMXR/XwGHV68+wrgkzST4UmQrY/XszSWA5dtnXpNp528zkcyJ/pzVcw==
dependencies:
semver "^5.4.1"
node-dir@^0.1.10:
version "0.1.17"
resolved "https://registry.yarnpkg.com/node-dir/-/node-dir-0.1.17.tgz#5f5665d93351335caabef8f1c554516cf5f1e4e5"
@ -10736,6 +10855,23 @@ node-gyp@^3.8.0:
tar "^2.0.0"
which "1"
node-gyp@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-4.0.0.tgz#972654af4e5dd0cd2a19081b4b46fe0442ba6f45"
integrity sha512-2XiryJ8sICNo6ej8d0idXDEMKfVfFK7kekGCtJAuelGsYHQxhj13KTf95swTCN2dZ/4lTfZ84Fu31jqJEEgjWA==
dependencies:
glob "^7.0.3"
graceful-fs "^4.1.2"
mkdirp "^0.5.0"
nopt "2 || 3"
npmlog "0 || 1 || 2 || 3 || 4"
osenv "0"
request "^2.87.0"
rimraf "2"
semver "~5.3.0"
tar "^4.4.8"
which "1"
node-gyp@^5.0.2:
version "5.0.5"
resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-5.0.5.tgz#f6cf1da246eb8c42b097d7cd4d6c3ce23a4163af"
@ -10849,6 +10985,11 @@ node-sass@^4.12.0:
stdout-stream "^1.4.0"
"true-case-path" "^1.0.2"
noop-logger@^0.1.1:
version "0.1.1"
resolved "https://registry.yarnpkg.com/noop-logger/-/noop-logger-0.1.1.tgz#94a2b1633c4f1317553007d8966fd0e841b6a4c2"
integrity sha1-lKKxYzxPExdVMAfYlm/Q6EG2pMI=
"nopt@2 || 3":
version "3.0.6"
resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9"
@ -10986,7 +11127,7 @@ npm-run-path@^3.0.0:
dependencies:
path-key "^3.0.0"
"npmlog@0 || 1 || 2 || 3 || 4", npmlog@^4.0.0, npmlog@^4.0.2, npmlog@^4.1.2:
"npmlog@0 || 1 || 2 || 3 || 4", npmlog@^4.0.0, npmlog@^4.0.1, npmlog@^4.0.2, npmlog@^4.1.2:
version "4.1.2"
resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b"
integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==
@ -12002,6 +12143,27 @@ potpack@^1.0.1:
resolved "https://registry.yarnpkg.com/potpack/-/potpack-1.0.1.tgz#d1b1afd89e4c8f7762865ec30bd112ab767e2ebf"
integrity sha512-15vItUAbViaYrmaB/Pbw7z6qX2xENbFSTA7Ii4tgbPtasxm5v6ryKhKtL91tpWovDJzTiZqdwzhcFBCwiMVdVw==
prebuild-install@^5.1.0:
version "5.3.2"
resolved "https://registry.yarnpkg.com/prebuild-install/-/prebuild-install-5.3.2.tgz#6392e9541ac0b879ef0f22b3d65037417eb2035e"
integrity sha512-INDfXzTPnhT+WYQemqnAXlP7SvfiFMopMozSgXCZ+RDLb279gKfIuLk4o7PgEawLp3WrMgIYGBpkxpraROHsSA==
dependencies:
detect-libc "^1.0.3"
expand-template "^2.0.3"
github-from-package "0.0.0"
minimist "^1.2.0"
mkdirp "^0.5.1"
napi-build-utils "^1.0.1"
node-abi "^2.7.0"
noop-logger "^0.1.1"
npmlog "^4.0.1"
pump "^3.0.0"
rc "^1.2.7"
simple-get "^3.0.3"
tar-fs "^2.0.0"
tunnel-agent "^0.6.0"
which-pm-runs "^1.0.0"
prelude-ls@~1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54"
@ -12761,7 +12923,7 @@ read@1, read@~1.0.1:
string_decoder "~1.1.1"
util-deprecate "~1.0.1"
"readable-stream@2 || 3", readable-stream@^3.0.2, readable-stream@^3.0.6, readable-stream@^3.1.1:
"readable-stream@2 || 3", readable-stream@^3.0.1, readable-stream@^3.0.2, readable-stream@^3.0.6, readable-stream@^3.1.1:
version "3.4.0"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.4.0.tgz#a51c26754658e0a3c21dbf59163bd45ba6f447fc"
integrity sha512-jItXPLmrSR8jmTRmRWJXCnGJsfy85mB3Wd/uINMXA65yrnFo0cPClFIUWzo2najVNSl+mx7/4W8ttlLWJe99pQ==
@ -12770,6 +12932,16 @@ read@1, read@~1.0.1:
string_decoder "^1.1.1"
util-deprecate "^1.0.1"
"readable-stream@>=1.0.33-1 <1.1.0-0":
version "1.0.34"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c"
integrity sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=
dependencies:
core-util-is "~1.0.0"
inherits "~2.0.1"
isarray "0.0.1"
string_decoder "~0.10.x"
readdir-scoped-modules@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/readdir-scoped-modules/-/readdir-scoped-modules-1.1.0.tgz#8d45407b4f870a0dcaebc0e28670d18e74514309"
@ -13100,7 +13272,7 @@ request-promise-native@^1.0.5:
stealthy-require "^1.1.1"
tough-cookie "^2.3.3"
request@^2.87.0, request@^2.88.0:
request@^2.86.0, request@^2.87.0, request@^2.88.0:
version "2.88.0"
resolved "https://registry.yarnpkg.com/request/-/request-2.88.0.tgz#9c2fca4f7d35b592efe57c7f0a55e81052124fef"
integrity sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==
@ -13680,6 +13852,20 @@ signal-exit@^3.0.0, signal-exit@^3.0.2:
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d"
integrity sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=
simple-concat@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/simple-concat/-/simple-concat-1.0.0.tgz#7344cbb8b6e26fb27d66b2fc86f9f6d5997521c6"
integrity sha1-c0TLuLbib7J9ZrL8hvn21Zl1IcY=
simple-get@^3.0.3:
version "3.1.0"
resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-3.1.0.tgz#b45be062435e50d159540b576202ceec40b9c6b3"
integrity sha512-bCR6cP+aTdScaQCnQKbPKtJOKDp/hj9EDLJo3Nw4y1QksqaovlW/bnptB6/c1e+qmNIDHRK+oXFDdEqBT8WzUA==
dependencies:
decompress-response "^4.2.0"
once "^1.3.1"
simple-concat "^1.0.0"
simplebar-react@^1.0.0-alpha.6:
version "1.2.3"
resolved "https://registry.yarnpkg.com/simplebar-react/-/simplebar-react-1.2.3.tgz#bd81fa9827628470e9470d06caef6ece15e1c882"
@ -14173,6 +14359,11 @@ string_decoder@^1.0.0, string_decoder@^1.1.1:
dependencies:
safe-buffer "~5.2.0"
string_decoder@~0.10.x:
version "0.10.31"
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94"
integrity sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=
string_decoder@~1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8"
@ -14511,6 +14702,27 @@ tapable@^2.0.0-beta.8:
resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.0.0-beta.8.tgz#0a8d42f6895d43d5a895de15d9a9e3e425f72a0a"
integrity sha512-7qMajFcHb2O+aWufLoAvKhEehIwikXUTH1s8RP4R5gSYMIB0Tmypp+J90EtSNVbIlI7oB0Oz8ZlpJUJlZ5owxQ==
tar-fs@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-2.0.0.tgz#677700fc0c8b337a78bee3623fdc235f21d7afad"
integrity sha512-vaY0obB6Om/fso8a8vakQBzwholQ7v5+uy+tF3Ozvxv1KNezmVQAiWtcNmMHFSFPqL3dJA8ha6gdtFbfX9mcxA==
dependencies:
chownr "^1.1.1"
mkdirp "^0.5.1"
pump "^3.0.0"
tar-stream "^2.0.0"
tar-stream@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-2.1.0.tgz#d1aaa3661f05b38b5acc9b7020efdca5179a2cc3"
integrity sha512-+DAn4Nb4+gz6WZigRzKEZl1QuJVOLtAwwF+WUxy1fJ6X63CaGaUAxJRD2KEn1OMfcbCjySTYpNC6WmfQoIEOdw==
dependencies:
bl "^3.0.0"
end-of-stream "^1.4.1"
fs-constants "^1.0.0"
inherits "^2.0.3"
readable-stream "^3.1.1"
tar@^2.0.0:
version "2.2.2"
resolved "https://registry.yarnpkg.com/tar/-/tar-2.2.2.tgz#0ca8848562c7299b8b446ff6a4d60cdbb23edc40"
@ -14644,6 +14856,14 @@ throttle-debounce@^2.1.0:
resolved "https://registry.yarnpkg.com/throttle-debounce/-/throttle-debounce-2.1.0.tgz#257e648f0a56bd9e54fe0f132c4ab8611df4e1d5"
integrity sha512-AOvyNahXQuU7NN+VVvOOX+uW6FPaWdAOdRP5HfwYxAfCzXTFKRMoIMk+n+po318+ktcChx+F1Dd91G3YHeMKyg==
through2@^0.6.3:
version "0.6.5"
resolved "https://registry.yarnpkg.com/through2/-/through2-0.6.5.tgz#41ab9c67b29d57209071410e1d7a7a968cd3ad48"
integrity sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=
dependencies:
readable-stream ">=1.0.33-1 <1.1.0-0"
xtend ">=4.0.0 <4.1.0-0"
through2@^2.0.0, through2@^2.0.2:
version "2.0.5"
resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd"
@ -15580,6 +15800,11 @@ which-module@^2.0.0:
resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a"
integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=
which-pm-runs@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/which-pm-runs/-/which-pm-runs-1.0.0.tgz#670b3afbc552e0b55df6b7780ca74615f23ad1cb"
integrity sha1-Zws6+8VS4LVd9rd4DKdGFfI60cs=
which@1, which@^1.2.14, which@^1.2.9, which@^1.3.0, which@^1.3.1:
version "1.3.1"
resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a"
@ -15770,7 +15995,7 @@ xml-name-validator@^3.0.0:
resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a"
integrity sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==
xtend@^4.0.0, xtend@^4.0.1, xtend@~4.0.1:
"xtend@>=4.0.0 <4.1.0-0", xtend@^4.0.0, xtend@^4.0.1, xtend@~4.0.1:
version "4.0.2"
resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54"
integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==