Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

kampos

Package Overview
Dependencies
Maintainers
0
Versions
42
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

kampos - npm Package Compare versions

Comparing version 0.10.0 to 0.10.1

.prettierignore

184

CHANGELOG.md

@@ -0,206 +1,212 @@

### 0.10.1 (2024-08-25)
_Fixed:_
- Export `IKampos` type of the `Kampos` class.
### 0.10.0 (2024-08-20)
*New:*
_New:_
- Added a `dist/index.cjs` distribution.
- Replaced `index.js` with `src/index.js`.
- Added a `dist/index.cjs` distribution.
- Replaced `index.js` with `src/index.js`.
*Fixed:*
_Fixed:_
- Fixed `extends` property of type `Attribute`.
- Fixed `extends` property of type `Attribute`.
*Breaking:*
_Breaking:_
- `main` field in `package.json` now points to `dist/index.cjs`.
- `main` field in `package.json` now points to `dist/index.cjs`.
### 0.9.2 (2024-08-20)
*New:*
_New:_
- Added a `types.d.ts` module.
- Added a `types.d.ts` module.
### 0.9.1 (2024-08-13)
*New:*
_New:_
- Added `kaleidoscope` effect.
- Added `kaleidoscope` effect.
### 0.9.0 (2024-08-13)
*New:*
_New:_
- Added `afterDraw` callback to kampos config. Used to pass a function that will be called after each draw call.
- Added optional function argument `afterDraw` to `kampos#play()` method to be dynamically set to `kampos.config.afterDraw`.
- Added optional boolean argument `skipTextureCreation` to `kampos#setSource()` method to skip texture creation for the source
media. useful for cases where using an OffscreenCanvas as a source for multiple programs and need to switch between them.
- Added `afterDraw` callback to kampos config. Used to pass a function that will be called after each draw call.
- Added optional function argument `afterDraw` to `kampos#play()` method to be dynamically set to `kampos.config.afterDraw`.
- Added optional boolean argument `skipTextureCreation` to `kampos#setSource()` method to skip texture creation for the source
media. useful for cases where using an OffscreenCanvas as a source for multiple programs and need to switch between them.
### 0.8.0 (2023-04-01)
*Breaking:*
_Breaking:_
- `index.js` now uses ES modules. For a UMD distribution please use `index.umd.js`
- `index.js` now uses ES modules. For a UMD distribution please use `index.umd.js`
*Fixed:*
_Fixed:_
- Fixed URLs of docs & demos.
- Rewrote Floss tests to run with Ava.
- Fixed URLs of docs & demos.
- Rewrote Floss tests to run with Ava.
### 0.7.1 (2023-02-13)
*Fixed:*
_Fixed:_
- Ignore test files from NPM that contain invalid characters on Windows systems.
- Ignore test files from NPM that contain invalid characters on Windows systems.
### 0.7.0 (2021-10-16)
*New:*
_New:_
- `transitions.dissolve` now has support for transitioning into a color by disabling the target media with `extureEnabled: false`. `color` argument is used to control the color and defaults to transparent black: `[0, 0, 0, 0]`.
- `transitions.dissolve` now has support for transitioning into a color by disabling the target media with `extureEnabled: false`. `color` argument is used to control the color and defaults to transparent black: `[0, 0, 0, 0]`.
### 0.6.1 (2021-10-14)
*Fixed:*
_Fixed:_
- Fixed dissolve transition to take alpha channel progress from the luminance of the map.
- Fixed dissolve transition to take alpha channel progress from the luminance of the map.
### 0.6.0 (2021-06-29)
*New:*
_New:_
- Added support for simple plane geometry using new `plane: {segments: number | {x: number, y: number}}`config.
- Added `extends: string` property to attribute config which takes a name of an attribute to extend its properties for simplifying coords attribute creation.
- Added support for simple plane geometry using new `plane: {segments: number | {x: number, y: number}}`config.
- Added `extends: string` property to attribute config which takes a name of an attribute to extend its properties for simplifying coords attribute creation.
*Fixed:*
_Fixed:_
- Fixed shader error reporting to correctly report vertex shader errors.
- Fixed shader error reporting to correctly report vertex shader errors.
### 0.5.2 (2021-05-07)
*Fixed:*
_Fixed:_
- Fixed error when called `desotry()` more than once.
- Fixed error when called `desotry()` more than once.
### 0.5.1 (2021-03-26)
*New:*
_New:_
- Added usage of the `OES_vertex_array_object` extension for improved drawing performance.
- Added usage of the `OES_vertex_array_object` extension for improved drawing performance.
### 0.5.0 (2021-03-04)
*New:*
_New:_
- `beforeDraw` callback now takes an argument `time` that will get the timestamp param of rAF injected into it.
- All effects and transitions now take `params` argument, an `Object` that contains initial values to set.
- `turbulence` effect now takes a new argument `params.output` which results in a code injected to the fragment shader for controlling the output of the effect. You can use the static properties of the effect:
- `turbulence.COLOR`: render the result value as a grayscale vector into `color`.
- `turbulence.ALPHA`: render the result value into `alpha`.
- `beforeDraw` callback now takes an argument `time` that will get the timestamp param of rAF injected into it.
- All effects and transitions now take `params` argument, an `Object` that contains initial values to set.
- `turbulence` effect now takes a new argument `params.output` which results in a code injected to the fragment shader for controlling the output of the effect. You can use the static properties of the effect:
- `turbulence.COLOR`: render the result value as a grayscale vector into `color`.
- `turbulence.ALPHA`: render the result value into `alpha`.
*Breaking:*
_Breaking:_
- `blend` effect now takes `noise` as a property of `params` object.
- `displacement` effect now takes `wrap` as a property of `params` object, which are now static properties of the effect:
- `displacement.CLAMP`
- `displacement.DISCARD`
- `displacement.WRAP`
- `tubulence` effect now takes the noise string argument as a property of `params`, as in: `params.noise`.
- `blend` effect now takes `noise` as a property of `params` object.
- `displacement` effect now takes `wrap` as a property of `params` object, which are now static properties of the effect:
- `displacement.CLAMP`
- `displacement.DISCARD`
- `displacement.WRAP`
- `tubulence` effect now takes the noise string argument as a property of `params`, as in: `params.noise`.
### 0.4.0 (2021-02-08)
*New:*
_New:_
- Dissolve transition.
- Dissolve transition.
### 0.3.7 (2021-02-07)
*New:*
_New:_
- Added cellular noise.
- `brightnessContrast` and `hueSaturation` effects now have initial default values in factory.
- Added cellular noise.
- `brightnessContrast` and `hueSaturation` effects now have initial default values in factory.
### 0.3.6 (2021-01-13)
*New:*
_New:_
- Initial work on `blend` effect.
- Initial work on `blend` effect.
*Fixed:*
_Fixed:_
- Fixed Travis build.
- Fixed Travis build.
### 0.3.5 (2019-11-09)
*Fixed:*
_Fixed:_
- Fixed noise rendering on mobile with changing `percision` to `highp`.
- Fixed noise rendering on mobile with changing `percision` to `highp`.
### 0.3.4 (2019-10-22)
*New:*
_New:_
- Added wrapping methods for `displacement` effect: `CLAMP`, `DISCARD`, `WRAP`.
- Added wrapping methods for `displacement` effect: `CLAMP`, `DISCARD`, `WRAP`.
*Fixed:*
_Fixed:_
- Fixed usage of `sourceCoords` in `displacement` transition.
- Fixed usage of `sourceCoords` in `displacement` transition.
### 0.3.3 (2019-10-20)
*New:*
_New:_
- Added simplex 3D noise.
- Added simplex 3D noise.
### 0.3.2 (2019-09-28)
*Fixed:*
_Fixed:_
- Fixed handling `noSource` and multiple textures in draw loop.
- Fixed handling `noSource` and multiple textures in draw loop.
### 0.3.1 (2019-09-25)
*Fixed:*
_Fixed:_
- Updated docs & README.
- Updated docs & README.
### 0.3.0 (2019-09-24)
*New:*
_New:_
- Added suport for `noSource` argument for rendering without a media source.
- Implemented `turbulence` effect.
- `alphaMask` effect now supports luminance mode via `isLuminance` getter/setter.
- Added `beforeDraw` callback to kampos config.
- Added perlin 3D noise.
- Added suport for `noSource` argument for rendering without a media source.
- Implemented `turbulence` effect.
- `alphaMask` effect now supports luminance mode via `isLuminance` getter/setter.
- Added `beforeDraw` callback to kampos config.
- Added perlin 3D noise.
*Fixed:*
_Fixed:_
- CI build fixes.
- CI build fixes.
### 0.2.3 (2019-08-22)
*Fixed:*
_Fixed:_
- Docs fixes.
- Integrate with Travis CI.
- Docs fixes.
- Integrate with Travis CI.
### 0.2.2 (2019-08-07)
*Fixed:*
_Fixed:_
- Added missing `progress` getter/setter for `fade` transition.
- Added missing `progress` getter/setter for `fade` transition.
### 0.2.1 (2019-08-07)
*Fixed:*
_Fixed:_
- kampos is not dependent on `Ticker`.
- kampos is not dependent on `Ticker`.
*New:*
_New:_
- Published transpiled source.
- Published transpiled source.
### 0.2.0 (2019-07-25)
*New:*
_New:_
- Initial public release.
- Initial public release.

@@ -11,6 +11,6 @@ import { Kampos, effects, noise } from '../index.js';

u_resolution: 'vec2',
u_time: 'float'
u_time: 'float',
},
constant: noise.cellular,
main: 'color = vec3(noise(vec3(gl_FragCoord.xy/u_resolution.xy, u_time * 0.0005)));'
main: 'color = vec3(noise(vec3(gl_FragCoord.xy/u_resolution.xy, u_time * 0.0005)));',
},

@@ -21,3 +21,3 @@ uniforms: [

type: 'f',
data: [1.0]
data: [1.0],
},

@@ -27,4 +27,4 @@ {

type: 'f',
data: [854 / 10, 480 / 10]
}
data: [854 / 10, 480 / 10],
},
],

@@ -36,3 +36,3 @@ get time() {

this.uniforms[0].data[0] = t;
}
},
};

@@ -45,4 +45,2 @@

// you can increase/decrease the time factor for a faster/slower animation
instance.play(
() => render.time = (Date.now() - start) * 2
);
instance.play(() => (render.time = (Date.now() - start) * 2));

@@ -1,6 +0,6 @@

function updatePreview (iframe, example, videos) {
iframe.setAttribute('srcdoc', getIFrameHTML({example, videos}))
function updatePreview(iframe, example, videos) {
iframe.setAttribute('srcdoc', getIFrameHTML({ example, videos }));
}
function getIFrameHTML ({example, videos}) {
function getIFrameHTML({ example, videos }) {
return `<!DOCTYPE html>

@@ -30,3 +30,3 @@ <html>

function insertSection (id) {
function insertSection(id) {
const section = document.querySelector(`#${id}`);

@@ -40,14 +40,12 @@ const main = document.querySelector('main');

document.querySelector('nav')
.addEventListener('click', e => {
const id = e.target.dataset.sectionId;
insertSection(id);
});
document.querySelector('nav').addEventListener('click', (e) => {
const id = e.target.dataset.sectionId;
insertSection(id);
});
document.querySelector('#open-code')
.addEventListener('click', () => {
document.querySelector('#section-wrapper').classList.toggle('open');
});
document.querySelector('#open-code').addEventListener('click', () => {
document.querySelector('#section-wrapper').classList.toggle('open');
});
function startDemo (script, ids) {
function startDemo(script, ids) {
const code = document.querySelector(`#${ids.code}`);

@@ -59,4 +57,4 @@ const preview = document.querySelector(`#${ids.preview}`);

fetch(script)
.then(resp => resp.text())
.then(text => {
.then((resp) => resp.text())
.then((text) => {
code.value = text;

@@ -66,6 +64,11 @@ const doc = CodeMirror.fromTextArea(code, {

lineNumbers: true,
theme: 'dracula'
theme: 'dracula',
});
const update = () => updatePreview(preview, doc.getValue(), video ? video.innerHTML : '');
const update = () =>
updatePreview(
preview,
doc.getValue(),
video ? video.innerHTML : ''
);

@@ -79,3 +82,3 @@ refresh.addEventListener('click', update);

const sectionScripts = {
section1 () {
section1() {
startDemo('./turbulence.js', {

@@ -85,7 +88,7 @@ code: 'code1',

video: 'videos1',
refresh: 'refresh1'
refresh: 'refresh1',
});
},
section2 () {
section2() {
startDemo('./hue-fade.js', {

@@ -95,7 +98,7 @@ code: 'code2',

video: 'videos2',
refresh: 'refresh2'
refresh: 'refresh2',
});
},
section3 () {
section3() {
startDemo('./disp.js', {

@@ -105,7 +108,7 @@ code: 'code3',

video: 'videos3',
refresh: 'refresh3'
refresh: 'refresh3',
});
},
section4 () {
section4() {
startDemo('./duotone.js', {

@@ -115,11 +118,11 @@ code: 'code4',

video: 'videos4',
refresh: 'refresh4'
refresh: 'refresh4',
});
},
section5 () {
section5() {
startDemo('./cellular-noise.js', {
code: 'code5',
preview: 'preview',
refresh: 'refresh5'
refresh: 'refresh5',
});

@@ -133,3 +136,3 @@ },

video: 'videos2',
refresh: 'refresh6'
refresh: 'refresh6',
});

@@ -143,3 +146,3 @@ },

video: 'none',
refresh: 'refresh7'
refresh: 'refresh7',
});

@@ -153,7 +156,26 @@ },

video: 'videos5',
refresh: 'refresh8'
refresh: 'refresh8',
});
},
section9() {
startDemo('./alpha-mask.js', {
code: 'code9',
preview: 'preview',
video: 'videos2',
refresh: 'refresh9',
});
},
};
insertSection('section7');
// on load get active section from url hash and set
const hash = window.location.hash.substring(1);
if (hash) {
const section = document.querySelector(`#${hash}`);
if (section) {
insertSection(hash);
}
}
insertSection('section7');

@@ -9,3 +9,3 @@ import { Kampos, transitions } from '../index.js';

class Transition {
constructor ({vid1, vid2, target, disp, dispScale}) {
constructor({ vid1, vid2, target, disp, dispScale }) {
/*

@@ -24,3 +24,3 @@ * prepare here everything we need

// init kampos
this.kampos = new Kampos({target, effects: [this.transition]});
this.kampos = new Kampos({ target, effects: [this.transition] });

@@ -31,25 +31,25 @@ // load the displacement map image

// make sure videos are loaded and playing
prepareVideos([this.vid1, this.vid2])
.then(() => {
const height = window.document.documentElement.clientHeight;
const width = height * this.vid1.videoWidth / this.vid1.videoHeight;
prepareVideos([this.vid1, this.vid2]).then(() => {
const height = window.document.documentElement.clientHeight;
const width =
(height * this.vid1.videoWidth) / this.vid1.videoHeight;
dispReady.then(img => {
/*
* set transition values
*/
this.transition.map = img;
this.transition.to = this.vid2;
dispReady.then((img) => {
/*
* set transition values
*/
this.transition.map = img;
this.transition.to = this.vid2;
// try playing with the x/y and +/- for different transition effects
this.transition.sourceScale = {x: this.dispScale};
this.transition.toScale = {x: -this.dispScale};
// try playing with the x/y and +/- for different transition effects
this.transition.sourceScale = { x: this.dispScale };
this.transition.toScale = { x: -this.dispScale };
// set media source
this.kampos.setSource({media: this.vid1, width, height});
// set media source
this.kampos.setSource({ media: this.vid1, width, height });
// start kampos
this.kampos.play();
});
// start kampos
this.kampos.play();
});
});
}

@@ -60,3 +60,3 @@

*/
forward () {
forward() {
this.direction = 1;

@@ -70,3 +70,3 @@ this.startTime = Date.now();

*/
backward () {
backward() {
this.direction = 0;

@@ -80,3 +80,3 @@ this.startTime = Date.now();

*/
tick (p) {
tick(p) {
this.transition.progress = p;

@@ -88,3 +88,3 @@ }

*/
loop () {
loop() {
const now = Date.now() - this.startTime;

@@ -108,4 +108,3 @@ // dividing by 500 is just enough to slow down the effect

}
}
else if (p * 100 <= 1) {
} else if (p * 100 <= 1) {
nextTick = () => this.tick(0);

@@ -132,3 +131,3 @@ }

// change this value and refresh to see how it affects the transition
dispScale: 1.0
dispScale: 1.0,
});

@@ -135,0 +134,0 @@

@@ -19,3 +19,3 @@ import { Kampos, effects, noise, transitions } from '../index.js';

edge: 0.4,
cellFactor: 4
cellFactor: 4,
},

@@ -25,5 +25,5 @@ LIQUID: {

edge: 0.03,
cellFactor: 2
}
}
cellFactor: 2,
},
};

@@ -35,3 +35,3 @@ mapTarget.width = MAP_WIDTH;

const AMPLITUDE = ANIMATIONS[TYPE].cellFactor / MAP_WIDTH;
const frequency = {x: AMPLITUDE, y: AMPLITUDE};
const frequency = { x: AMPLITUDE, y: AMPLITUDE };

@@ -48,6 +48,10 @@ /* increase number on range (1, 8) to go from water-like effect into clouds-like one */

frequency,
isFractal
isFractal,
});
const dissolveMap = new Kampos({ target: mapTarget, effects: [turbulence], noSource: true });
const dissolveMap = new Kampos({
target: mapTarget,
effects: [turbulence],
noSource: true,
});

@@ -65,3 +69,3 @@ /* create the dissolve map by generating a single noise frame */

/* init kampos */
const instance = new Kampos({target, effects:[dissolve]});
const instance = new Kampos({ target, effects: [dissolve] });

@@ -73,94 +77,93 @@ /* make sure videos are loaded and playing*/

loadImage(`https://picsum.photos/${MAP_WIDTH}/${MAP_HEIGHT}?random=3`),
loadImage(`https://picsum.photos/${MAP_WIDTH}/${MAP_HEIGHT}?random=4`)
])
.then((images) => {
const width = MAP_WIDTH;
const height = MAP_HEIGHT;
let index = 0;
loadImage(`https://picsum.photos/${MAP_WIDTH}/${MAP_HEIGHT}?random=4`),
]).then((images) => {
const width = MAP_WIDTH;
const height = MAP_HEIGHT;
let index = 0;
if (DYNAMIC) {
dissolve.textures[1].update = true;
}
if (DYNAMIC) {
dissolve.textures[1].update = true;
}
/* paint initial scene */
instance.setSource({media: images[0], width, height});
dissolve.to = images[1];
instance.draw();
/* paint initial scene */
instance.setSource({ media: images[0], width, height });
dissolve.to = images[1];
instance.draw();
function easeOutCubic(x) {
return 1 - Math.pow(1 - x, 3);
}
function easeOutCubic(x) {
return 1 - Math.pow(1 - x, 3);
}
function changeImage(prevImage, nextImage) {
/* set media source */
instance.setSource({media: prevImage, width, height});
function changeImage(prevImage, nextImage) {
/* set media source */
instance.setSource({ media: prevImage, width, height });
/* set media to transition into */
dissolve.to = nextImage;
/* set media to transition into */
dissolve.to = nextImage;
const start = performance.now();
const start = performance.now();
/* start kampos */
instance.play(function draw () {
const time = performance.now() - start;
/* start kampos */
instance.play(function draw() {
const time = performance.now() - start;
/* this is invoked once in every animation frame */
if (DYNAMIC) {
turbulence.time = time * 2;
dissolveMap.draw();
}
/* this is invoked once in every animation frame */
if (DYNAMIC) {
turbulence.time = time * 2;
dissolveMap.draw();
}
/* you can reduce time factor for slower transition, or increase for faster */
const progress = easeOutCubic(time * (DYNAMIC ? 2e-4 : 4e-4));
dissolve.progress = progress;
/* you can reduce time factor for slower transition, or increase for faster */
const progress = easeOutCubic(time * (DYNAMIC ? 2e-4 : 4e-4));
dissolve.progress = progress;
if (progress * 100 >= 99.9) {
instance.stop();
if (progress * 100 >= 99.9) {
instance.stop();
// bind the event again
bindClick();
}
});
}
// bind the event again
bindClick();
}
});
}
function next() {
const from = images[index];
function next() {
const from = images[index];
// next...
index = (index + 1) % images.length;
// next...
index = (index + 1) % images.length;
const to = images[index];
const to = images[index];
changeImage(from, to);
}
changeImage(from, to);
}
function prev() {
const from = images[index];
function prev() {
const from = images[index];
// prev...
index = (index - 1 + images.length) % images.length;
// prev...
index = (index - 1 + images.length) % images.length;
const to = images[index];
const to = images[index];
changeImage(from, to);
}
changeImage(from, to);
}
function click(event) {
const {offsetX} = event;
function click(event) {
const { offsetX } = event;
target.classList.remove('clickable');
target.classList.remove('clickable');
if (offsetX > width / 2) {
next();
} else {
prev();
}
if (offsetX > width / 2) {
next();
} else {
prev();
}
}
function bindClick() {
target.classList.add('clickable');
target.addEventListener('click', click, {once: true});
}
function bindClick() {
target.classList.add('clickable');
target.addEventListener('click', click, { once: true });
}
bindClick();
});
bindClick();
});

@@ -21,3 +21,3 @@ import { Kampos, effects, noise, transitions } from '../index.js';

edge: 0.4,
cellFactor: 4
cellFactor: 4,
},

@@ -27,5 +27,5 @@ LIQUID: {

edge: 0.03,
cellFactor: 2
}
}
cellFactor: 2,
},
};

@@ -37,3 +37,3 @@ mapTarget.width = MAP_WIDTH;

const AMPLITUDE = ANIMATIONS[TYPE].cellFactor / MAP_WIDTH;
const frequency = {x: AMPLITUDE, y: AMPLITUDE};
const frequency = { x: AMPLITUDE, y: AMPLITUDE };

@@ -50,6 +50,10 @@ /* increase number on range (1, 8) to go from water-like effect into clouds-like one */

frequency,
isFractal
isFractal,
});
const dissolveMap = new Kampos({ target: mapTarget, effects: [turbulence], noSource: true });
const dissolveMap = new Kampos({
target: mapTarget,
effects: [turbulence],
noSource: true,
});

@@ -67,29 +71,28 @@ /* create the dissolve map by generating a single noise frame */

/* init kampos */
const instance = new Kampos({target, effects:[dissolve]});
const instance = new Kampos({ target, effects: [dissolve] });
/* make sure videos are loaded and playing */
prepareVideos([media1, media2])
.then(() => {
const width = media1.videoWidth;
const height = media1.videoHeight;
prepareVideos([media1, media2]).then(() => {
const width = media1.videoWidth;
const height = media1.videoHeight;
/* set media source */
instance.setSource({media: media1, width, height});
/* set media source */
instance.setSource({ media: media1, width, height });
/* set media to transition into*/
dissolve.to = media2;
/* set media to transition into*/
dissolve.to = media2;
if (DYNAMIC) {
dissolve.textures[1].update = true;
}
/* start kampos */
instance.play(function draw(time) {
/* this is invoked once in every animation frame, while the mouse over the canvas */
if (DYNAMIC) {
dissolve.textures[1].update = true;
turbulence.time = time * 2;
dissolveMap.draw();
}
/* start kampos */
instance.play(function draw (time) {
/* this is invoked once in every animation frame, while the mouse over the canvas */
if (DYNAMIC) {
turbulence.time = time * 2;
dissolveMap.draw();
}
/* you can reduce time factor for slower transition, or increase for faster */
dissolve.progress = Math.abs(Math.sin(time * (DYNAMIC ? 2e-4 : 4e-4)));
});
/* you can reduce time factor for slower transition, or increase for faster */
dissolve.progress = Math.abs(Math.sin(time * (DYNAMIC ? 2e-4 : 4e-4)));
});
});

@@ -11,30 +11,31 @@ import { Kampos, effects } from '../index.js';

// init kampos with effect
const instance = new Kampos({target, effects:[duotone, hueSaturation]});
const instance = new Kampos({ target, effects: [duotone, hueSaturation] });
// prepareVideos([media])
loadImage('https://static.wixstatic.com/media/cec2b6_36e46176b7e54b678e4c6d39d36452e5~mv2.jpg')
.then((img) => {
// const width = media.videoWidth;
// const height = media.videoHeight;
const height = window.document.documentElement.clientHeight;
const width = height * img.naturalWidth / img.naturalHeight;
loadImage(
'https://static.wixstatic.com/media/cec2b6_36e46176b7e54b678e4c6d39d36452e5~mv2.jpg',
).then((img) => {
// const width = media.videoWidth;
// const height = media.videoHeight;
const height = window.document.documentElement.clientHeight;
const width = (height * img.naturalWidth) / img.naturalHeight;
// set media source
instance.setSource({media: img, width, height});
// set media source
instance.setSource({ media: img, width, height });
// start kampos
instance.play((time) => {
hueSaturation.hue = Math.sin(time / 2e3) * 360;
});
// start kampos
instance.play((time) => {
hueSaturation.hue = Math.sin(time / 2e3) * 360;
});
// add mouse events to disable/enable the effect
target.addEventListener('mouseenter', () => {
duotone.disabled = true;
hueSaturation.hueDisabled = true;
});
// add mouse events to disable/enable the effect
target.addEventListener('mouseenter', () => {
duotone.disabled = true;
hueSaturation.hueDisabled = true;
});
target.addEventListener('mouseleave', () => {
duotone.disabled = false;
hueSaturation.hueDisabled = false;
});
target.addEventListener('mouseleave', () => {
duotone.disabled = false;
hueSaturation.hueDisabled = false;
});
});

@@ -12,19 +12,18 @@ import { Kampos, transitions } from '../index.js';

// init kampos
const instance = new Kampos({target, effects:[fade]});
const instance = new Kampos({ target, effects: [fade] });
// make sure videos are loaded and playing
prepareVideos([media1, media2])
.then(() => {
const width = media1.videoWidth;
const height = media1.videoHeight;
prepareVideos([media1, media2]).then(() => {
const width = media1.videoWidth;
const height = media1.videoHeight;
// set media source
instance.setSource({media: media1, width, height});
// set media source
instance.setSource({ media: media1, width, height });
// set media to transition into
fade.to = media2;
// set media to transition into
fade.to = media2;
// start kampos
instance.play();
});
// start kampos
instance.play();
});

@@ -35,3 +34,3 @@ let x, y, rect;

// this is invoked once in every animation frame, while there's a mouse move over the canvas
function tick () {
function tick() {
fade.progress = Math.max(0, Math.min(1, (x - rect.x) / rect.width));

@@ -43,4 +42,4 @@ // hueSat.hue = Math.max(0, Math.min(1, (x - rect.x) / rect.width)) * 360 - 180;

// handler for detecting mouse move
const moveHandler = e => {
const {clientX} = e;
const moveHandler = (e) => {
const { clientX } = e;

@@ -47,0 +46,0 @@ // cache mouse location

(function () {
'use strict';
function updatePreview (iframe, example, videos) {
iframe.setAttribute('srcdoc', getIFrameHTML({example, videos}));
function updatePreview(iframe, example, videos) {
iframe.setAttribute('srcdoc', getIFrameHTML({ example, videos }));
}
function getIFrameHTML ({example, videos}) {
function getIFrameHTML({ example, videos }) {
return `<!DOCTYPE html>

@@ -33,3 +33,3 @@ <html>

function insertSection (id) {
function insertSection(id) {
const section = document.querySelector(`#${id}`);

@@ -43,14 +43,12 @@ const main = document.querySelector('main');

document.querySelector('nav')
.addEventListener('click', e => {
const id = e.target.dataset.sectionId;
insertSection(id);
});
document.querySelector('nav').addEventListener('click', (e) => {
const id = e.target.dataset.sectionId;
insertSection(id);
});
document.querySelector('#open-code')
.addEventListener('click', () => {
document.querySelector('#section-wrapper').classList.toggle('open');
});
document.querySelector('#open-code').addEventListener('click', () => {
document.querySelector('#section-wrapper').classList.toggle('open');
});
function startDemo (script, ids) {
function startDemo(script, ids) {
const code = document.querySelector(`#${ids.code}`);

@@ -62,4 +60,4 @@ const preview = document.querySelector(`#${ids.preview}`);

fetch(script)
.then(resp => resp.text())
.then(text => {
.then((resp) => resp.text())
.then((text) => {
code.value = text;

@@ -69,6 +67,11 @@ const doc = CodeMirror.fromTextArea(code, {

lineNumbers: true,
theme: 'dracula'
theme: 'dracula',
});
const update = () => updatePreview(preview, doc.getValue(), video ? video.innerHTML : '');
const update = () =>
updatePreview(
preview,
doc.getValue(),
video ? video.innerHTML : ''
);

@@ -82,3 +85,3 @@ refresh.addEventListener('click', update);

const sectionScripts = {
section1 () {
section1() {
startDemo('./turbulence.js', {

@@ -88,7 +91,7 @@ code: 'code1',

video: 'videos1',
refresh: 'refresh1'
refresh: 'refresh1',
});
},
section2 () {
section2() {
startDemo('./hue-fade.js', {

@@ -98,7 +101,7 @@ code: 'code2',

video: 'videos2',
refresh: 'refresh2'
refresh: 'refresh2',
});
},
section3 () {
section3() {
startDemo('./disp.js', {

@@ -108,7 +111,7 @@ code: 'code3',

video: 'videos3',
refresh: 'refresh3'
refresh: 'refresh3',
});
},
section4 () {
section4() {
startDemo('./duotone.js', {

@@ -118,11 +121,11 @@ code: 'code4',

video: 'videos4',
refresh: 'refresh4'
refresh: 'refresh4',
});
},
section5 () {
section5() {
startDemo('./cellular-noise.js', {
code: 'code5',
preview: 'preview',
refresh: 'refresh5'
refresh: 'refresh5',
});

@@ -136,3 +139,3 @@ },

video: 'videos2',
refresh: 'refresh6'
refresh: 'refresh6',
});

@@ -146,3 +149,3 @@ },

video: 'none',
refresh: 'refresh7'
refresh: 'refresh7',
});

@@ -156,5 +159,14 @@ },

video: 'videos5',
refresh: 'refresh8'
refresh: 'refresh8',
});
}
},
section9() {
startDemo('./alpha-mask.js', {
code: 'code9',
preview: 'preview',
video: 'videos2',
refresh: 'refresh9',
});
},
};

@@ -164,2 +176,12 @@

// on load get active section from url hash and set
const hash = window.location.hash.substring(1);
if (hash) {
const section = document.querySelector(`#${hash}`);
if (section) {
insertSection(hash);
}
}
})();

@@ -8,19 +8,18 @@ import { Kampos, effects } from '../index.js';

const instance = new Kampos({effects: [kaleidoscope], target})
const instance = new Kampos({ effects: [kaleidoscope], target });
/* make sure video is loaded and playing */
prepareVideos([media])
.then(() => {
const width = media.videoWidth;
const height = media.videoHeight;
prepareVideos([media]).then(() => {
const width = media.videoWidth;
const height = media.videoHeight;
/* set media source */
instance.setSource({media, width, height});
/* set media source */
instance.setSource({ media, width, height });
instance.play();
instance.play();
target.addEventListener('pointermove', (e) => {
const { offsetX, offsetY } = e;
kaleidoscope.offset = offsetX / width - 0.5;
});
target.addEventListener('pointermove', (e) => {
const { offsetX, offsetY } = e;
kaleidoscope.offset = offsetX / width - 0.5;
});
});
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: https://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror"], mod);
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
"use strict";
(function (mod) {
if (typeof exports == 'object' && typeof module == 'object')
// CommonJS
mod(require('../../lib/codemirror'));
else if (typeof define == 'function' && define.amd)
// AMD
define(['../../lib/codemirror'], mod);
// Plain browser env
else mod(CodeMirror);
})(function (CodeMirror) {
'use strict';
CodeMirror.defineMode("javascript", function(config, parserConfig) {
var indentUnit = config.indentUnit;
var statementIndent = parserConfig.statementIndent;
var jsonldMode = parserConfig.jsonld;
var jsonMode = parserConfig.json || jsonldMode;
var isTS = parserConfig.typescript;
var wordRE = parserConfig.wordCharacters || /[\w$\xa1-\uffff]/;
CodeMirror.defineMode('javascript', function (config, parserConfig) {
var indentUnit = config.indentUnit;
var statementIndent = parserConfig.statementIndent;
var jsonldMode = parserConfig.jsonld;
var jsonMode = parserConfig.json || jsonldMode;
var isTS = parserConfig.typescript;
var wordRE = parserConfig.wordCharacters || /[\w$\xa1-\uffff]/;
// Tokenizer
// Tokenizer
var keywords = function(){
function kw(type) {return {type: type, style: "keyword"};}
var A = kw("keyword a"), B = kw("keyword b"), C = kw("keyword c"), D = kw("keyword d");
var operator = kw("operator"), atom = {type: "atom", style: "atom"};
var keywords = (function () {
function kw(type) {
return { type: type, style: 'keyword' };
}
var A = kw('keyword a'),
B = kw('keyword b'),
C = kw('keyword c'),
D = kw('keyword d');
var operator = kw('operator'),
atom = { type: 'atom', style: 'atom' };
return {
"if": kw("if"), "while": A, "with": A, "else": B, "do": B, "try": B, "finally": B,
"return": D, "break": D, "continue": D, "new": kw("new"), "delete": C, "void": C, "throw": C,
"debugger": kw("debugger"), "var": kw("var"), "const": kw("var"), "let": kw("var"),
"function": kw("function"), "catch": kw("catch"),
"for": kw("for"), "switch": kw("switch"), "case": kw("case"), "default": kw("default"),
"in": operator, "typeof": operator, "instanceof": operator,
"true": atom, "false": atom, "null": atom, "undefined": atom, "NaN": atom, "Infinity": atom,
"this": kw("this"), "class": kw("class"), "super": kw("atom"),
"yield": C, "export": kw("export"), "import": kw("import"), "extends": C,
"await": C
};
}();
return {
if: kw('if'),
while: A,
with: A,
else: B,
do: B,
try: B,
finally: B,
return: D,
break: D,
continue: D,
new: kw('new'),
delete: C,
void: C,
throw: C,
debugger: kw('debugger'),
var: kw('var'),
const: kw('var'),
let: kw('var'),
function: kw('function'),
catch: kw('catch'),
for: kw('for'),
switch: kw('switch'),
case: kw('case'),
default: kw('default'),
in: operator,
typeof: operator,
instanceof: operator,
true: atom,
false: atom,
null: atom,
undefined: atom,
NaN: atom,
Infinity: atom,
this: kw('this'),
class: kw('class'),
super: kw('atom'),
yield: C,
export: kw('export'),
import: kw('import'),
extends: C,
await: C,
};
})();
var isOperatorChar = /[+\-*&%=<>!?|~^@]/;
var isJsonldKeyword = /^@(context|id|value|language|type|container|list|set|reverse|index|base|vocab|graph)"/;
var isOperatorChar = /[+\-*&%=<>!?|~^@]/;
var isJsonldKeyword =
/^@(context|id|value|language|type|container|list|set|reverse|index|base|vocab|graph)"/;
function readRegexp(stream) {
var escaped = false, next, inSet = false;
while ((next = stream.next()) != null) {
if (!escaped) {
if (next == "/" && !inSet) return;
if (next == "[") inSet = true;
else if (inSet && next == "]") inSet = false;
}
escaped = !escaped && next == "\\";
}
}
function readRegexp(stream) {
var escaped = false,
next,
inSet = false;
while ((next = stream.next()) != null) {
if (!escaped) {
if (next == '/' && !inSet) return;
if (next == '[') inSet = true;
else if (inSet && next == ']') inSet = false;
}
escaped = !escaped && next == '\\';
}
}
// Used as scratch variables to communicate multiple values without
// consing up tons of objects.
var type, content;
function ret(tp, style, cont) {
type = tp; content = cont;
return style;
}
function tokenBase(stream, state) {
var ch = stream.next();
if (ch == '"' || ch == "'") {
state.tokenize = tokenString(ch);
return state.tokenize(stream, state);
} else if (ch == "." && stream.match(/^\d[\d_]*(?:[eE][+\-]?[\d_]+)?/)) {
return ret("number", "number");
} else if (ch == "." && stream.match("..")) {
return ret("spread", "meta");
} else if (/[\[\]{}\(\),;\:\.]/.test(ch)) {
return ret(ch);
} else if (ch == "=" && stream.eat(">")) {
return ret("=>", "operator");
} else if (ch == "0" && stream.match(/^(?:x[\dA-Fa-f_]+|o[0-7_]+|b[01_]+)n?/)) {
return ret("number", "number");
} else if (/\d/.test(ch)) {
stream.match(/^[\d_]*(?:n|(?:\.[\d_]*)?(?:[eE][+\-]?[\d_]+)?)?/);
return ret("number", "number");
} else if (ch == "/") {
if (stream.eat("*")) {
state.tokenize = tokenComment;
return tokenComment(stream, state);
} else if (stream.eat("/")) {
stream.skipToEnd();
return ret("comment", "comment");
} else if (expressionAllowed(stream, state, 1)) {
readRegexp(stream);
stream.match(/^\b(([gimyus])(?![gimyus]*\2))+\b/);
return ret("regexp", "string-2");
} else {
stream.eat("=");
return ret("operator", "operator", stream.current());
}
} else if (ch == "`") {
state.tokenize = tokenQuasi;
return tokenQuasi(stream, state);
} else if (ch == "#") {
stream.skipToEnd();
return ret("error", "error");
} else if (isOperatorChar.test(ch)) {
if (ch != ">" || !state.lexical || state.lexical.type != ">") {
if (stream.eat("=")) {
if (ch == "!" || ch == "=") stream.eat("=")
} else if (/[<>*+\-]/.test(ch)) {
stream.eat(ch)
if (ch == ">") stream.eat(ch)
// Used as scratch variables to communicate multiple values without
// consing up tons of objects.
var type, content;
function ret(tp, style, cont) {
type = tp;
content = cont;
return style;
}
}
return ret("operator", "operator", stream.current());
} else if (wordRE.test(ch)) {
stream.eatWhile(wordRE);
var word = stream.current()
if (state.lastType != ".") {
if (keywords.propertyIsEnumerable(word)) {
var kw = keywords[word]
return ret(kw.type, kw.style, word)
function tokenBase(stream, state) {
var ch = stream.next();
if (ch == '"' || ch == "'") {
state.tokenize = tokenString(ch);
return state.tokenize(stream, state);
} else if (
ch == '.' &&
stream.match(/^\d[\d_]*(?:[eE][+\-]?[\d_]+)?/)
) {
return ret('number', 'number');
} else if (ch == '.' && stream.match('..')) {
return ret('spread', 'meta');
} else if (/[\[\]{}\(\),;\:\.]/.test(ch)) {
return ret(ch);
} else if (ch == '=' && stream.eat('>')) {
return ret('=>', 'operator');
} else if (
ch == '0' &&
stream.match(/^(?:x[\dA-Fa-f_]+|o[0-7_]+|b[01_]+)n?/)
) {
return ret('number', 'number');
} else if (/\d/.test(ch)) {
stream.match(
/^[\d_]*(?:n|(?:\.[\d_]*)?(?:[eE][+\-]?[\d_]+)?)?/,
);
return ret('number', 'number');
} else if (ch == '/') {
if (stream.eat('*')) {
state.tokenize = tokenComment;
return tokenComment(stream, state);
} else if (stream.eat('/')) {
stream.skipToEnd();
return ret('comment', 'comment');
} else if (expressionAllowed(stream, state, 1)) {
readRegexp(stream);
stream.match(/^\b(([gimyus])(?![gimyus]*\2))+\b/);
return ret('regexp', 'string-2');
} else {
stream.eat('=');
return ret('operator', 'operator', stream.current());
}
} else if (ch == '`') {
state.tokenize = tokenQuasi;
return tokenQuasi(stream, state);
} else if (ch == '#') {
stream.skipToEnd();
return ret('error', 'error');
} else if (isOperatorChar.test(ch)) {
if (ch != '>' || !state.lexical || state.lexical.type != '>') {
if (stream.eat('=')) {
if (ch == '!' || ch == '=') stream.eat('=');
} else if (/[<>*+\-]/.test(ch)) {
stream.eat(ch);
if (ch == '>') stream.eat(ch);
}
}
return ret('operator', 'operator', stream.current());
} else if (wordRE.test(ch)) {
stream.eatWhile(wordRE);
var word = stream.current();
if (state.lastType != '.') {
if (keywords.propertyIsEnumerable(word)) {
var kw = keywords[word];
return ret(kw.type, kw.style, word);
}
if (
word == 'async' &&
stream.match(/^(\s|\/\*.*?\*\/)*[\[\(\w]/, false)
)
return ret('async', 'keyword', word);
}
return ret('variable', 'variable', word);
}
}
if (word == "async" && stream.match(/^(\s|\/\*.*?\*\/)*[\[\(\w]/, false))
return ret("async", "keyword", word)
}
return ret("variable", "variable", word)
}
}
function tokenString(quote) {
return function(stream, state) {
var escaped = false, next;
if (jsonldMode && stream.peek() == "@" && stream.match(isJsonldKeyword)){
state.tokenize = tokenBase;
return ret("jsonld-keyword", "meta");
}
while ((next = stream.next()) != null) {
if (next == quote && !escaped) break;
escaped = !escaped && next == "\\";
}
if (!escaped) state.tokenize = tokenBase;
return ret("string", "string");
};
}
function tokenString(quote) {
return function (stream, state) {
var escaped = false,
next;
if (
jsonldMode &&
stream.peek() == '@' &&
stream.match(isJsonldKeyword)
) {
state.tokenize = tokenBase;
return ret('jsonld-keyword', 'meta');
}
while ((next = stream.next()) != null) {
if (next == quote && !escaped) break;
escaped = !escaped && next == '\\';
}
if (!escaped) state.tokenize = tokenBase;
return ret('string', 'string');
};
}
function tokenComment(stream, state) {
var maybeEnd = false, ch;
while (ch = stream.next()) {
if (ch == "/" && maybeEnd) {
state.tokenize = tokenBase;
break;
}
maybeEnd = (ch == "*");
}
return ret("comment", "comment");
}
function tokenComment(stream, state) {
var maybeEnd = false,
ch;
while ((ch = stream.next())) {
if (ch == '/' && maybeEnd) {
state.tokenize = tokenBase;
break;
}
maybeEnd = ch == '*';
}
return ret('comment', 'comment');
}
function tokenQuasi(stream, state) {
var escaped = false, next;
while ((next = stream.next()) != null) {
if (!escaped && (next == "`" || next == "$" && stream.eat("{"))) {
state.tokenize = tokenBase;
break;
}
escaped = !escaped && next == "\\";
}
return ret("quasi", "string-2", stream.current());
}
function tokenQuasi(stream, state) {
var escaped = false,
next;
while ((next = stream.next()) != null) {
if (
!escaped &&
(next == '`' || (next == '$' && stream.eat('{')))
) {
state.tokenize = tokenBase;
break;
}
escaped = !escaped && next == '\\';
}
return ret('quasi', 'string-2', stream.current());
}
var brackets = "([{}])";
// This is a crude lookahead trick to try and notice that we're
// parsing the argument patterns for a fat-arrow function before we
// actually hit the arrow token. It only works if the arrow is on
// the same line as the arguments and there's no strange noise
// (comments) in between. Fallback is to only notice when we hit the
// arrow, and not declare the arguments as locals for the arrow
// body.
function findFatArrow(stream, state) {
if (state.fatArrowAt) state.fatArrowAt = null;
var arrow = stream.string.indexOf("=>", stream.start);
if (arrow < 0) return;
var brackets = '([{}])';
// This is a crude lookahead trick to try and notice that we're
// parsing the argument patterns for a fat-arrow function before we
// actually hit the arrow token. It only works if the arrow is on
// the same line as the arguments and there's no strange noise
// (comments) in between. Fallback is to only notice when we hit the
// arrow, and not declare the arguments as locals for the arrow
// body.
function findFatArrow(stream, state) {
if (state.fatArrowAt) state.fatArrowAt = null;
var arrow = stream.string.indexOf('=>', stream.start);
if (arrow < 0) return;
if (isTS) { // Try to skip TypeScript return type declarations after the arguments
var m = /:\s*(?:\w+(?:<[^>]*>|\[\])?|\{[^}]*\})\s*$/.exec(stream.string.slice(stream.start, arrow))
if (m) arrow = m.index
}
if (isTS) {
// Try to skip TypeScript return type declarations after the arguments
var m = /:\s*(?:\w+(?:<[^>]*>|\[\])?|\{[^}]*\})\s*$/.exec(
stream.string.slice(stream.start, arrow),
);
if (m) arrow = m.index;
}
var depth = 0, sawSomething = false;
for (var pos = arrow - 1; pos >= 0; --pos) {
var ch = stream.string.charAt(pos);
var bracket = brackets.indexOf(ch);
if (bracket >= 0 && bracket < 3) {
if (!depth) { ++pos; break; }
if (--depth == 0) { if (ch == "(") sawSomething = true; break; }
} else if (bracket >= 3 && bracket < 6) {
++depth;
} else if (wordRE.test(ch)) {
sawSomething = true;
} else if (/["'\/`]/.test(ch)) {
for (;; --pos) {
if (pos == 0) return
var next = stream.string.charAt(pos - 1)
if (next == ch && stream.string.charAt(pos - 2) != "\\") { pos--; break }
var depth = 0,
sawSomething = false;
for (var pos = arrow - 1; pos >= 0; --pos) {
var ch = stream.string.charAt(pos);
var bracket = brackets.indexOf(ch);
if (bracket >= 0 && bracket < 3) {
if (!depth) {
++pos;
break;
}
if (--depth == 0) {
if (ch == '(') sawSomething = true;
break;
}
} else if (bracket >= 3 && bracket < 6) {
++depth;
} else if (wordRE.test(ch)) {
sawSomething = true;
} else if (/["'\/`]/.test(ch)) {
for (; ; --pos) {
if (pos == 0) return;
var next = stream.string.charAt(pos - 1);
if (
next == ch &&
stream.string.charAt(pos - 2) != '\\'
) {
pos--;
break;
}
}
} else if (sawSomething && !depth) {
++pos;
break;
}
}
if (sawSomething && !depth) state.fatArrowAt = pos;
}
} else if (sawSomething && !depth) {
++pos;
break;
}
}
if (sawSomething && !depth) state.fatArrowAt = pos;
}
// Parser
// Parser
var atomicTypes = {"atom": true, "number": true, "variable": true, "string": true, "regexp": true, "this": true, "jsonld-keyword": true};
var atomicTypes = {
atom: true,
number: true,
variable: true,
string: true,
regexp: true,
this: true,
'jsonld-keyword': true,
};
function JSLexical(indented, column, type, align, prev, info) {
this.indented = indented;
this.column = column;
this.type = type;
this.prev = prev;
this.info = info;
if (align != null) this.align = align;
}
function JSLexical(indented, column, type, align, prev, info) {
this.indented = indented;
this.column = column;
this.type = type;
this.prev = prev;
this.info = info;
if (align != null) this.align = align;
}
function inScope(state, varname) {
for (var v = state.localVars; v; v = v.next)
if (v.name == varname) return true;
for (var cx = state.context; cx; cx = cx.prev) {
for (var v = cx.vars; v; v = v.next)
if (v.name == varname) return true;
}
}
function inScope(state, varname) {
for (var v = state.localVars; v; v = v.next)
if (v.name == varname) return true;
for (var cx = state.context; cx; cx = cx.prev) {
for (var v = cx.vars; v; v = v.next)
if (v.name == varname) return true;
}
}
function parseJS(state, style, type, content, stream) {
var cc = state.cc;
// Communicate our context to the combinators.
// (Less wasteful than consing up a hundred closures on every call.)
cx.state = state; cx.stream = stream; cx.marked = null, cx.cc = cc; cx.style = style;
function parseJS(state, style, type, content, stream) {
var cc = state.cc;
// Communicate our context to the combinators.
// (Less wasteful than consing up a hundred closures on every call.)
cx.state = state;
cx.stream = stream;
(cx.marked = null), (cx.cc = cc);
cx.style = style;
if (!state.lexical.hasOwnProperty("align"))
state.lexical.align = true;
if (!state.lexical.hasOwnProperty('align'))
state.lexical.align = true;
while(true) {
var combinator = cc.length ? cc.pop() : jsonMode ? expression : statement;
if (combinator(type, content)) {
while(cc.length && cc[cc.length - 1].lex)
cc.pop()();
if (cx.marked) return cx.marked;
if (type == "variable" && inScope(state, content)) return "variable-2";
return style;
}
}
}
while (true) {
var combinator = cc.length
? cc.pop()
: jsonMode
? expression
: statement;
if (combinator(type, content)) {
while (cc.length && cc[cc.length - 1].lex) cc.pop()();
if (cx.marked) return cx.marked;
if (type == 'variable' && inScope(state, content))
return 'variable-2';
return style;
}
}
}
// Combinator utils
// Combinator utils
var cx = {state: null, column: null, marked: null, cc: null};
function pass() {
for (var i = arguments.length - 1; i >= 0; i--) cx.cc.push(arguments[i]);
}
function cont() {
pass.apply(null, arguments);
return true;
}
function inList(name, list) {
for (var v = list; v; v = v.next) if (v.name == name) return true
return false;
}
function register(varname) {
var state = cx.state;
cx.marked = "def";
if (state.context) {
if (state.lexical.info == "var" && state.context && state.context.block) {
// FIXME function decls are also not block scoped
var newContext = registerVarScoped(varname, state.context)
if (newContext != null) {
state.context = newContext
return
var cx = { state: null, column: null, marked: null, cc: null };
function pass() {
for (var i = arguments.length - 1; i >= 0; i--)
cx.cc.push(arguments[i]);
}
} else if (!inList(varname, state.localVars)) {
state.localVars = new Var(varname, state.localVars)
return
}
}
// Fall through means this is global
if (parserConfig.globalVars && !inList(varname, state.globalVars))
state.globalVars = new Var(varname, state.globalVars)
}
function registerVarScoped(varname, context) {
if (!context) {
return null
} else if (context.block) {
var inner = registerVarScoped(varname, context.prev)
if (!inner) return null
if (inner == context.prev) return context
return new Context(inner, context.vars, true)
} else if (inList(varname, context.vars)) {
return context
} else {
return new Context(context.prev, new Var(varname, context.vars), false)
}
}
function cont() {
pass.apply(null, arguments);
return true;
}
function inList(name, list) {
for (var v = list; v; v = v.next) if (v.name == name) return true;
return false;
}
function register(varname) {
var state = cx.state;
cx.marked = 'def';
if (state.context) {
if (
state.lexical.info == 'var' &&
state.context &&
state.context.block
) {
// FIXME function decls are also not block scoped
var newContext = registerVarScoped(varname, state.context);
if (newContext != null) {
state.context = newContext;
return;
}
} else if (!inList(varname, state.localVars)) {
state.localVars = new Var(varname, state.localVars);
return;
}
}
// Fall through means this is global
if (parserConfig.globalVars && !inList(varname, state.globalVars))
state.globalVars = new Var(varname, state.globalVars);
}
function registerVarScoped(varname, context) {
if (!context) {
return null;
} else if (context.block) {
var inner = registerVarScoped(varname, context.prev);
if (!inner) return null;
if (inner == context.prev) return context;
return new Context(inner, context.vars, true);
} else if (inList(varname, context.vars)) {
return context;
} else {
return new Context(
context.prev,
new Var(varname, context.vars),
false,
);
}
}
function isModifier(name) {
return name == "public" || name == "private" || name == "protected" || name == "abstract" || name == "readonly"
}
function isModifier(name) {
return (
name == 'public' ||
name == 'private' ||
name == 'protected' ||
name == 'abstract' ||
name == 'readonly'
);
}
// Combinators
// Combinators
function Context(prev, vars, block) { this.prev = prev; this.vars = vars; this.block = block }
function Var(name, next) { this.name = name; this.next = next }
function Context(prev, vars, block) {
this.prev = prev;
this.vars = vars;
this.block = block;
}
function Var(name, next) {
this.name = name;
this.next = next;
}
var defaultVars = new Var("this", new Var("arguments", null))
function pushcontext() {
cx.state.context = new Context(cx.state.context, cx.state.localVars, false)
cx.state.localVars = defaultVars
}
function pushblockcontext() {
cx.state.context = new Context(cx.state.context, cx.state.localVars, true)
cx.state.localVars = null
}
function popcontext() {
cx.state.localVars = cx.state.context.vars
cx.state.context = cx.state.context.prev
}
popcontext.lex = true
function pushlex(type, info) {
var result = function() {
var state = cx.state, indent = state.indented;
if (state.lexical.type == "stat") indent = state.lexical.indented;
else for (var outer = state.lexical; outer && outer.type == ")" && outer.align; outer = outer.prev)
indent = outer.indented;
state.lexical = new JSLexical(indent, cx.stream.column(), type, null, state.lexical, info);
};
result.lex = true;
return result;
}
function poplex() {
var state = cx.state;
if (state.lexical.prev) {
if (state.lexical.type == ")")
state.indented = state.lexical.indented;
state.lexical = state.lexical.prev;
}
}
poplex.lex = true;
var defaultVars = new Var('this', new Var('arguments', null));
function pushcontext() {
cx.state.context = new Context(
cx.state.context,
cx.state.localVars,
false,
);
cx.state.localVars = defaultVars;
}
function pushblockcontext() {
cx.state.context = new Context(
cx.state.context,
cx.state.localVars,
true,
);
cx.state.localVars = null;
}
function popcontext() {
cx.state.localVars = cx.state.context.vars;
cx.state.context = cx.state.context.prev;
}
popcontext.lex = true;
function pushlex(type, info) {
var result = function () {
var state = cx.state,
indent = state.indented;
if (state.lexical.type == 'stat')
indent = state.lexical.indented;
else
for (
var outer = state.lexical;
outer && outer.type == ')' && outer.align;
outer = outer.prev
)
indent = outer.indented;
state.lexical = new JSLexical(
indent,
cx.stream.column(),
type,
null,
state.lexical,
info,
);
};
result.lex = true;
return result;
}
function poplex() {
var state = cx.state;
if (state.lexical.prev) {
if (state.lexical.type == ')')
state.indented = state.lexical.indented;
state.lexical = state.lexical.prev;
}
}
poplex.lex = true;
function expect(wanted) {
function exp(type) {
if (type == wanted) return cont();
else if (wanted == ";" || type == "}" || type == ")" || type == "]") return pass();
else return cont(exp);
};
return exp;
}
function expect(wanted) {
function exp(type) {
if (type == wanted) return cont();
else if (
wanted == ';' ||
type == '}' ||
type == ')' ||
type == ']'
)
return pass();
else return cont(exp);
}
return exp;
}
function statement(type, value) {
if (type == "var") return cont(pushlex("vardef", value), vardef, expect(";"), poplex);
if (type == "keyword a") return cont(pushlex("form"), parenExpr, statement, poplex);
if (type == "keyword b") return cont(pushlex("form"), statement, poplex);
if (type == "keyword d") return cx.stream.match(/^\s*$/, false) ? cont() : cont(pushlex("stat"), maybeexpression, expect(";"), poplex);
if (type == "debugger") return cont(expect(";"));
if (type == "{") return cont(pushlex("}"), pushblockcontext, block, poplex, popcontext);
if (type == ";") return cont();
if (type == "if") {
if (cx.state.lexical.info == "else" && cx.state.cc[cx.state.cc.length - 1] == poplex)
cx.state.cc.pop()();
return cont(pushlex("form"), parenExpr, statement, poplex, maybeelse);
}
if (type == "function") return cont(functiondef);
if (type == "for") return cont(pushlex("form"), forspec, statement, poplex);
if (type == "class" || (isTS && value == "interface")) {
cx.marked = "keyword"
return cont(pushlex("form", type == "class" ? type : value), className, poplex)
}
if (type == "variable") {
if (isTS && value == "declare") {
cx.marked = "keyword"
return cont(statement)
} else if (isTS && (value == "module" || value == "enum" || value == "type") && cx.stream.match(/^\s*\w/, false)) {
cx.marked = "keyword"
if (value == "enum") return cont(enumdef);
else if (value == "type") return cont(typename, expect("operator"), typeexpr, expect(";"));
else return cont(pushlex("form"), pattern, expect("{"), pushlex("}"), block, poplex, poplex)
} else if (isTS && value == "namespace") {
cx.marked = "keyword"
return cont(pushlex("form"), expression, statement, poplex)
} else if (isTS && value == "abstract") {
cx.marked = "keyword"
return cont(statement)
} else {
return cont(pushlex("stat"), maybelabel);
}
}
if (type == "switch") return cont(pushlex("form"), parenExpr, expect("{"), pushlex("}", "switch"), pushblockcontext,
block, poplex, poplex, popcontext);
if (type == "case") return cont(expression, expect(":"));
if (type == "default") return cont(expect(":"));
if (type == "catch") return cont(pushlex("form"), pushcontext, maybeCatchBinding, statement, poplex, popcontext);
if (type == "export") return cont(pushlex("stat"), afterExport, poplex);
if (type == "import") return cont(pushlex("stat"), afterImport, poplex);
if (type == "async") return cont(statement)
if (value == "@") return cont(expression, statement)
return pass(pushlex("stat"), expression, expect(";"), poplex);
}
function maybeCatchBinding(type) {
if (type == "(") return cont(funarg, expect(")"))
}
function expression(type, value) {
return expressionInner(type, value, false);
}
function expressionNoComma(type, value) {
return expressionInner(type, value, true);
}
function parenExpr(type) {
if (type != "(") return pass()
return cont(pushlex(")"), expression, expect(")"), poplex)
}
function expressionInner(type, value, noComma) {
if (cx.state.fatArrowAt == cx.stream.start) {
var body = noComma ? arrowBodyNoComma : arrowBody;
if (type == "(") return cont(pushcontext, pushlex(")"), commasep(funarg, ")"), poplex, expect("=>"), body, popcontext);
else if (type == "variable") return pass(pushcontext, pattern, expect("=>"), body, popcontext);
}
function statement(type, value) {
if (type == 'var')
return cont(
pushlex('vardef', value),
vardef,
expect(';'),
poplex,
);
if (type == 'keyword a')
return cont(pushlex('form'), parenExpr, statement, poplex);
if (type == 'keyword b')
return cont(pushlex('form'), statement, poplex);
if (type == 'keyword d')
return cx.stream.match(/^\s*$/, false)
? cont()
: cont(
pushlex('stat'),
maybeexpression,
expect(';'),
poplex,
);
if (type == 'debugger') return cont(expect(';'));
if (type == '{')
return cont(
pushlex('}'),
pushblockcontext,
block,
poplex,
popcontext,
);
if (type == ';') return cont();
if (type == 'if') {
if (
cx.state.lexical.info == 'else' &&
cx.state.cc[cx.state.cc.length - 1] == poplex
)
cx.state.cc.pop()();
return cont(
pushlex('form'),
parenExpr,
statement,
poplex,
maybeelse,
);
}
if (type == 'function') return cont(functiondef);
if (type == 'for')
return cont(pushlex('form'), forspec, statement, poplex);
if (type == 'class' || (isTS && value == 'interface')) {
cx.marked = 'keyword';
return cont(
pushlex('form', type == 'class' ? type : value),
className,
poplex,
);
}
if (type == 'variable') {
if (isTS && value == 'declare') {
cx.marked = 'keyword';
return cont(statement);
} else if (
isTS &&
(value == 'module' || value == 'enum' || value == 'type') &&
cx.stream.match(/^\s*\w/, false)
) {
cx.marked = 'keyword';
if (value == 'enum') return cont(enumdef);
else if (value == 'type')
return cont(
typename,
expect('operator'),
typeexpr,
expect(';'),
);
else
return cont(
pushlex('form'),
pattern,
expect('{'),
pushlex('}'),
block,
poplex,
poplex,
);
} else if (isTS && value == 'namespace') {
cx.marked = 'keyword';
return cont(pushlex('form'), expression, statement, poplex);
} else if (isTS && value == 'abstract') {
cx.marked = 'keyword';
return cont(statement);
} else {
return cont(pushlex('stat'), maybelabel);
}
}
if (type == 'switch')
return cont(
pushlex('form'),
parenExpr,
expect('{'),
pushlex('}', 'switch'),
pushblockcontext,
block,
poplex,
poplex,
popcontext,
);
if (type == 'case') return cont(expression, expect(':'));
if (type == 'default') return cont(expect(':'));
if (type == 'catch')
return cont(
pushlex('form'),
pushcontext,
maybeCatchBinding,
statement,
poplex,
popcontext,
);
if (type == 'export')
return cont(pushlex('stat'), afterExport, poplex);
if (type == 'import')
return cont(pushlex('stat'), afterImport, poplex);
if (type == 'async') return cont(statement);
if (value == '@') return cont(expression, statement);
return pass(pushlex('stat'), expression, expect(';'), poplex);
}
function maybeCatchBinding(type) {
if (type == '(') return cont(funarg, expect(')'));
}
function expression(type, value) {
return expressionInner(type, value, false);
}
function expressionNoComma(type, value) {
return expressionInner(type, value, true);
}
function parenExpr(type) {
if (type != '(') return pass();
return cont(pushlex(')'), expression, expect(')'), poplex);
}
function expressionInner(type, value, noComma) {
if (cx.state.fatArrowAt == cx.stream.start) {
var body = noComma ? arrowBodyNoComma : arrowBody;
if (type == '(')
return cont(
pushcontext,
pushlex(')'),
commasep(funarg, ')'),
poplex,
expect('=>'),
body,
popcontext,
);
else if (type == 'variable')
return pass(
pushcontext,
pattern,
expect('=>'),
body,
popcontext,
);
}
var maybeop = noComma ? maybeoperatorNoComma : maybeoperatorComma;
if (atomicTypes.hasOwnProperty(type)) return cont(maybeop);
if (type == "function") return cont(functiondef, maybeop);
if (type == "class" || (isTS && value == "interface")) { cx.marked = "keyword"; return cont(pushlex("form"), classExpression, poplex); }
if (type == "keyword c" || type == "async") return cont(noComma ? expressionNoComma : expression);
if (type == "(") return cont(pushlex(")"), maybeexpression, expect(")"), poplex, maybeop);
if (type == "operator" || type == "spread") return cont(noComma ? expressionNoComma : expression);
if (type == "[") return cont(pushlex("]"), arrayLiteral, poplex, maybeop);
if (type == "{") return contCommasep(objprop, "}", null, maybeop);
if (type == "quasi") return pass(quasi, maybeop);
if (type == "new") return cont(maybeTarget(noComma));
if (type == "import") return cont(expression);
return cont();
}
function maybeexpression(type) {
if (type.match(/[;\}\)\],]/)) return pass();
return pass(expression);
}
var maybeop = noComma ? maybeoperatorNoComma : maybeoperatorComma;
if (atomicTypes.hasOwnProperty(type)) return cont(maybeop);
if (type == 'function') return cont(functiondef, maybeop);
if (type == 'class' || (isTS && value == 'interface')) {
cx.marked = 'keyword';
return cont(pushlex('form'), classExpression, poplex);
}
if (type == 'keyword c' || type == 'async')
return cont(noComma ? expressionNoComma : expression);
if (type == '(')
return cont(
pushlex(')'),
maybeexpression,
expect(')'),
poplex,
maybeop,
);
if (type == 'operator' || type == 'spread')
return cont(noComma ? expressionNoComma : expression);
if (type == '[')
return cont(pushlex(']'), arrayLiteral, poplex, maybeop);
if (type == '{') return contCommasep(objprop, '}', null, maybeop);
if (type == 'quasi') return pass(quasi, maybeop);
if (type == 'new') return cont(maybeTarget(noComma));
if (type == 'import') return cont(expression);
return cont();
}
function maybeexpression(type) {
if (type.match(/[;\}\)\],]/)) return pass();
return pass(expression);
}
function maybeoperatorComma(type, value) {
if (type == ",") return cont(expression);
return maybeoperatorNoComma(type, value, false);
}
function maybeoperatorNoComma(type, value, noComma) {
var me = noComma == false ? maybeoperatorComma : maybeoperatorNoComma;
var expr = noComma == false ? expression : expressionNoComma;
if (type == "=>") return cont(pushcontext, noComma ? arrowBodyNoComma : arrowBody, popcontext);
if (type == "operator") {
if (/\+\+|--/.test(value) || isTS && value == "!") return cont(me);
if (isTS && value == "<" && cx.stream.match(/^([^>]|<.*?>)*>\s*\(/, false))
return cont(pushlex(">"), commasep(typeexpr, ">"), poplex, me);
if (value == "?") return cont(expression, expect(":"), expr);
return cont(expr);
}
if (type == "quasi") { return pass(quasi, me); }
if (type == ";") return;
if (type == "(") return contCommasep(expressionNoComma, ")", "call", me);
if (type == ".") return cont(property, me);
if (type == "[") return cont(pushlex("]"), maybeexpression, expect("]"), poplex, me);
if (isTS && value == "as") { cx.marked = "keyword"; return cont(typeexpr, me) }
if (type == "regexp") {
cx.state.lastType = cx.marked = "operator"
cx.stream.backUp(cx.stream.pos - cx.stream.start - 1)
return cont(expr)
}
}
function quasi(type, value) {
if (type != "quasi") return pass();
if (value.slice(value.length - 2) != "${") return cont(quasi);
return cont(expression, continueQuasi);
}
function continueQuasi(type) {
if (type == "}") {
cx.marked = "string-2";
cx.state.tokenize = tokenQuasi;
return cont(quasi);
}
}
function arrowBody(type) {
findFatArrow(cx.stream, cx.state);
return pass(type == "{" ? statement : expression);
}
function arrowBodyNoComma(type) {
findFatArrow(cx.stream, cx.state);
return pass(type == "{" ? statement : expressionNoComma);
}
function maybeTarget(noComma) {
return function(type) {
if (type == ".") return cont(noComma ? targetNoComma : target);
else if (type == "variable" && isTS) return cont(maybeTypeArgs, noComma ? maybeoperatorNoComma : maybeoperatorComma)
else return pass(noComma ? expressionNoComma : expression);
};
}
function target(_, value) {
if (value == "target") { cx.marked = "keyword"; return cont(maybeoperatorComma); }
}
function targetNoComma(_, value) {
if (value == "target") { cx.marked = "keyword"; return cont(maybeoperatorNoComma); }
}
function maybelabel(type) {
if (type == ":") return cont(poplex, statement);
return pass(maybeoperatorComma, expect(";"), poplex);
}
function property(type) {
if (type == "variable") {cx.marked = "property"; return cont();}
}
function objprop(type, value) {
if (type == "async") {
cx.marked = "property";
return cont(objprop);
} else if (type == "variable" || cx.style == "keyword") {
cx.marked = "property";
if (value == "get" || value == "set") return cont(getterSetter);
var m // Work around fat-arrow-detection complication for detecting typescript typed arrow params
if (isTS && cx.state.fatArrowAt == cx.stream.start && (m = cx.stream.match(/^\s*:\s*/, false)))
cx.state.fatArrowAt = cx.stream.pos + m[0].length
return cont(afterprop);
} else if (type == "number" || type == "string") {
cx.marked = jsonldMode ? "property" : (cx.style + " property");
return cont(afterprop);
} else if (type == "jsonld-keyword") {
return cont(afterprop);
} else if (isTS && isModifier(value)) {
cx.marked = "keyword"
return cont(objprop)
} else if (type == "[") {
return cont(expression, maybetype, expect("]"), afterprop);
} else if (type == "spread") {
return cont(expressionNoComma, afterprop);
} else if (value == "*") {
cx.marked = "keyword";
return cont(objprop);
} else if (type == ":") {
return pass(afterprop)
}
}
function getterSetter(type) {
if (type != "variable") return pass(afterprop);
cx.marked = "property";
return cont(functiondef);
}
function afterprop(type) {
if (type == ":") return cont(expressionNoComma);
if (type == "(") return pass(functiondef);
}
function commasep(what, end, sep) {
function proceed(type, value) {
if (sep ? sep.indexOf(type) > -1 : type == ",") {
var lex = cx.state.lexical;
if (lex.info == "call") lex.pos = (lex.pos || 0) + 1;
return cont(function(type, value) {
if (type == end || value == end) return pass()
return pass(what)
}, proceed);
}
if (type == end || value == end) return cont();
if (sep && sep.indexOf(";") > -1) return pass(what)
return cont(expect(end));
}
return function(type, value) {
if (type == end || value == end) return cont();
return pass(what, proceed);
};
}
function contCommasep(what, end, info) {
for (var i = 3; i < arguments.length; i++)
cx.cc.push(arguments[i]);
return cont(pushlex(end, info), commasep(what, end), poplex);
}
function block(type) {
if (type == "}") return cont();
return pass(statement, block);
}
function maybetype(type, value) {
if (isTS) {
if (type == ":") return cont(typeexpr);
if (value == "?") return cont(maybetype);
}
}
function maybetypeOrIn(type, value) {
if (isTS && (type == ":" || value == "in")) return cont(typeexpr)
}
function mayberettype(type) {
if (isTS && type == ":") {
if (cx.stream.match(/^\s*\w+\s+is\b/, false)) return cont(expression, isKW, typeexpr)
else return cont(typeexpr)
}
}
function isKW(_, value) {
if (value == "is") {
cx.marked = "keyword"
return cont()
}
}
function typeexpr(type, value) {
if (value == "keyof" || value == "typeof" || value == "infer") {
cx.marked = "keyword"
return cont(value == "typeof" ? expressionNoComma : typeexpr)
}
if (type == "variable" || value == "void") {
cx.marked = "type"
return cont(afterType)
}
if (value == "|" || value == "&") return cont(typeexpr)
if (type == "string" || type == "number" || type == "atom") return cont(afterType);
if (type == "[") return cont(pushlex("]"), commasep(typeexpr, "]", ","), poplex, afterType)
if (type == "{") return cont(pushlex("}"), commasep(typeprop, "}", ",;"), poplex, afterType)
if (type == "(") return cont(commasep(typearg, ")"), maybeReturnType, afterType)
if (type == "<") return cont(commasep(typeexpr, ">"), typeexpr)
}
function maybeReturnType(type) {
if (type == "=>") return cont(typeexpr)
}
function typeprop(type, value) {
if (type == "variable" || cx.style == "keyword") {
cx.marked = "property"
return cont(typeprop)
} else if (value == "?" || type == "number" || type == "string") {
return cont(typeprop)
} else if (type == ":") {
return cont(typeexpr)
} else if (type == "[") {
return cont(expect("variable"), maybetypeOrIn, expect("]"), typeprop)
} else if (type == "(") {
return pass(functiondecl, typeprop)
}
}
function typearg(type, value) {
if (type == "variable" && cx.stream.match(/^\s*[?:]/, false) || value == "?") return cont(typearg)
if (type == ":") return cont(typeexpr)
if (type == "spread") return cont(typearg)
return pass(typeexpr)
}
function afterType(type, value) {
if (value == "<") return cont(pushlex(">"), commasep(typeexpr, ">"), poplex, afterType)
if (value == "|" || type == "." || value == "&") return cont(typeexpr)
if (type == "[") return cont(typeexpr, expect("]"), afterType)
if (value == "extends" || value == "implements") { cx.marked = "keyword"; return cont(typeexpr) }
if (value == "?") return cont(typeexpr, expect(":"), typeexpr)
}
function maybeTypeArgs(_, value) {
if (value == "<") return cont(pushlex(">"), commasep(typeexpr, ">"), poplex, afterType)
}
function typeparam() {
return pass(typeexpr, maybeTypeDefault)
}
function maybeTypeDefault(_, value) {
if (value == "=") return cont(typeexpr)
}
function vardef(_, value) {
if (value == "enum") {cx.marked = "keyword"; return cont(enumdef)}
return pass(pattern, maybetype, maybeAssign, vardefCont);
}
function pattern(type, value) {
if (isTS && isModifier(value)) { cx.marked = "keyword"; return cont(pattern) }
if (type == "variable") { register(value); return cont(); }
if (type == "spread") return cont(pattern);
if (type == "[") return contCommasep(eltpattern, "]");
if (type == "{") return contCommasep(proppattern, "}");
}
function proppattern(type, value) {
if (type == "variable" && !cx.stream.match(/^\s*:/, false)) {
register(value);
return cont(maybeAssign);
}
if (type == "variable") cx.marked = "property";
if (type == "spread") return cont(pattern);
if (type == "}") return pass();
if (type == "[") return cont(expression, expect(']'), expect(':'), proppattern);
return cont(expect(":"), pattern, maybeAssign);
}
function eltpattern() {
return pass(pattern, maybeAssign)
}
function maybeAssign(_type, value) {
if (value == "=") return cont(expressionNoComma);
}
function vardefCont(type) {
if (type == ",") return cont(vardef);
}
function maybeelse(type, value) {
if (type == "keyword b" && value == "else") return cont(pushlex("form", "else"), statement, poplex);
}
function forspec(type, value) {
if (value == "await") return cont(forspec);
if (type == "(") return cont(pushlex(")"), forspec1, poplex);
}
function forspec1(type) {
if (type == "var") return cont(vardef, forspec2);
if (type == "variable") return cont(forspec2);
return pass(forspec2)
}
function forspec2(type, value) {
if (type == ")") return cont()
if (type == ";") return cont(forspec2)
if (value == "in" || value == "of") { cx.marked = "keyword"; return cont(expression, forspec2) }
return pass(expression, forspec2)
}
function functiondef(type, value) {
if (value == "*") {cx.marked = "keyword"; return cont(functiondef);}
if (type == "variable") {register(value); return cont(functiondef);}
if (type == "(") return cont(pushcontext, pushlex(")"), commasep(funarg, ")"), poplex, mayberettype, statement, popcontext);
if (isTS && value == "<") return cont(pushlex(">"), commasep(typeparam, ">"), poplex, functiondef)
}
function functiondecl(type, value) {
if (value == "*") {cx.marked = "keyword"; return cont(functiondecl);}
if (type == "variable") {register(value); return cont(functiondecl);}
if (type == "(") return cont(pushcontext, pushlex(")"), commasep(funarg, ")"), poplex, mayberettype, popcontext);
if (isTS && value == "<") return cont(pushlex(">"), commasep(typeparam, ">"), poplex, functiondecl)
}
function typename(type, value) {
if (type == "keyword" || type == "variable") {
cx.marked = "type"
return cont(typename)
} else if (value == "<") {
return cont(pushlex(">"), commasep(typeparam, ">"), poplex)
}
}
function funarg(type, value) {
if (value == "@") cont(expression, funarg)
if (type == "spread") return cont(funarg);
if (isTS && isModifier(value)) { cx.marked = "keyword"; return cont(funarg); }
if (isTS && type == "this") return cont(maybetype, maybeAssign)
return pass(pattern, maybetype, maybeAssign);
}
function classExpression(type, value) {
// Class expressions may have an optional name.
if (type == "variable") return className(type, value);
return classNameAfter(type, value);
}
function className(type, value) {
if (type == "variable") {register(value); return cont(classNameAfter);}
}
function classNameAfter(type, value) {
if (value == "<") return cont(pushlex(">"), commasep(typeparam, ">"), poplex, classNameAfter)
if (value == "extends" || value == "implements" || (isTS && type == ",")) {
if (value == "implements") cx.marked = "keyword";
return cont(isTS ? typeexpr : expression, classNameAfter);
}
if (type == "{") return cont(pushlex("}"), classBody, poplex);
}
function classBody(type, value) {
if (type == "async" ||
(type == "variable" &&
(value == "static" || value == "get" || value == "set" || (isTS && isModifier(value))) &&
cx.stream.match(/^\s+[\w$\xa1-\uffff]/, false))) {
cx.marked = "keyword";
return cont(classBody);
}
if (type == "variable" || cx.style == "keyword") {
cx.marked = "property";
return cont(isTS ? classfield : functiondef, classBody);
}
if (type == "number" || type == "string") return cont(isTS ? classfield : functiondef, classBody);
if (type == "[")
return cont(expression, maybetype, expect("]"), isTS ? classfield : functiondef, classBody)
if (value == "*") {
cx.marked = "keyword";
return cont(classBody);
}
if (isTS && type == "(") return pass(functiondecl, classBody)
if (type == ";" || type == ",") return cont(classBody);
if (type == "}") return cont();
if (value == "@") return cont(expression, classBody)
}
function classfield(type, value) {
if (value == "?") return cont(classfield)
if (type == ":") return cont(typeexpr, maybeAssign)
if (value == "=") return cont(expressionNoComma)
var context = cx.state.lexical.prev, isInterface = context && context.info == "interface"
return pass(isInterface ? functiondecl : functiondef)
}
function afterExport(type, value) {
if (value == "*") { cx.marked = "keyword"; return cont(maybeFrom, expect(";")); }
if (value == "default") { cx.marked = "keyword"; return cont(expression, expect(";")); }
if (type == "{") return cont(commasep(exportField, "}"), maybeFrom, expect(";"));
return pass(statement);
}
function exportField(type, value) {
if (value == "as") { cx.marked = "keyword"; return cont(expect("variable")); }
if (type == "variable") return pass(expressionNoComma, exportField);
}
function afterImport(type) {
if (type == "string") return cont();
if (type == "(") return pass(expression);
return pass(importSpec, maybeMoreImports, maybeFrom);
}
function importSpec(type, value) {
if (type == "{") return contCommasep(importSpec, "}");
if (type == "variable") register(value);
if (value == "*") cx.marked = "keyword";
return cont(maybeAs);
}
function maybeMoreImports(type) {
if (type == ",") return cont(importSpec, maybeMoreImports)
}
function maybeAs(_type, value) {
if (value == "as") { cx.marked = "keyword"; return cont(importSpec); }
}
function maybeFrom(_type, value) {
if (value == "from") { cx.marked = "keyword"; return cont(expression); }
}
function arrayLiteral(type) {
if (type == "]") return cont();
return pass(commasep(expressionNoComma, "]"));
}
function enumdef() {
return pass(pushlex("form"), pattern, expect("{"), pushlex("}"), commasep(enummember, "}"), poplex, poplex)
}
function enummember() {
return pass(pattern, maybeAssign);
}
function maybeoperatorComma(type, value) {
if (type == ',') return cont(expression);
return maybeoperatorNoComma(type, value, false);
}
function maybeoperatorNoComma(type, value, noComma) {
var me =
noComma == false ? maybeoperatorComma : maybeoperatorNoComma;
var expr = noComma == false ? expression : expressionNoComma;
if (type == '=>')
return cont(
pushcontext,
noComma ? arrowBodyNoComma : arrowBody,
popcontext,
);
if (type == 'operator') {
if (/\+\+|--/.test(value) || (isTS && value == '!'))
return cont(me);
if (
isTS &&
value == '<' &&
cx.stream.match(/^([^>]|<.*?>)*>\s*\(/, false)
)
return cont(
pushlex('>'),
commasep(typeexpr, '>'),
poplex,
me,
);
if (value == '?') return cont(expression, expect(':'), expr);
return cont(expr);
}
if (type == 'quasi') {
return pass(quasi, me);
}
if (type == ';') return;
if (type == '(')
return contCommasep(expressionNoComma, ')', 'call', me);
if (type == '.') return cont(property, me);
if (type == '[')
return cont(
pushlex(']'),
maybeexpression,
expect(']'),
poplex,
me,
);
if (isTS && value == 'as') {
cx.marked = 'keyword';
return cont(typeexpr, me);
}
if (type == 'regexp') {
cx.state.lastType = cx.marked = 'operator';
cx.stream.backUp(cx.stream.pos - cx.stream.start - 1);
return cont(expr);
}
}
function quasi(type, value) {
if (type != 'quasi') return pass();
if (value.slice(value.length - 2) != '${') return cont(quasi);
return cont(expression, continueQuasi);
}
function continueQuasi(type) {
if (type == '}') {
cx.marked = 'string-2';
cx.state.tokenize = tokenQuasi;
return cont(quasi);
}
}
function arrowBody(type) {
findFatArrow(cx.stream, cx.state);
return pass(type == '{' ? statement : expression);
}
function arrowBodyNoComma(type) {
findFatArrow(cx.stream, cx.state);
return pass(type == '{' ? statement : expressionNoComma);
}
function maybeTarget(noComma) {
return function (type) {
if (type == '.') return cont(noComma ? targetNoComma : target);
else if (type == 'variable' && isTS)
return cont(
maybeTypeArgs,
noComma ? maybeoperatorNoComma : maybeoperatorComma,
);
else return pass(noComma ? expressionNoComma : expression);
};
}
function target(_, value) {
if (value == 'target') {
cx.marked = 'keyword';
return cont(maybeoperatorComma);
}
}
function targetNoComma(_, value) {
if (value == 'target') {
cx.marked = 'keyword';
return cont(maybeoperatorNoComma);
}
}
function maybelabel(type) {
if (type == ':') return cont(poplex, statement);
return pass(maybeoperatorComma, expect(';'), poplex);
}
function property(type) {
if (type == 'variable') {
cx.marked = 'property';
return cont();
}
}
function objprop(type, value) {
if (type == 'async') {
cx.marked = 'property';
return cont(objprop);
} else if (type == 'variable' || cx.style == 'keyword') {
cx.marked = 'property';
if (value == 'get' || value == 'set') return cont(getterSetter);
var m; // Work around fat-arrow-detection complication for detecting typescript typed arrow params
if (
isTS &&
cx.state.fatArrowAt == cx.stream.start &&
(m = cx.stream.match(/^\s*:\s*/, false))
)
cx.state.fatArrowAt = cx.stream.pos + m[0].length;
return cont(afterprop);
} else if (type == 'number' || type == 'string') {
cx.marked = jsonldMode ? 'property' : cx.style + ' property';
return cont(afterprop);
} else if (type == 'jsonld-keyword') {
return cont(afterprop);
} else if (isTS && isModifier(value)) {
cx.marked = 'keyword';
return cont(objprop);
} else if (type == '[') {
return cont(expression, maybetype, expect(']'), afterprop);
} else if (type == 'spread') {
return cont(expressionNoComma, afterprop);
} else if (value == '*') {
cx.marked = 'keyword';
return cont(objprop);
} else if (type == ':') {
return pass(afterprop);
}
}
function getterSetter(type) {
if (type != 'variable') return pass(afterprop);
cx.marked = 'property';
return cont(functiondef);
}
function afterprop(type) {
if (type == ':') return cont(expressionNoComma);
if (type == '(') return pass(functiondef);
}
function commasep(what, end, sep) {
function proceed(type, value) {
if (sep ? sep.indexOf(type) > -1 : type == ',') {
var lex = cx.state.lexical;
if (lex.info == 'call') lex.pos = (lex.pos || 0) + 1;
return cont(function (type, value) {
if (type == end || value == end) return pass();
return pass(what);
}, proceed);
}
if (type == end || value == end) return cont();
if (sep && sep.indexOf(';') > -1) return pass(what);
return cont(expect(end));
}
return function (type, value) {
if (type == end || value == end) return cont();
return pass(what, proceed);
};
}
function contCommasep(what, end, info) {
for (var i = 3; i < arguments.length; i++) cx.cc.push(arguments[i]);
return cont(pushlex(end, info), commasep(what, end), poplex);
}
function block(type) {
if (type == '}') return cont();
return pass(statement, block);
}
function maybetype(type, value) {
if (isTS) {
if (type == ':') return cont(typeexpr);
if (value == '?') return cont(maybetype);
}
}
function maybetypeOrIn(type, value) {
if (isTS && (type == ':' || value == 'in')) return cont(typeexpr);
}
function mayberettype(type) {
if (isTS && type == ':') {
if (cx.stream.match(/^\s*\w+\s+is\b/, false))
return cont(expression, isKW, typeexpr);
else return cont(typeexpr);
}
}
function isKW(_, value) {
if (value == 'is') {
cx.marked = 'keyword';
return cont();
}
}
function typeexpr(type, value) {
if (value == 'keyof' || value == 'typeof' || value == 'infer') {
cx.marked = 'keyword';
return cont(value == 'typeof' ? expressionNoComma : typeexpr);
}
if (type == 'variable' || value == 'void') {
cx.marked = 'type';
return cont(afterType);
}
if (value == '|' || value == '&') return cont(typeexpr);
if (type == 'string' || type == 'number' || type == 'atom')
return cont(afterType);
if (type == '[')
return cont(
pushlex(']'),
commasep(typeexpr, ']', ','),
poplex,
afterType,
);
if (type == '{')
return cont(
pushlex('}'),
commasep(typeprop, '}', ',;'),
poplex,
afterType,
);
if (type == '(')
return cont(commasep(typearg, ')'), maybeReturnType, afterType);
if (type == '<') return cont(commasep(typeexpr, '>'), typeexpr);
}
function maybeReturnType(type) {
if (type == '=>') return cont(typeexpr);
}
function typeprop(type, value) {
if (type == 'variable' || cx.style == 'keyword') {
cx.marked = 'property';
return cont(typeprop);
} else if (value == '?' || type == 'number' || type == 'string') {
return cont(typeprop);
} else if (type == ':') {
return cont(typeexpr);
} else if (type == '[') {
return cont(
expect('variable'),
maybetypeOrIn,
expect(']'),
typeprop,
);
} else if (type == '(') {
return pass(functiondecl, typeprop);
}
}
function typearg(type, value) {
if (
(type == 'variable' && cx.stream.match(/^\s*[?:]/, false)) ||
value == '?'
)
return cont(typearg);
if (type == ':') return cont(typeexpr);
if (type == 'spread') return cont(typearg);
return pass(typeexpr);
}
function afterType(type, value) {
if (value == '<')
return cont(
pushlex('>'),
commasep(typeexpr, '>'),
poplex,
afterType,
);
if (value == '|' || type == '.' || value == '&')
return cont(typeexpr);
if (type == '[') return cont(typeexpr, expect(']'), afterType);
if (value == 'extends' || value == 'implements') {
cx.marked = 'keyword';
return cont(typeexpr);
}
if (value == '?') return cont(typeexpr, expect(':'), typeexpr);
}
function maybeTypeArgs(_, value) {
if (value == '<')
return cont(
pushlex('>'),
commasep(typeexpr, '>'),
poplex,
afterType,
);
}
function typeparam() {
return pass(typeexpr, maybeTypeDefault);
}
function maybeTypeDefault(_, value) {
if (value == '=') return cont(typeexpr);
}
function vardef(_, value) {
if (value == 'enum') {
cx.marked = 'keyword';
return cont(enumdef);
}
return pass(pattern, maybetype, maybeAssign, vardefCont);
}
function pattern(type, value) {
if (isTS && isModifier(value)) {
cx.marked = 'keyword';
return cont(pattern);
}
if (type == 'variable') {
register(value);
return cont();
}
if (type == 'spread') return cont(pattern);
if (type == '[') return contCommasep(eltpattern, ']');
if (type == '{') return contCommasep(proppattern, '}');
}
function proppattern(type, value) {
if (type == 'variable' && !cx.stream.match(/^\s*:/, false)) {
register(value);
return cont(maybeAssign);
}
if (type == 'variable') cx.marked = 'property';
if (type == 'spread') return cont(pattern);
if (type == '}') return pass();
if (type == '[')
return cont(expression, expect(']'), expect(':'), proppattern);
return cont(expect(':'), pattern, maybeAssign);
}
function eltpattern() {
return pass(pattern, maybeAssign);
}
function maybeAssign(_type, value) {
if (value == '=') return cont(expressionNoComma);
}
function vardefCont(type) {
if (type == ',') return cont(vardef);
}
function maybeelse(type, value) {
if (type == 'keyword b' && value == 'else')
return cont(pushlex('form', 'else'), statement, poplex);
}
function forspec(type, value) {
if (value == 'await') return cont(forspec);
if (type == '(') return cont(pushlex(')'), forspec1, poplex);
}
function forspec1(type) {
if (type == 'var') return cont(vardef, forspec2);
if (type == 'variable') return cont(forspec2);
return pass(forspec2);
}
function forspec2(type, value) {
if (type == ')') return cont();
if (type == ';') return cont(forspec2);
if (value == 'in' || value == 'of') {
cx.marked = 'keyword';
return cont(expression, forspec2);
}
return pass(expression, forspec2);
}
function functiondef(type, value) {
if (value == '*') {
cx.marked = 'keyword';
return cont(functiondef);
}
if (type == 'variable') {
register(value);
return cont(functiondef);
}
if (type == '(')
return cont(
pushcontext,
pushlex(')'),
commasep(funarg, ')'),
poplex,
mayberettype,
statement,
popcontext,
);
if (isTS && value == '<')
return cont(
pushlex('>'),
commasep(typeparam, '>'),
poplex,
functiondef,
);
}
function functiondecl(type, value) {
if (value == '*') {
cx.marked = 'keyword';
return cont(functiondecl);
}
if (type == 'variable') {
register(value);
return cont(functiondecl);
}
if (type == '(')
return cont(
pushcontext,
pushlex(')'),
commasep(funarg, ')'),
poplex,
mayberettype,
popcontext,
);
if (isTS && value == '<')
return cont(
pushlex('>'),
commasep(typeparam, '>'),
poplex,
functiondecl,
);
}
function typename(type, value) {
if (type == 'keyword' || type == 'variable') {
cx.marked = 'type';
return cont(typename);
} else if (value == '<') {
return cont(pushlex('>'), commasep(typeparam, '>'), poplex);
}
}
function funarg(type, value) {
if (value == '@') cont(expression, funarg);
if (type == 'spread') return cont(funarg);
if (isTS && isModifier(value)) {
cx.marked = 'keyword';
return cont(funarg);
}
if (isTS && type == 'this') return cont(maybetype, maybeAssign);
return pass(pattern, maybetype, maybeAssign);
}
function classExpression(type, value) {
// Class expressions may have an optional name.
if (type == 'variable') return className(type, value);
return classNameAfter(type, value);
}
function className(type, value) {
if (type == 'variable') {
register(value);
return cont(classNameAfter);
}
}
function classNameAfter(type, value) {
if (value == '<')
return cont(
pushlex('>'),
commasep(typeparam, '>'),
poplex,
classNameAfter,
);
if (
value == 'extends' ||
value == 'implements' ||
(isTS && type == ',')
) {
if (value == 'implements') cx.marked = 'keyword';
return cont(isTS ? typeexpr : expression, classNameAfter);
}
if (type == '{') return cont(pushlex('}'), classBody, poplex);
}
function classBody(type, value) {
if (
type == 'async' ||
(type == 'variable' &&
(value == 'static' ||
value == 'get' ||
value == 'set' ||
(isTS && isModifier(value))) &&
cx.stream.match(/^\s+[\w$\xa1-\uffff]/, false))
) {
cx.marked = 'keyword';
return cont(classBody);
}
if (type == 'variable' || cx.style == 'keyword') {
cx.marked = 'property';
return cont(isTS ? classfield : functiondef, classBody);
}
if (type == 'number' || type == 'string')
return cont(isTS ? classfield : functiondef, classBody);
if (type == '[')
return cont(
expression,
maybetype,
expect(']'),
isTS ? classfield : functiondef,
classBody,
);
if (value == '*') {
cx.marked = 'keyword';
return cont(classBody);
}
if (isTS && type == '(') return pass(functiondecl, classBody);
if (type == ';' || type == ',') return cont(classBody);
if (type == '}') return cont();
if (value == '@') return cont(expression, classBody);
}
function classfield(type, value) {
if (value == '?') return cont(classfield);
if (type == ':') return cont(typeexpr, maybeAssign);
if (value == '=') return cont(expressionNoComma);
var context = cx.state.lexical.prev,
isInterface = context && context.info == 'interface';
return pass(isInterface ? functiondecl : functiondef);
}
function afterExport(type, value) {
if (value == '*') {
cx.marked = 'keyword';
return cont(maybeFrom, expect(';'));
}
if (value == 'default') {
cx.marked = 'keyword';
return cont(expression, expect(';'));
}
if (type == '{')
return cont(commasep(exportField, '}'), maybeFrom, expect(';'));
return pass(statement);
}
function exportField(type, value) {
if (value == 'as') {
cx.marked = 'keyword';
return cont(expect('variable'));
}
if (type == 'variable') return pass(expressionNoComma, exportField);
}
function afterImport(type) {
if (type == 'string') return cont();
if (type == '(') return pass(expression);
return pass(importSpec, maybeMoreImports, maybeFrom);
}
function importSpec(type, value) {
if (type == '{') return contCommasep(importSpec, '}');
if (type == 'variable') register(value);
if (value == '*') cx.marked = 'keyword';
return cont(maybeAs);
}
function maybeMoreImports(type) {
if (type == ',') return cont(importSpec, maybeMoreImports);
}
function maybeAs(_type, value) {
if (value == 'as') {
cx.marked = 'keyword';
return cont(importSpec);
}
}
function maybeFrom(_type, value) {
if (value == 'from') {
cx.marked = 'keyword';
return cont(expression);
}
}
function arrayLiteral(type) {
if (type == ']') return cont();
return pass(commasep(expressionNoComma, ']'));
}
function enumdef() {
return pass(
pushlex('form'),
pattern,
expect('{'),
pushlex('}'),
commasep(enummember, '}'),
poplex,
poplex,
);
}
function enummember() {
return pass(pattern, maybeAssign);
}
function isContinuedStatement(state, textAfter) {
return state.lastType == "operator" || state.lastType == "," ||
isOperatorChar.test(textAfter.charAt(0)) ||
/[,.]/.test(textAfter.charAt(0));
}
function isContinuedStatement(state, textAfter) {
return (
state.lastType == 'operator' ||
state.lastType == ',' ||
isOperatorChar.test(textAfter.charAt(0)) ||
/[,.]/.test(textAfter.charAt(0))
);
}
function expressionAllowed(stream, state, backUp) {
return state.tokenize == tokenBase &&
/^(?:operator|sof|keyword [bcd]|case|new|export|default|spread|[\[{}\(,;:]|=>)$/.test(state.lastType) ||
(state.lastType == "quasi" && /\{\s*$/.test(stream.string.slice(0, stream.pos - (backUp || 0))))
}
function expressionAllowed(stream, state, backUp) {
return (
(state.tokenize == tokenBase &&
/^(?:operator|sof|keyword [bcd]|case|new|export|default|spread|[\[{}\(,;:]|=>)$/.test(
state.lastType,
)) ||
(state.lastType == 'quasi' &&
/\{\s*$/.test(
stream.string.slice(0, stream.pos - (backUp || 0)),
))
);
}
// Interface
// Interface
return {
startState: function(basecolumn) {
var state = {
tokenize: tokenBase,
lastType: "sof",
cc: [],
lexical: new JSLexical((basecolumn || 0) - indentUnit, 0, "block", false),
localVars: parserConfig.localVars,
context: parserConfig.localVars && new Context(null, null, false),
indented: basecolumn || 0
};
if (parserConfig.globalVars && typeof parserConfig.globalVars == "object")
state.globalVars = parserConfig.globalVars;
return state;
},
return {
startState: function (basecolumn) {
var state = {
tokenize: tokenBase,
lastType: 'sof',
cc: [],
lexical: new JSLexical(
(basecolumn || 0) - indentUnit,
0,
'block',
false,
),
localVars: parserConfig.localVars,
context:
parserConfig.localVars &&
new Context(null, null, false),
indented: basecolumn || 0,
};
if (
parserConfig.globalVars &&
typeof parserConfig.globalVars == 'object'
)
state.globalVars = parserConfig.globalVars;
return state;
},
token: function(stream, state) {
if (stream.sol()) {
if (!state.lexical.hasOwnProperty("align"))
state.lexical.align = false;
state.indented = stream.indentation();
findFatArrow(stream, state);
}
if (state.tokenize != tokenComment && stream.eatSpace()) return null;
var style = state.tokenize(stream, state);
if (type == "comment") return style;
state.lastType = type == "operator" && (content == "++" || content == "--") ? "incdec" : type;
return parseJS(state, style, type, content, stream);
},
token: function (stream, state) {
if (stream.sol()) {
if (!state.lexical.hasOwnProperty('align'))
state.lexical.align = false;
state.indented = stream.indentation();
findFatArrow(stream, state);
}
if (state.tokenize != tokenComment && stream.eatSpace())
return null;
var style = state.tokenize(stream, state);
if (type == 'comment') return style;
state.lastType =
type == 'operator' && (content == '++' || content == '--')
? 'incdec'
: type;
return parseJS(state, style, type, content, stream);
},
indent: function(state, textAfter) {
if (state.tokenize == tokenComment) return CodeMirror.Pass;
if (state.tokenize != tokenBase) return 0;
var firstChar = textAfter && textAfter.charAt(0), lexical = state.lexical, top
// Kludge to prevent 'maybelse' from blocking lexical scope pops
if (!/^\s*else\b/.test(textAfter)) for (var i = state.cc.length - 1; i >= 0; --i) {
var c = state.cc[i];
if (c == poplex) lexical = lexical.prev;
else if (c != maybeelse) break;
}
while ((lexical.type == "stat" || lexical.type == "form") &&
(firstChar == "}" || ((top = state.cc[state.cc.length - 1]) &&
(top == maybeoperatorComma || top == maybeoperatorNoComma) &&
!/^[,\.=+\-*:?[\(]/.test(textAfter))))
lexical = lexical.prev;
if (statementIndent && lexical.type == ")" && lexical.prev.type == "stat")
lexical = lexical.prev;
var type = lexical.type, closing = firstChar == type;
indent: function (state, textAfter) {
if (state.tokenize == tokenComment) return CodeMirror.Pass;
if (state.tokenize != tokenBase) return 0;
var firstChar = textAfter && textAfter.charAt(0),
lexical = state.lexical,
top;
// Kludge to prevent 'maybelse' from blocking lexical scope pops
if (!/^\s*else\b/.test(textAfter))
for (var i = state.cc.length - 1; i >= 0; --i) {
var c = state.cc[i];
if (c == poplex) lexical = lexical.prev;
else if (c != maybeelse) break;
}
while (
(lexical.type == 'stat' || lexical.type == 'form') &&
(firstChar == '}' ||
((top = state.cc[state.cc.length - 1]) &&
(top == maybeoperatorComma ||
top == maybeoperatorNoComma) &&
!/^[,\.=+\-*:?[\(]/.test(textAfter)))
)
lexical = lexical.prev;
if (
statementIndent &&
lexical.type == ')' &&
lexical.prev.type == 'stat'
)
lexical = lexical.prev;
var type = lexical.type,
closing = firstChar == type;
if (type == "vardef") return lexical.indented + (state.lastType == "operator" || state.lastType == "," ? lexical.info.length + 1 : 0);
else if (type == "form" && firstChar == "{") return lexical.indented;
else if (type == "form") return lexical.indented + indentUnit;
else if (type == "stat")
return lexical.indented + (isContinuedStatement(state, textAfter) ? statementIndent || indentUnit : 0);
else if (lexical.info == "switch" && !closing && parserConfig.doubleIndentSwitch != false)
return lexical.indented + (/^(?:case|default)\b/.test(textAfter) ? indentUnit : 2 * indentUnit);
else if (lexical.align) return lexical.column + (closing ? 0 : 1);
else return lexical.indented + (closing ? 0 : indentUnit);
},
if (type == 'vardef')
return (
lexical.indented +
(state.lastType == 'operator' || state.lastType == ','
? lexical.info.length + 1
: 0)
);
else if (type == 'form' && firstChar == '{')
return lexical.indented;
else if (type == 'form') return lexical.indented + indentUnit;
else if (type == 'stat')
return (
lexical.indented +
(isContinuedStatement(state, textAfter)
? statementIndent || indentUnit
: 0)
);
else if (
lexical.info == 'switch' &&
!closing &&
parserConfig.doubleIndentSwitch != false
)
return (
lexical.indented +
(/^(?:case|default)\b/.test(textAfter)
? indentUnit
: 2 * indentUnit)
);
else if (lexical.align)
return lexical.column + (closing ? 0 : 1);
else return lexical.indented + (closing ? 0 : indentUnit);
},
electricInput: /^\s*(?:case .*?:|default:|\{|\})$/,
blockCommentStart: jsonMode ? null : "/*",
blockCommentEnd: jsonMode ? null : "*/",
blockCommentContinue: jsonMode ? null : " * ",
lineComment: jsonMode ? null : "//",
fold: "brace",
closeBrackets: "()[]{}''\"\"``",
electricInput: /^\s*(?:case .*?:|default:|\{|\})$/,
blockCommentStart: jsonMode ? null : '/*',
blockCommentEnd: jsonMode ? null : '*/',
blockCommentContinue: jsonMode ? null : ' * ',
lineComment: jsonMode ? null : '//',
fold: 'brace',
closeBrackets: '()[]{}\'\'""``',
helperType: jsonMode ? "json" : "javascript",
jsonldMode: jsonldMode,
jsonMode: jsonMode,
helperType: jsonMode ? 'json' : 'javascript',
jsonldMode: jsonldMode,
jsonMode: jsonMode,
expressionAllowed: expressionAllowed,
expressionAllowed: expressionAllowed,
skipExpression: function(state) {
var top = state.cc[state.cc.length - 1]
if (top == expression || top == expressionNoComma) state.cc.pop()
}
};
});
skipExpression: function (state) {
var top = state.cc[state.cc.length - 1];
if (top == expression || top == expressionNoComma)
state.cc.pop();
},
};
});
CodeMirror.registerHelper("wordChars", "javascript", /[\w$]/);
CodeMirror.registerHelper('wordChars', 'javascript', /[\w$]/);
CodeMirror.defineMIME("text/javascript", "javascript");
CodeMirror.defineMIME("text/ecmascript", "javascript");
CodeMirror.defineMIME("application/javascript", "javascript");
CodeMirror.defineMIME("application/x-javascript", "javascript");
CodeMirror.defineMIME("application/ecmascript", "javascript");
CodeMirror.defineMIME("application/json", {name: "javascript", json: true});
CodeMirror.defineMIME("application/x-json", {name: "javascript", json: true});
CodeMirror.defineMIME("application/ld+json", {name: "javascript", jsonld: true});
CodeMirror.defineMIME("text/typescript", { name: "javascript", typescript: true });
CodeMirror.defineMIME("application/typescript", { name: "javascript", typescript: true });
CodeMirror.defineMIME('text/javascript', 'javascript');
CodeMirror.defineMIME('text/ecmascript', 'javascript');
CodeMirror.defineMIME('application/javascript', 'javascript');
CodeMirror.defineMIME('application/x-javascript', 'javascript');
CodeMirror.defineMIME('application/ecmascript', 'javascript');
CodeMirror.defineMIME('application/json', {
name: 'javascript',
json: true,
});
CodeMirror.defineMIME('application/x-json', {
name: 'javascript',
json: true,
});
CodeMirror.defineMIME('application/ld+json', {
name: 'javascript',
jsonld: true,
});
CodeMirror.defineMIME('text/typescript', {
name: 'javascript',
typescript: true,
});
CodeMirror.defineMIME('application/typescript', {
name: 'javascript',
typescript: true,
});
});

@@ -9,12 +9,12 @@ import progress from 'rollup-plugin-progress';

format: 'iife',
sourcemap: false
sourcemap: false,
},
plugins: [
progress({
clearLine: false
clearLine: false,
}),
filesize()
]
filesize(),
],
};
export default config;

@@ -15,3 +15,3 @@ import { Kampos, effects, noise } from '../index.js';

const AMPLITUDE = 1 / target.width;
const frequency = {x: AMPLITUDE, y: AMPLITUDE};
const frequency = { x: AMPLITUDE, y: AMPLITUDE };

@@ -27,7 +27,7 @@ const octaves = 4;

octaves,
isFractal
isFractal,
});
// init kampos
const instance = new Kampos({target, effects:[turbulence], noSource: true});
const instance = new Kampos({ target, effects: [turbulence], noSource: true });

@@ -37,21 +37,20 @@ // create a simple effect that converts the turbulence return value into the output color

const instance2 = new Kampos({target: target2, effects:[disp]});
const instance2 = new Kampos({ target: target2, effects: [disp] });
// you can increase/decrease the time factor for a faster/slower animation
instance.play(time => turbulence.time = time * 2);
instance.play((time) => (turbulence.time = time * 2));
prepareVideos([media1])
.then(() => {
const width = media1.videoWidth;
const height = media1.videoHeight;
prepareVideos([media1]).then(() => {
const width = media1.videoWidth;
const height = media1.videoHeight;
// set media source
instance2.setSource({media: media1, width, height});
// set media source
instance2.setSource({ media: media1, width, height });
disp.map = target;
disp.scale = {x: 0.15, y: -0.15};
disp.textures[0].update = true; // to update
disp.map = target;
disp.scale = { x: 0.15, y: -0.15 };
disp.textures[0].update = true; // to update
// start kampos
instance2.play();
});
// start kampos
instance2.play();
});

@@ -5,4 +5,4 @@ /*

*/
function loadImage (src) {
return new Promise(resolve => {
function loadImage(src) {
return new Promise((resolve) => {
const img = new Image();

@@ -25,12 +25,12 @@ img.crossOrigin = 'anonymous';

*/
function prepareVideos (videos) {
return new Promise(resolve => {
function prepareVideos(videos) {
return new Promise((resolve) => {
let playing = 0;
let timeupdate = 0;
function canPlay (e) {
function canPlay(e) {
e.target.play();
}
const isPlaying = e => {
const isPlaying = (e) => {
playing += 1;

@@ -48,3 +48,3 @@ e.target.removeEventListener('playing', isPlaying, true);

if (playing === videos.length && timeupdate === videos.length) {
videos.forEach(vid => {
videos.forEach((vid) => {
vid.removeEventListener('canplay', canPlay, true);

@@ -57,3 +57,3 @@ });

videos.forEach(vid => {
videos.forEach((vid) => {
vid.addEventListener('playing', isPlaying, true);

@@ -60,0 +60,0 @@ vid.addEventListener('timeupdate', isTimeupdate, true);

{
"name": "kampos",
"version": "0.10.0",
"description": "Tiny and fast effects compositor on WebGL",
"registry": "https://registry.npmjs.org/",
"main": "dist/index.cjs",
"module": "index.js",
"type": "module",
"types": "types.d.ts",
"scripts": {
"build": "rollup -c rollup.build.js && rollup -c rollup.umd.js",
"watch": "rollup -c rollup.build.js -w",
"demo": "cd demo && rollup -c && cd -",
"watch:demo": "cd demo && rollup -c -w && cd -",
"test:unit": "vitest test/unit/core.js && vitest test/unit/kampos.js",
"test:e2e": "vitest test/e2e/*.js",
"test": "npm run test:unit && npm run test:e2e",
"docs": "documentation build src/index.js -f html -o docs -c documentation.yml",
"check": "npm-check -u",
"start": "npm run build && npm run demo && http-server"
},
"repository": {
"type": "git",
"url": "git+https://github.com/wix-incubator/kampos.git"
},
"keywords": [
"effects",
"media",
"video",
"filters",
"webgl",
"compositor"
],
"author": "Yehonatan Daniv",
"license": "MIT",
"bugs": {
"url": "https://github.com/wix-incubator/kampos/issues"
},
"homepage": "https://wix-incubator.github.io/kampos/",
"devDependencies": {
"@babel/core": "^7.24.7",
"documentation": "^14.0.3",
"finalhandler": "^1.2.0",
"get-port": "^7.1.0",
"gl": "^6.0.2",
"node-canvas-webgl": "^0.3.0",
"npm-check": "^6.0.1",
"pify": "^6.1.0",
"pixelmatch": "^6.0.0",
"pngjs": "^7.0.0",
"puppeteer": "^23.0.2",
"rollup": "^4.18.0",
"rollup-plugin-babel": "^4.4.0",
"rollup-plugin-filesize": "^10.0.0",
"rollup-plugin-progress": "^1.1.2",
"serve-static": "^1.15.0",
"vitest": "^2.0.2"
}
"name": "kampos",
"version": "0.10.1",
"description": "Tiny and fast effects compositor on WebGL",
"registry": "https://registry.npmjs.org/",
"main": "dist/index.cjs",
"module": "index.js",
"type": "module",
"types": "types.d.ts",
"scripts": {
"build": "rollup -c rollup.build.js && rollup -c rollup.umd.js",
"watch": "rollup -c rollup.build.js -w",
"demo": "cd demo && rollup -c && cd -",
"watch:demo": "cd demo && rollup -c -w && cd -",
"test:unit": "vitest test/unit/core.js && vitest test/unit/kampos.js",
"test:e2e": "vitest test/e2e/*.js",
"test": "npm run test:unit && npm run test:e2e",
"docs": "documentation build src/index.js -f html -o docs -c documentation.yml",
"check": "npm-check -u",
"prettier": "prettier --write .",
"start": "npm run build && npm run demo && npx http-server",
"dev": "concurrently \"npm run watch\" \"npm run watch:demo\" \"npx http-server\""
},
"repository": {
"type": "git",
"url": "git+https://github.com/wix-incubator/kampos.git"
},
"keywords": [
"effects",
"media",
"video",
"filters",
"webgl",
"compositor"
],
"author": "Yehonatan Daniv",
"license": "MIT",
"bugs": {
"url": "https://github.com/wix-incubator/kampos/issues"
},
"homepage": "https://wix-incubator.github.io/kampos/",
"devDependencies": {
"@babel/core": "^7.24.7",
"concurrently": "^8.2.2",
"documentation": "^14.0.3",
"finalhandler": "^1.2.0",
"get-port": "^7.1.0",
"gl": "^6.0.2",
"http-server": "^14.1.1",
"node-canvas-webgl": "^0.3.0",
"npm-check": "^6.0.1",
"pify": "^6.1.0",
"pixelmatch": "^6.0.0",
"pngjs": "^7.0.0",
"puppeteer": "^23.0.2",
"rollup": "^4.18.0",
"rollup-plugin-babel": "^4.4.0",
"rollup-plugin-filesize": "^10.0.0",
"rollup-plugin-progress": "^1.1.2",
"serve-static": "^1.15.0",
"vitest": "^2.0.2"
}
}

@@ -6,2 +6,3 @@ <p align="center">

# kampos
### Tiny and fast effects compositor on WebGL

@@ -14,24 +15,31 @@

## Intro
Read the [blog post](https://www.wix.engineering/post/introducing-kampos-a-tiny-and-fast-effects-compositor) introducing kampos on Wix Engineering Blog.
## Posts
CSS-Tricks: [Nailing That Cool Dissolve Transition](https://css-tricks.com/nailing-that-cool-dissolve-transition/)
## Demo
Check out the [live demo](https://wix-incubator.github.io/kampos/demo/).
## Documentation
For API reference and examples, read [the docs](https://wix-incubator.github.io/kampos/docs/).
## Features
* Filter effects for images and videos that you can mix and compose.
* As tiny as **~4KB** (minified and gzipped).
* Core engine for creating and running effects.
* Plugins for effects and transitions - available for import.
* Custom plugins? Extremely easy by using the effects/transitions descriptors DSL.
- Filter effects for images and videos that you can mix and compose.
- As tiny as **~4KB** (minified and gzipped).
- Core engine for creating and running effects.
- Plugins for effects and transitions - available for import.
- Custom plugins? Extremely easy by using the effects/transitions descriptors DSL.
## Usage
Here's a simple example for using kampos:
```javascript
import {Kampos, effects} from 'kampos';
import { Kampos, effects } from 'kampos';

@@ -44,3 +52,3 @@ const target = document.querySelector('canvas');

const kampos = new Kampos({target, effects: [hueSaturation]});
const kampos = new Kampos({ target, effects: [hueSaturation] });

@@ -52,5 +60,7 @@ kampos.setSource(media);

## Getting started
Grab the source from here, or install via package manager.
### npm example:
```bash

@@ -61,7 +71,9 @@ npm install kampos

Import the default build:
```javascript
import {Kampos, Ticker, effects, transitions} from 'kampos';
import { Kampos, Ticker, effects, transitions } from 'kampos';
```
Or take just what you need:
```javascript

@@ -74,2 +86,3 @@ import Kampos from './node_modules/kampos/src/kampos';

## Building locally
```bash

@@ -79,10 +92,14 @@ npm install

```
if npm install fails on node-gyp :
MacOS:
```
brew install pkg-config cairo pango libpng jpeg giflib librsvg pixman
```
[source and other OS](https://github.com/Automattic/node-canvas#compiling)
## Running tests
```bash

@@ -93,5 +110,7 @@ npm run test

## Contributing
Contributions are welcome! (:
## License
kampos is distributed under the MIT license.

@@ -8,10 +8,10 @@ import progress from 'rollup-plugin-progress';

file: 'dist/index.cjs',
format: 'cjs'
format: 'cjs',
},
plugins: [
progress({
clearLine: false
clearLine: false,
}),
filesize()
]
filesize(),
],
};

@@ -10,10 +10,10 @@ import progress from 'rollup-plugin-progress';

format: 'umd',
sourcemap: false
sourcemap: false,
},
plugins: [
progress({
clearLine: false
clearLine: false,
}),
filesize()
]
filesize(),
],
};

@@ -6,3 +6,3 @@ const vertexSimpleTemplate = ({

constant = '',
main = ''
main = '',
}) => `

@@ -27,3 +27,3 @@ precision highp float;

constant = '',
main = ''
main = '',
}) => `

@@ -51,3 +51,3 @@ precision highp float;

main = '',
source = ''
source = '',
}) => `

@@ -73,3 +73,3 @@ precision highp float;

main = '',
source = ''
source = '',
}) => `

@@ -97,3 +97,3 @@ precision highp float;

repeat: 'REPEAT',
mirror: 'MIRRORED_REPEAT'
mirror: 'MIRRORED_REPEAT',
};

@@ -103,3 +103,3 @@

vertex: 'VERTEX',
fragment: 'FRAGMENT'
fragment: 'FRAGMENT',
};

@@ -119,7 +119,6 @@

*/
export function init ({gl, plane, effects, dimensions, noSource}) {
export function init({ gl, plane, effects, dimensions, noSource }) {
const programData = _initProgram(gl, plane, effects, noSource);
return {gl, data: programData, dimensions: dimensions || {}};
return { gl, data: programData, dimensions: dimensions || {} };
}

@@ -138,3 +137,3 @@

*/
export function getWebGLContext (canvas) {
export function getWebGLContext(canvas) {
let context;

@@ -146,3 +145,3 @@

depth: false, // turn off for explicitness - and in some cases perf boost
stencil: false // turn off for explicitness - and in some cases perf boost
stencil: false, // turn off for explicitness - and in some cases perf boost
};

@@ -152,9 +151,7 @@

if ( context ) {
if (context) {
WEBGL_CONTEXT_SUPPORTED = true;
}
else if ( ! WEBGL_CONTEXT_SUPPORTED ) {
} else if (!WEBGL_CONTEXT_SUPPORTED) {
context = canvas.getContext('experimental-webgl', config);
}
else {
} else {
return null;

@@ -174,13 +171,12 @@ }

*/
export function resize (gl, dimensions) {
export function resize(gl, dimensions) {
const canvas = gl.canvas;
const realToCSSPixels = 1; //window.devicePixelRatio;
const {width, height} = dimensions || {};
const { width, height } = dimensions || {};
let displayWidth, displayHeight;
if ( width && height ) {
if (width && height) {
displayWidth = width;
displayHeight = height;
}
else {
} else {
// Lookup the size the browser is displaying the canvas.

@@ -192,7 +188,5 @@ displayWidth = Math.floor(canvas.clientWidth * realToCSSPixels);

// Check if the canvas is not the same size.
if ( canvas.width !== displayWidth ||
canvas.height !== displayHeight ) {
if (canvas.width !== displayWidth || canvas.height !== displayHeight) {
// Make the canvas the same size
canvas.width = displayWidth;
canvas.width = displayWidth;
canvas.height = displayHeight;

@@ -214,7 +208,8 @@ }

*/
export function draw (gl, plane = {}, media, data, dimensions) {
const {program, source, attributes, uniforms, textures, extensions, vao} = data;
const {xSegments = 1, ySegments = 1} = plane;
export function draw(gl, plane = {}, media, data, dimensions) {
const { program, source, attributes, uniforms, textures, extensions, vao } =
data;
const { xSegments = 1, ySegments = 1 } = plane;
if ( media && source && source.texture ) {
if (media && source && source.texture) {
// bind the source texture

@@ -224,3 +219,10 @@ gl.bindTexture(gl.TEXTURE_2D, source.texture);

// read source data into texture
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, media);
gl.texImage2D(
gl.TEXTURE_2D,
0,
gl.RGBA,
gl.RGBA,
gl.UNSIGNED_BYTE,
media,
);
}

@@ -231,6 +233,5 @@

if ( vao ) {
if (vao) {
extensions.vao.bindVertexArrayOES(vao);
}
else {
} else {
// set attribute buffers with data

@@ -245,3 +246,3 @@ _enableVertexAttributes(gl, attributes);

if ( source ) {
if (source) {
gl.activeTexture(startTex);

@@ -252,4 +253,4 @@ gl.bindTexture(gl.TEXTURE_2D, source.texture);

if ( textures ) {
for ( let i = 0; i < textures.length; i++ ) {
if (textures) {
for (let i = 0; i < textures.length; i++) {
gl.activeTexture(startTex + i);

@@ -260,4 +261,11 @@

if ( tex.update ) {
gl.texImage2D(gl.TEXTURE_2D, 0, gl[tex.format], gl[tex.format], gl.UNSIGNED_BYTE, tex.data);
if (tex.update) {
gl.texImage2D(
gl.TEXTURE_2D,
0,
gl[tex.format],
gl[tex.format],
gl.UNSIGNED_BYTE,
tex.data,
);
}

@@ -278,14 +286,20 @@ }

*/
export function destroy (gl, data) {
const {program, vertexShader, fragmentShader, source, attributes, extensions, vao} = data;
export function destroy(gl, data) {
const {
program,
vertexShader,
fragmentShader,
source,
attributes,
extensions,
vao,
} = data;
// delete buffers
(attributes || []).forEach(attr => gl.deleteBuffer(attr.buffer));
(attributes || []).forEach((attr) => gl.deleteBuffer(attr.buffer));
if ( vao )
extensions.vao.deleteVertexArrayOES(vao);
if (vao) extensions.vao.deleteVertexArrayOES(vao);
// delete texture
if ( source && source.texture )
gl.deleteTexture(source.texture);
if (source && source.texture) gl.deleteTexture(source.texture);

@@ -300,9 +314,11 @@ // delete program

function _initProgram (gl, plane, effects, noSource=false) {
const source = noSource ? null : {
texture: createTexture(gl).texture,
buffer: null
};
function _initProgram(gl, plane, effects, noSource = false) {
const source = noSource
? null
: {
texture: createTexture(gl).texture,
buffer: null,
};
if ( source ) {
if (source) {
// flip Y axis for source texture

@@ -314,10 +330,19 @@ gl.bindTexture(gl.TEXTURE_2D, source.texture);

const data = _mergeEffectsData(plane, effects, noSource);
const vertexSrc = _stringifyShaderSrc(data.vertex, noSource ? vertexSimpleTemplate : vertexMediaTemplate);
const fragmentSrc = _stringifyShaderSrc(data.fragment, noSource ? fragmentSimpleTemplate : fragmentMediaTemplate);
const vertexSrc = _stringifyShaderSrc(
data.vertex,
noSource ? vertexSimpleTemplate : vertexMediaTemplate,
);
const fragmentSrc = _stringifyShaderSrc(
data.fragment,
noSource ? fragmentSimpleTemplate : fragmentMediaTemplate,
);
// compile the GLSL program
const {program, vertexShader, fragmentShader, error, type} = _getWebGLProgram(gl, vertexSrc, fragmentSrc);
const { program, vertexShader, fragmentShader, error, type } =
_getWebGLProgram(gl, vertexSrc, fragmentSrc);
if ( error ) {
throw new Error(`${type} error:: ${error}\n${type === SHADER_ERROR_TYPES.fragment ? fragmentSrc : vertexSrc}`);
if (error) {
throw new Error(
`${type} error:: ${error}\n${type === SHADER_ERROR_TYPES.fragment ? fragmentSrc : vertexSrc}`,
);
}

@@ -330,4 +355,3 @@

vaoExt.bindVertexArrayOES(vao);
}
catch (e) {
} catch (e) {
// ignore

@@ -339,3 +363,3 @@ }

if ( vao ) {
if (vao) {
_enableVertexAttributes(gl, attributes);

@@ -350,3 +374,3 @@ vaoExt.bindVertexArrayOES(null);

extensions: {
vao: vaoExt
vao: vaoExt,
},

@@ -360,61 +384,80 @@ program,

textures: data.textures,
vao
vao,
};
}
function _mergeEffectsData (plane, effects, noSource= false) {
return effects.reduce((result, config) => {
const {attributes = [], uniforms = [], textures = [], varying = {}} = config;
const merge = shader => Object.keys(config[shader] || {}).forEach(key => {
if ( key === 'constant' || key === 'main' || key === 'source' ) {
result[shader][key] += config[shader][key] + '\n';
}
else {
result[shader][key] = {...result[shader][key], ...config[shader][key]};
}
});
function _mergeEffectsData(plane, effects, noSource = false) {
return effects.reduce(
(result, config) => {
const {
attributes = [],
uniforms = [],
textures = [],
varying = {},
} = config;
const merge = (shader) =>
Object.keys(config[shader] || {}).forEach((key) => {
if (
key === 'constant' ||
key === 'main' ||
key === 'source'
) {
result[shader][key] += config[shader][key] + '\n';
} else {
result[shader][key] = {
...result[shader][key],
...config[shader][key],
};
}
});
merge('vertex');
merge('fragment');
merge('vertex');
merge('fragment');
attributes.forEach(attribute => {
const found = result.attributes.some((attr) => {
if ( attr.name === attribute.name ) {
Object.assign(attr, attribute);
return true;
attributes.forEach((attribute) => {
const found = result.attributes.some((attr) => {
if (attr.name === attribute.name) {
Object.assign(attr, attribute);
return true;
}
});
if (!found) {
result.attributes.push(attribute);
}
});
if ( ! found ) {
result.attributes.push(attribute);
}
});
result.attributes.forEach((attr) => {
if (attr.extends) {
const found = result.attributes.some((attrToExtend) => {
if (attrToExtend.name === attr.extends) {
Object.assign(attr, attrToExtend, {
name: attr.name,
});
return true;
}
});
result.attributes.forEach((attr) => {
if ( attr.extends ) {
const found = result.attributes.some(attrToExtend => {
if ( attrToExtend.name === attr.extends ) {
Object.assign(attr, attrToExtend, {name: attr.name});
return true;
if (!found) {
throw new Error(
`Could not find attribute ${attr.extends} to extend`,
);
}
});
if ( !found ) {
throw new Error(`Could not find attribute ${attr.extends} to extend`);
}
}
});
});
result.uniforms.push(...uniforms);
result.textures.push(...textures);
result.uniforms.push(...uniforms);
result.textures.push(...textures);
Object.assign(result.vertex.varying, varying);
Object.assign(result.fragment.varying, varying);
Object.assign(result.vertex.varying, varying);
Object.assign(result.fragment.varying, varying);
return result;
}, getEffectDefaults(plane, noSource));
return result;
},
getEffectDefaults(plane, noSource),
);
}
function _getPlaneCoords({xEnd, yEnd, factor}, plane = {}) {
const {xSegments = 1, ySegments = 1} = plane;
function _getPlaneCoords({ xEnd, yEnd, factor }, plane = {}) {
const { xSegments = 1, ySegments = 1 } = plane;
const result = [];

@@ -426,29 +469,29 @@

result.push(
xEnd * i / xSegments - factor,
yEnd * j / ySegments - factor
(xEnd * i) / xSegments - factor,
(yEnd * j) / ySegments - factor,
);
/* B */
result.push(
xEnd * i / xSegments - factor,
yEnd * (j + 1) / ySegments - factor
(xEnd * i) / xSegments - factor,
(yEnd * (j + 1)) / ySegments - factor,
);
/* C */
result.push(
xEnd * (i + 1) / xSegments - factor,
yEnd * j / ySegments - factor
(xEnd * (i + 1)) / xSegments - factor,
(yEnd * j) / ySegments - factor,
);
/* D */
result.push(
xEnd * (i + 1) / xSegments - factor,
yEnd * j / ySegments - factor
(xEnd * (i + 1)) / xSegments - factor,
(yEnd * j) / ySegments - factor,
);
/* E */
result.push(
xEnd * i / xSegments - factor,
yEnd * (j + 1) / ySegments - factor
(xEnd * i) / xSegments - factor,
(yEnd * (j + 1)) / ySegments - factor,
);
/* F */
result.push(
xEnd * (i + 1) / xSegments - factor,
yEnd * (j + 1) / ySegments - factor
(xEnd * (i + 1)) / xSegments - factor,
(yEnd * (j + 1)) / ySegments - factor,
);

@@ -461,13 +504,15 @@ }

function getEffectDefaults (plane, noSource) {
function getEffectDefaults(plane, noSource) {
/*
* Default uniforms
*/
const uniforms = noSource ? [] : [
{
name: 'u_source',
type: 'i',
data: [0]
}
];
const uniforms = noSource
? []
: [
{
name: 'u_source',
type: 'i',
data: [0],
},
];

@@ -480,14 +525,18 @@ /*

name: 'a_position',
data: new Float32Array(_getPlaneCoords({xEnd: 2, yEnd: 2, factor: 1}, plane)),
data: new Float32Array(
_getPlaneCoords({ xEnd: 2, yEnd: 2, factor: 1 }, plane),
),
size: 2,
type: 'FLOAT'
}
type: 'FLOAT',
},
];
if ( ! noSource ) {
if (!noSource) {
attributes.push({
name: 'a_texCoord',
data: new Float32Array(_getPlaneCoords({xEnd: 1, yEnd: 1, factor: 0}, plane)),
data: new Float32Array(
_getPlaneCoords({ xEnd: 1, yEnd: 1, factor: 0 }, plane),
),
size: 2,
type: 'FLOAT'
type: 'FLOAT',
});

@@ -502,3 +551,3 @@ }

constant: '',
main: ''
main: '',
},

@@ -510,3 +559,3 @@ fragment: {

main: '',
source: ''
source: '',
},

@@ -518,22 +567,19 @@ attributes,

*/
textures: []
textures: [],
};
}
function _stringifyShaderSrc (data, template) {
const templateData = Object.entries(data)
.reduce((result, [key, value]) => {
if ( ['uniform', 'attribute', 'varying'].includes(key) ) {
result[key] = Object.entries(value)
.reduce((str, [name, type]) =>
str + `${key} ${type} ${name};\n`,
''
);
}
else {
result[key] = value;
}
function _stringifyShaderSrc(data, template) {
const templateData = Object.entries(data).reduce((result, [key, value]) => {
if (['uniform', 'attribute', 'varying'].includes(key)) {
result[key] = Object.entries(value).reduce(
(str, [name, type]) => str + `${key} ${type} ${name};\n`,
'',
);
} else {
result[key] = value;
}
return result;
}, {});
return result;
}, {});

@@ -543,11 +589,11 @@ return template(templateData);

function _getWebGLProgram (gl, vertexSrc, fragmentSrc) {
function _getWebGLProgram(gl, vertexSrc, fragmentSrc) {
const vertexShader = _createShader(gl, gl.VERTEX_SHADER, vertexSrc);
const fragmentShader = _createShader(gl, gl.FRAGMENT_SHADER, fragmentSrc);
if ( vertexShader.error ) {
if (vertexShader.error) {
return vertexShader;
}
if ( fragmentShader.error ) {
if (fragmentShader.error) {
return fragmentShader;

@@ -559,3 +605,3 @@ }

function _createProgram (gl, vertexShader, fragmentShader) {
function _createProgram(gl, vertexShader, fragmentShader) {
const program = gl.createProgram();

@@ -569,4 +615,4 @@

if ( success ) {
return {program, vertexShader, fragmentShader};
if (success) {
return { program, vertexShader, fragmentShader };
}

@@ -576,3 +622,3 @@

error: gl.getProgramInfoLog(program),
type: 'program'
type: 'program',
};

@@ -585,3 +631,3 @@

function _createShader (gl, type, source) {
function _createShader(gl, type, source) {
const shader = gl.createShader(type);

@@ -594,3 +640,3 @@

if ( success ) {
if (success) {
return shader;

@@ -601,3 +647,6 @@ }

error: gl.getShaderInfoLog(shader),
type: type === gl.VERTEX_SHADER ? SHADER_ERROR_TYPES.vertex : SHADER_ERROR_TYPES.fragment
type:
type === gl.VERTEX_SHADER
? SHADER_ERROR_TYPES.vertex
: SHADER_ERROR_TYPES.fragment,
};

@@ -623,3 +672,12 @@

*/
export function createTexture (gl, {width=1, height=1, data=null, format='RGBA', wrap='stretch'}={}) {
export function createTexture(
gl,
{
width = 1,
height = 1,
data = null,
format = 'RGBA',
wrap = 'stretch',
} = {},
) {
const texture = gl.createTexture();

@@ -630,20 +688,44 @@

// Set the parameters so we can render any size image
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl[_getTextureWrap(wrap.x || wrap)]);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl[_getTextureWrap(wrap.y || wrap)]);
gl.texParameteri(
gl.TEXTURE_2D,
gl.TEXTURE_WRAP_S,
gl[_getTextureWrap(wrap.x || wrap)],
);
gl.texParameteri(
gl.TEXTURE_2D,
gl.TEXTURE_WRAP_T,
gl[_getTextureWrap(wrap.y || wrap)],
);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
if ( data ) {
if (data) {
// Upload the image into the texture
gl.texImage2D(gl.TEXTURE_2D, 0,gl[format], gl[format], gl.UNSIGNED_BYTE, data);
}
else {
gl.texImage2D(
gl.TEXTURE_2D,
0,
gl[format],
gl[format],
gl.UNSIGNED_BYTE,
data,
);
} else {
// Create empty texture
gl.texImage2D(gl.TEXTURE_2D, 0, gl[format], width, height, 0, gl[format], gl.UNSIGNED_BYTE, null);
gl.texImage2D(
gl.TEXTURE_2D,
0,
gl[format],
width,
height,
0,
gl[format],
gl.UNSIGNED_BYTE,
null,
);
}
return {texture, width, height, format};
return { texture, width, height, format };
}
function _createBuffer (gl, program, name, data) {
function _createBuffer(gl, program, name, data) {
const location = gl.getAttribLocation(program, name);

@@ -655,8 +737,13 @@ const buffer = gl.createBuffer();

return {location, buffer};
return { location, buffer };
}
function _initVertexAttributes (gl, program, data) {
return (data || []).map(attr => {
const {location, buffer} = _createBuffer(gl, program, attr.name, attr.data);
function _initVertexAttributes(gl, program, data) {
return (data || []).map((attr) => {
const { location, buffer } = _createBuffer(
gl,
program,
attr.name,
attr.data,
);

@@ -668,3 +755,3 @@ return {

type: attr.type,
size: attr.size
size: attr.size,
};

@@ -674,4 +761,4 @@ });

function _initUniforms (gl, program, uniforms) {
return (uniforms || []).map(uniform => {
function _initUniforms(gl, program, uniforms) {
return (uniforms || []).map((uniform) => {
const location = gl.getUniformLocation(program, uniform.name);

@@ -683,3 +770,3 @@

type: uniform.type,
data: uniform.data
data: uniform.data,
};

@@ -689,7 +776,7 @@ });

function _setUniforms (gl, uniformData) {
(uniformData || []).forEach(uniform => {
let {size, type, location, data} = uniform;
function _setUniforms(gl, uniformData) {
(uniformData || []).forEach((uniform) => {
let { size, type, location, data } = uniform;
if ( type === 'i' ) {
if (type === 'i') {
data = new Int32Array(data);

@@ -702,5 +789,5 @@ }

function _enableVertexAttributes (gl, attributes) {
(attributes || []).forEach(attrib => {
const {location, buffer, size, type} = attrib;
function _enableVertexAttributes(gl, attributes) {
(attributes || []).forEach((attrib) => {
const { location, buffer, size, type } = attrib;

@@ -713,3 +800,3 @@ gl.enableVertexAttribArray(location);

function _getTextureWrap (key) {
function _getTextureWrap(key) {
return TEXTURE_WRAP[key] || TEXTURE_WRAP['stretch'];

@@ -716,0 +803,0 @@ }

@@ -9,3 +9,3 @@ /**

*/
export default function ({isLuminance = false} = {}) {
export default function ({ isLuminance = false } = {}) {
/**

@@ -28,6 +28,6 @@ * @typedef {Object} alphaMaskEffect

attribute: {
a_alphaMaskTexCoord: 'vec2'
a_alphaMaskTexCoord: 'vec2',
},
main: `
v_alphaMaskTexCoord = a_alphaMaskTexCoord;`
v_alphaMaskTexCoord = a_alphaMaskTexCoord;`,
},

@@ -38,3 +38,3 @@ fragment: {

u_alphaMaskIsLuminance: 'bool',
u_mask: 'sampler2D'
u_mask: 'sampler2D',
},

@@ -51,20 +51,20 @@ main: `

}
}`
}`,
},
get disabled () {
get disabled() {
return !this.uniforms[0].data[0];
},
set disabled (b) {
set disabled(b) {
this.uniforms[0].data[0] = +!b;
},
get mask () {
get mask() {
return this.textures[0].data;
},
set mask (img) {
set mask(img) {
this.textures[0].data = img;
},
get isLuminance () {
get isLuminance() {
return !!this.uniforms[2].data[0];
},
set isLuminance (toggle) {
set isLuminance(toggle) {
this.uniforms[2].data[0] = +toggle;

@@ -74,3 +74,3 @@ this.textures[0].format = toggle ? 'RGBA' : 'ALPHA';

varying: {
v_alphaMaskTexCoord: 'vec2'
v_alphaMaskTexCoord: 'vec2',
},

@@ -81,3 +81,3 @@ uniforms: [

type: 'i',
data: [1]
data: [1],
},

@@ -87,3 +87,3 @@ {

type: 'i',
data: [1]
data: [1],
},

@@ -93,4 +93,4 @@ {

type: 'i',
data: [+!!isLuminance]
}
data: [+!!isLuminance],
},
],

@@ -100,11 +100,11 @@ attributes: [

name: 'a_alphaMaskTexCoord',
extends: 'a_texCoord'
}
extends: 'a_texCoord',
},
],
textures: [
{
format: isLuminance ? 'RGBA' : 'ALPHA'
}
]
format: isLuminance ? 'RGBA' : 'ALPHA',
},
],
};
};
}

@@ -100,3 +100,3 @@ const MODES_AUX = {

return vec3(r, g, b);
}`
}`,
};

@@ -180,4 +180,4 @@

function generateBlendVector (name) {
return `vec3(${name}(backdrop.r, source.r), ${name}(backdrop.g, source.g), ${name}(backdrop.b, source.b))`
function generateBlendVector(name) {
return `vec3(${name}(backdrop.r, source.r), ${name}(backdrop.g, source.g), ${name}(backdrop.b, source.b))`;
}

@@ -199,5 +199,6 @@

hue: 'blend_set_luminosity(blend_set_saturation(source, blend_saturation(backdrop)), blend_luminosity(backdrop))',
saturation: 'blend_set_luminosity(blend_set_saturation(backdrop, blend_saturation(source)), blend_luminosity(backdrop))',
saturation:
'blend_set_luminosity(blend_set_saturation(backdrop, blend_saturation(source)), blend_luminosity(backdrop))',
color: 'blend_set_luminosity(source, blend_luminosity(backdrop))',
luminosity: 'blend_set_luminosity(backdrop, blend_luminosity(source))'
luminosity: 'blend_set_luminosity(backdrop, blend_luminosity(source))',
};

@@ -215,3 +216,3 @@

mode = 'normal',
color = [0.0, 0.0, 0.0, 1.0]
color = [0.0, 0.0, 0.0, 1.0],
} = {}) {

@@ -233,6 +234,6 @@ /**

attribute: {
a_blendImageTexCoord: 'vec2'
a_blendImageTexCoord: 'vec2',
},
main: `
v_blendImageTexCoord = a_blendImageTexCoord;`
v_blendImageTexCoord = a_blendImageTexCoord;`,
},

@@ -274,12 +275,11 @@ fragment: {

alpha = alpha + backdropAlpha * (1.0 - alpha);
}`
}`,
},
get color () {
get color() {
return this.uniforms[1].data.slice(0);
},
set color (l) {
set color(l) {
if (!l || !l.length) {
this.uniforms[2].data[0] = 0;
}
else {
} else {
this.uniforms[2].data[0] = 1;

@@ -293,22 +293,21 @@ l.forEach((c, i) => {

},
get image () {
get image() {
return this.textures[0].data;
},
set image (img) {
set image(img) {
if (img) {
this.uniforms[4].data[0] = 1;
this.textures[0].data = img;
}
else {
} else {
this.uniforms[4].data[0] = 0;
}
},
get disabled () {
get disabled() {
return !this.uniforms[0].data[0];
},
set disabled (b) {
set disabled(b) {
this.uniforms[0].data[0] = +!b;
},
varying: {
v_blendImageTexCoord: 'vec2'
v_blendImageTexCoord: 'vec2',
},

@@ -319,3 +318,3 @@ uniforms: [

type: 'i',
data: [1]
data: [1],
},

@@ -325,3 +324,3 @@ {

type: 'f',
data: color
data: color,
},

@@ -331,3 +330,3 @@ {

type: 'i',
data: [1]
data: [1],
},

@@ -337,3 +336,3 @@ {

type: 'i',
data: [1]
data: [1],
},

@@ -343,4 +342,4 @@ {

type: 'i',
data: [0]
}
data: [0],
},
],

@@ -350,11 +349,11 @@ attributes: [

name: 'a_blendImageTexCoord',
extends: 'a_texCoord'
}
extends: 'a_texCoord',
},
],
textures: [
{
format: 'RGBA'
}
]
format: 'RGBA',
},
],
};
};
}

@@ -12,3 +12,3 @@ /**

*/
export default function ({brightness = 1.0, contrast = 1.0} = {}) {
export default function ({ brightness = 1.0, contrast = 1.0 } = {}) {
/**

@@ -32,3 +32,3 @@ * @typedef {Object} brightnessContrastEffect

u_contrast: 'float',
u_brightness: 'float'
u_brightness: 'float',
},

@@ -45,26 +45,26 @@ constant: 'const vec3 half3 = vec3(0.5);',

color = clamp(color, 0.0, 1.0);`
color = clamp(color, 0.0, 1.0);`,
},
get brightness () {
get brightness() {
return this.uniforms[2].data[0];
},
set brightness (value) {
set brightness(value) {
this.uniforms[2].data[0] = parseFloat(Math.max(0, value));
},
get contrast () {
get contrast() {
return this.uniforms[3].data[0];
},
set contrast (value) {
set contrast(value) {
this.uniforms[3].data[0] = parseFloat(Math.max(0, value));
},
get brightnessDisabled () {
get brightnessDisabled() {
return !this.uniforms[0].data[0];
},
set brightnessDisabled (toggle) {
set brightnessDisabled(toggle) {
this.uniforms[0].data[0] = +!toggle;
},
get contrastDisabled () {
get contrastDisabled() {
return !this.uniforms[1].data[0];
},
set contrastDisabled (toggle) {
set contrastDisabled(toggle) {
this.uniforms[1].data[0] = +!toggle;

@@ -76,3 +76,3 @@ },

type: 'i',
data: [1]
data: [1],
},

@@ -82,3 +82,3 @@ {

type: 'i',
data: [1]
data: [1],
},

@@ -88,3 +88,3 @@ {

type: 'f',
data: [brightness]
data: [brightness],
},

@@ -94,6 +94,6 @@ {

type: 'f',
data: [contrast]
}
]
data: [contrast],
},
],
};
};
}

@@ -13,7 +13,4 @@ /**

*/
function displacement ({
wrap = WRAP_METHODS.CLAMP,
scale
} = {}) {
const { x: sx, y: sy } = (scale || { x: 0.0, y: 0.0 });
function displacement({ wrap = WRAP_METHODS.CLAMP, scale } = {}) {
const { x: sx, y: sy } = scale || { x: 0.0, y: 0.0 };

@@ -35,6 +32,6 @@ /**

attribute: {
a_displacementMapTexCoord: 'vec2'
a_displacementMapTexCoord: 'vec2',
},
main: `
v_displacementMapTexCoord = a_displacementMapTexCoord;`
v_displacementMapTexCoord = a_displacementMapTexCoord;`,
},

@@ -45,3 +42,3 @@ fragment: {

u_dispMap: 'sampler2D',
u_dispScale: 'vec2'
u_dispScale: 'vec2',
},

@@ -54,28 +51,26 @@ source: `

sourceCoord = dispVec;
}`
}`,
},
get disabled () {
get disabled() {
return !this.uniforms[0].data[0];
},
set disabled (b) {
set disabled(b) {
this.uniforms[0].data[0] = +!b;
},
get scale () {
get scale() {
const [x, y] = this.uniforms[2].data;
return {x, y};
return { x, y };
},
set scale ({x, y}) {
if ( typeof x !== 'undefined' )
this.uniforms[2].data[0] = x;
if ( typeof y !== 'undefined' )
this.uniforms[2].data[1] = y;
set scale({ x, y }) {
if (typeof x !== 'undefined') this.uniforms[2].data[0] = x;
if (typeof y !== 'undefined') this.uniforms[2].data[1] = y;
},
get map () {
get map() {
return this.textures[0].data;
},
set map (img) {
set map(img) {
this.textures[0].data = img;
},
varying: {
v_displacementMapTexCoord: 'vec2'
v_displacementMapTexCoord: 'vec2',
},

@@ -86,3 +81,3 @@ uniforms: [

type: 'i',
data: [1]
data: [1],
},

@@ -92,3 +87,3 @@ {

type: 'i',
data: [1]
data: [1],
},

@@ -98,4 +93,4 @@ {

type: 'f',
data: [sx, sy]
}
data: [sx, sy],
},
],

@@ -105,17 +100,17 @@ attributes: [

name: 'a_displacementMapTexCoord',
extends: 'a_texCoord'
}
extends: 'a_texCoord',
},
],
textures: [
{
format: 'RGB'
}
]
format: 'RGB',
},
],
};
}
const WRAP_METHODS = {
const WRAP_METHODS = {
CLAMP: `dispVec = clamp(dispVec, 0.0, 1.0);`,
DISCARD: `if (dispVec.x < 0.0 || dispVec.x > 1.0 || dispVec.y > 1.0 || dispVec.y < 0.0) { discard; }`,
WRAP: `dispVec = mod(dispVec, 1.0);`
WRAP: `dispVec = mod(dispVec, 1.0);`,
};

@@ -122,0 +117,0 @@

@@ -12,4 +12,4 @@ /**

dark = [0.7411764706, 0.0431372549, 0.568627451, 1],
light = [0.9882352941, 0.7333333333, 0.05098039216, 1]
} = {}) {
light = [0.9882352941, 0.7333333333, 0.05098039216, 1],
} = {}) {
/**

@@ -30,3 +30,3 @@ * @typedef {Object} duotoneEffect

u_light: 'vec4',
u_dark: 'vec4'
u_dark: 'vec4',
},

@@ -37,10 +37,10 @@ main: `

color = mix(u_dark.rgb, u_light.rgb, gray);
}`
}`,
},
get light () {
get light() {
return this.uniforms[1].data.slice(0);
},
set light (l) {
set light(l) {
l.forEach((c, i) => {
if ( ! Number.isNaN(c) ) {
if (!Number.isNaN(c)) {
this.uniforms[1].data[i] = c;

@@ -50,8 +50,8 @@ }

},
get dark () {
get dark() {
return this.uniforms[2].data.slice(0);
},
set dark (d) {
set dark(d) {
d.forEach((c, i) => {
if ( ! Number.isNaN(c) ) {
if (!Number.isNaN(c)) {
this.uniforms[2].data[i] = c;

@@ -61,6 +61,6 @@ }

},
get disabled () {
get disabled() {
return !this.uniforms[0].data[0];
},
set disabled (b) {
set disabled(b) {
this.uniforms[0].data[0] = +!b;

@@ -72,3 +72,3 @@ },

type: 'i',
data: [1]
data: [1],
},

@@ -78,3 +78,3 @@ {

type: 'f',
data: light
data: light,
},

@@ -84,6 +84,6 @@ {

type: 'f',
data: dark
}
]
data: dark,
},
],
};
};
}

@@ -11,3 +11,3 @@ /**

*/
export default function ({hue = 0.0, saturation = 1.0} = {}) {
export default function ({ hue = 0.0, saturation = 1.0 } = {}) {
/**

@@ -28,3 +28,3 @@ * @typedef {Object} hueSaturationEffect

u_hue: 'float',
u_saturation: 'float'
u_saturation: 'float',
},

@@ -56,3 +56,3 @@ // for implementation see: https://www.w3.org/TR/SVG11/filters.html#feColorMatrixElement

v_hueRotation = lummat + cos(angle) * cosmat + sin(angle) * sinmat;
v_saturation = lummat + satmat * u_saturation;`
v_saturation = lummat + satmat * u_saturation;`,
},

@@ -64,3 +64,3 @@ fragment: {

u_hue: 'float',
u_saturation: 'float'
u_saturation: 'float',
},

@@ -84,31 +84,31 @@ main: `

color = clamp(color, 0.0, 1.0);`
color = clamp(color, 0.0, 1.0);`,
},
varying: {
v_hueRotation: 'mat3',
v_saturation: 'mat3'
v_saturation: 'mat3',
},
get hue () {
get hue() {
return this.uniforms[2].data[0];
},
set hue (h) {
set hue(h) {
this.uniforms[2].data[0] = parseFloat(h);
},
get saturation () {
get saturation() {
return this.uniforms[3].data[0];
},
set saturation (s) {
set saturation(s) {
this.uniforms[3].data[0] = parseFloat(Math.max(0, s));
},
get hueDisabled () {
get hueDisabled() {
return !this.uniforms[0].data[0];
},
set hueDisabled (b) {
set hueDisabled(b) {
this.uniforms[0].data[0] = +!b;
},
get saturationDisabled () {
get saturationDisabled() {
return !this.uniforms[1].data[0];
},
set saturationDisabled (b) {
set saturationDisabled(b) {
this.uniforms[1].data[0] = +!b;

@@ -120,3 +120,3 @@ },

type: 'i',
data: [1]
data: [1],
},

@@ -126,3 +126,3 @@ {

type: 'i',
data: [1]
data: [1],
},

@@ -132,3 +132,3 @@ {

type: 'f',
data: [hue]
data: [hue],
},

@@ -138,6 +138,6 @@ {

type: 'f',
data: [saturation]
}
]
data: [saturation],
},
],
};
};
}

@@ -10,6 +10,3 @@ /**

*/
export default function ({
segments = 6,
offset = 0
} = {}) {
export default function ({ segments = 6, offset = 0 } = {}) {
/**

@@ -30,3 +27,3 @@ * @typedef {Object} kaleidoscopeEffect

u_segments: 'float',
u_offset: 'float'
u_offset: 'float',
},

@@ -43,20 +40,20 @@ constant: `const float PI = ${Math.PI};`,

sourceCoord = mod(newCoords - u_offset, 1.0);
}`
}`,
},
get segments () {
get segments() {
return this.uniforms[1].data[0];
},
set segments (n) {
set segments(n) {
this.uniforms[1].data[0] = +n;
},
get offset () {
get offset() {
return this.uniforms[2].data[0];
},
set offset (o) {
set offset(o) {
this.uniforms[2].data[0] = +o;
},
get disabled () {
get disabled() {
return !this.uniforms[0].data[0];
},
set disabled (b) {
set disabled(b) {
this.uniforms[0].data[0] = +!b;

@@ -68,3 +65,3 @@ },

type: 'i',
data: [1]
data: [1],
},

@@ -74,3 +71,3 @@ {

type: 'f',
data: [segments]
data: [segments],
},

@@ -80,6 +77,6 @@ {

type: 'f',
data: [offset]
}
]
data: [offset],
},
],
};
};
}

@@ -16,11 +16,11 @@ /**

*/
function turbulence ({
function turbulence({
noise,
output= OUTPUT_TYPES.COLOR,
output = OUTPUT_TYPES.COLOR,
frequency,
octaves = 1,
isFractal= false,
time = 0.0
isFractal = false,
time = 0.0,
}) {
const { x: fx, y: fy } = (frequency || { x: 0.0, y: 0.0 });
const { x: fx, y: fy } = frequency || { x: 0.0, y: 0.0 };

@@ -48,3 +48,3 @@ /**

u_isFractal: 'bool',
u_time: 'float'
u_time: 'float',
},

@@ -89,30 +89,28 @@ constant: `

float turbulenceValue = turbulence(turbulenceSeed, u_turbulenceFrequency, u_turbulenceOctaves, u_isFractal);
${output || ''}`
${output || ''}`,
},
get frequency () {
get frequency() {
const [x, y] = this.uniforms[0].data;
return {x, y};
return { x, y };
},
set frequency ({x, y}) {
if ( typeof x !== 'undefined' )
this.uniforms[0].data[0] = x;
if ( typeof y !== 'undefined' )
this.uniforms[0].data[1] = y;
set frequency({ x, y }) {
if (typeof x !== 'undefined') this.uniforms[0].data[0] = x;
if (typeof y !== 'undefined') this.uniforms[0].data[1] = y;
},
get octaves () {
get octaves() {
return this.uniforms[1].data[0];
},
set octaves (value) {
set octaves(value) {
this.uniforms[1].data[0] = Math.max(0, parseInt(value));
},
get isFractal () {
get isFractal() {
return !!this.uniforms[2].data[0];
},
set isFractal (toggle) {
set isFractal(toggle) {
this.uniforms[2].data[0] = +toggle;
},
get time () {
get time() {
return this.uniforms[3].data[0];
},
set time (value) {
set time(value) {
this.uniforms[3].data[0] = Math.max(0, parseFloat(value));

@@ -124,3 +122,3 @@ },

type: 'f',
data: [fx, fy]
data: [fx, fy],
},

@@ -130,3 +128,3 @@ {

type: 'i',
data: [octaves]
data: [octaves],
},

@@ -136,3 +134,3 @@ {

type: 'i',
data: [+!!isFractal]
data: [+!!isFractal],
},

@@ -142,5 +140,5 @@ {

type: 'f',
data: [time]
}
]
data: [time],
},
],
};

@@ -151,4 +149,4 @@ }

COLOR: 'color = vec3(turbulenceValue);',
ALPHA: 'alpha = turbulenceValue;'
}
ALPHA: 'alpha = turbulenceValue;',
};

@@ -155,0 +153,0 @@ turbulence.COLOR = OUTPUT_TYPES.COLOR;

@@ -19,8 +19,8 @@ import * as core from './core.js';

*/
constructor (config) {
if ( ! config || ! config.target ) {
constructor(config) {
if (!config || !config.target) {
throw new Error('A target canvas was not provided');
}
if ( Kampos.preventContextCreation )
if (Kampos.preventContextCreation)
throw new Error('Context creation is prevented');

@@ -31,3 +31,3 @@

if ( config && config.onContextCreationError ) {
if (config && config.onContextCreationError) {
config.onContextCreationError.call(this, config);

@@ -37,8 +37,11 @@ }

config.target.addEventListener('webglcontextcreationerror', this._contextCreationError, false);
config.target.addEventListener(
'webglcontextcreationerror',
this._contextCreationError,
false,
);
const success = this.init(config);
if ( ! success )
throw new Error('Could not create context');
if (!success) throw new Error('Could not create context');

@@ -48,10 +51,13 @@ this._restoreContext = (e) => {

this.config.target.removeEventListener('webglcontextrestored', this._restoreContext, true);
this.config.target.removeEventListener(
'webglcontextrestored',
this._restoreContext,
true,
);
const success = this.init();
if ( ! success )
return false;
if (!success) return false;
if ( this._source ) {
if (this._source) {
this.setSource(this._source);

@@ -62,3 +68,3 @@ }

if ( config && config.onContextRestored ) {
if (config && config.onContextRestored) {
config.onContextRestored.call(this, config);

@@ -73,11 +79,14 @@ }

if ( this.gl && this.gl.isContextLost() ) {
if (this.gl && this.gl.isContextLost()) {
this.lostContext = true;
this.config.target.addEventListener('webglcontextrestored', this._restoreContext, true);
this.config.target.addEventListener(
'webglcontextrestored',
this._restoreContext,
true,
);
this.destroy(true);
if ( config && config.onContextLost ) {
if (config && config.onContextLost) {
config.onContextLost.call(this, config);

@@ -88,3 +97,7 @@ }

this.config.target.addEventListener('webglcontextlost', this._loseContext, true);
this.config.target.addEventListener(
'webglcontextlost',
this._loseContext,
true,
);
}

@@ -101,8 +114,7 @@

*/
init (config) {
init(config) {
config = config || this.config;
let {target, plane, effects, ticker, noSource} = config;
let { target, plane, effects, ticker, noSource } = config;
if ( Kampos.preventContextCreation )
return false;
if (Kampos.preventContextCreation) return false;

@@ -113,10 +125,8 @@ this.lostContext = false;

if ( ! gl )
return false;
if (!gl) return false;
if ( gl.isContextLost() ) {
if (gl.isContextLost()) {
const success = this.restoreContext();
if ( ! success )
return false;
if (!success) return false;

@@ -126,17 +136,23 @@ // get new context from the fresh clone

if ( ! gl )
return false;
if (!gl) return false;
}
const {x: xSegments = 1, y: ySegments = 1} = plane && plane.segments
? typeof plane.segments === 'object'
? plane.segments
: {x: plane.segments, y: plane.segments}
: {};
const { x: xSegments = 1, y: ySegments = 1 } =
plane && plane.segments
? typeof plane.segments === 'object'
? plane.segments
: { x: plane.segments, y: plane.segments }
: {};
this.plane = {
xSegments,
ySegments
ySegments,
};
const {data} = core.init({gl, plane: this.plane, effects, dimensions: this.dimensions, noSource});
const { data } = core.init({
gl,
plane: this.plane,
effects,
dimensions: this.dimensions,
noSource,
});

@@ -149,3 +165,3 @@ this.gl = gl;

if ( ticker ) {
if (ticker) {
this.ticker = ticker;

@@ -167,9 +183,9 @@ ticker.add(this);

*/
setSource (source, skipTextureCreation) {
if ( ! source ) return;
setSource(source, skipTextureCreation) {
if (!source) return;
if ( this.lostContext ) {
if (this.lostContext) {
const success = this.restoreContext();
if ( ! success ) return;
if (!success) return;
}

@@ -179,10 +195,9 @@

if ( Object.prototype.toString.call(source) === '[object Object]' ) {
({media, width, height} = source);
}
else {
if (Object.prototype.toString.call(source) === '[object Object]') {
({ media, width, height } = source);
} else {
media = source;
}
if ( width && height ) {
if (width && height) {
this.dimensions = { width, height };

@@ -194,3 +209,3 @@ }

if ( ! skipTextureCreation ) {
if (!skipTextureCreation) {
this._createTextures();

@@ -207,7 +222,7 @@ }

*/
draw (time) {
if ( this.lostContext ) {
draw(time) {
if (this.lostContext) {
const success = this.restoreContext();
if ( ! success ) return;
if (!success) return;
}

@@ -217,4 +232,3 @@

if ( cb && cb(time) === false )
return;
if (cb && cb(time) === false) return;

@@ -236,3 +250,3 @@ core.draw(this.gl, this.plane, this.media, this.data, this.dimensions);

*/
play (beforeDraw, afterDraw) {
play(beforeDraw, afterDraw) {
if (typeof beforeDraw === 'function') {

@@ -245,13 +259,12 @@ this.config.beforeDraw = beforeDraw;

if ( this.ticker ) {
if ( this.animationFrameId ) {
if (this.ticker) {
if (this.animationFrameId) {
this.stop();
}
if ( ! this.playing ) {
if (!this.playing) {
this.playing = true;
this.ticker.add(this);
}
}
else if ( ! this.animationFrameId ) {
} else if (!this.animationFrameId) {
const loop = (time) => {

@@ -264,3 +277,2 @@ this.animationFrameId = window.requestAnimationFrame(loop);

}
}

@@ -273,4 +285,4 @@

*/
stop () {
if ( this.animationFrameId ) {
stop() {
if (this.animationFrameId) {
window.cancelAnimationFrame(this.animationFrameId);

@@ -280,3 +292,3 @@ this.animationFrameId = null;

if ( this.playing ) {
if (this.playing) {
this.playing = false;

@@ -292,10 +304,10 @@ this.ticker.remove(this);

*/
destroy (keepState) {
destroy(keepState) {
this.stop();
if ( this.gl && this.data ) {
if (this.gl && this.data) {
core.destroy(this.gl, this.data);
}
if ( keepState ) {
if (keepState) {
const dims = this.dimensions || {};

@@ -306,9 +318,16 @@

width: dims.width,
height: dims.height
height: dims.height,
};
}
else {
} else {
if (this.config) {
this.config.target.removeEventListener('webglcontextlost', this._loseContext, true);
this.config.target.removeEventListener('webglcontextcreationerror', this._contextCreationError, false);
this.config.target.removeEventListener(
'webglcontextlost',
this._loseContext,
true,
);
this.config.target.removeEventListener(
'webglcontextcreationerror',
this._contextCreationError,
false,
);
}

@@ -331,5 +350,4 @@

*/
restoreContext () {
if ( Kampos.preventContextCreation )
return false;
restoreContext() {
if (Kampos.preventContextCreation) return false;

@@ -340,3 +358,3 @@ const canvas = this.config.target;

if ( parent ) {
if (parent) {
parent.replaceChild(clone, canvas);

@@ -348,8 +366,20 @@ }

canvas.removeEventListener('webglcontextlost', this._loseContext, true);
canvas.removeEventListener('webglcontextrestored', this._restoreContext, true);
canvas.removeEventListener('webglcontextcreationerror', this._contextCreationError, false);
canvas.removeEventListener(
'webglcontextrestored',
this._restoreContext,
true,
);
canvas.removeEventListener(
'webglcontextcreationerror',
this._contextCreationError,
false,
);
clone.addEventListener('webglcontextlost', this._loseContext, true);
clone.addEventListener('webglcontextcreationerror', this._contextCreationError, false);
clone.addEventListener(
'webglcontextcreationerror',
this._contextCreationError,
false,
);
if ( this.lostContext ) {
if (this.lostContext) {
return this._restoreContext();

@@ -361,17 +391,18 @@ }

_createTextures () {
this.data && this.data.textures.forEach((texture, i) => {
const data = this.data.textures[i];
_createTextures() {
this.data &&
this.data.textures.forEach((texture, i) => {
const data = this.data.textures[i];
data.texture = core.createTexture(this.gl, {
width: this.dimensions.width,
height: this.dimensions.height,
format: texture.format,
data: texture.data,
wrap: texture.wrap
}).texture;
data.texture = core.createTexture(this.gl, {
width: this.dimensions.width,
height: this.dimensions.height,
format: texture.format,
data: texture.data,
wrap: texture.wrap,
}).texture;
data.format = texture.format;
data.update = texture.update;
});
data.format = texture.format;
data.update = texture.update;
});
}

@@ -378,0 +409,0 @@ }

@@ -7,3 +7,3 @@ /**

export class Ticker {
constructor () {
constructor() {
this.pool = [];

@@ -15,4 +15,4 @@ }

*/
start () {
if ( ! this.animationFrameId ) {
start() {
if (!this.animationFrameId) {
const loop = (time) => {

@@ -30,3 +30,3 @@ this.animationFrameId = window.requestAnimationFrame(loop);

*/
stop () {
stop() {
window.cancelAnimationFrame(this.animationFrameId);

@@ -41,4 +41,4 @@ this.animationFrameId = null;

*/
draw (time) {
this.pool.forEach(instance => instance.draw(time));
draw(time) {
this.pool.forEach((instance) => instance.draw(time));
}

@@ -51,6 +51,6 @@

*/
add (instance) {
add(instance) {
const index = this.pool.indexOf(instance);
if ( ! ~ index ) {
if (!~index) {
this.pool.push(instance);

@@ -66,6 +66,6 @@ instance.playing = true;

*/
remove (instance) {
remove(instance) {
const index = this.pool.indexOf(instance);
if ( ~ index ) {
if (~index) {
this.pool.splice(index, 1);

@@ -72,0 +72,0 @@ instance.playing = false;

@@ -9,5 +9,5 @@ /**

*/
export default function ({sourceScale, toScale} = {}) {
const { x: sSx, y: sSy } = (sourceScale || { x: 0.0, y: 0.0 });
const { x: tSx, y: tSy } = (toScale || { x: 0.0, y: 0.0 });
export default function ({ sourceScale, toScale } = {}) {
const { x: sSx, y: sSy } = sourceScale || { x: 0.0, y: 0.0 };
const { x: tSx, y: tSy } = toScale || { x: 0.0, y: 0.0 };

@@ -35,7 +35,7 @@ /**

a_transitionToTexCoord: 'vec2',
a_transitionDispMapTexCoord: 'vec2'
a_transitionDispMapTexCoord: 'vec2',
},
main: `
v_transitionToTexCoord = a_transitionToTexCoord;
v_transitionDispMapTexCoord = a_transitionDispMapTexCoord;`
v_transitionDispMapTexCoord = a_transitionDispMapTexCoord;`,
},

@@ -49,3 +49,3 @@ fragment: {

u_sourceDispScale: 'vec2',
u_toDispScale: 'vec2'
u_toDispScale: 'vec2',
},

@@ -76,46 +76,42 @@ source: `

alpha = mix(alpha, targetPixel.a, u_transitionProgress);
}`
}`,
},
get disabled () {
get disabled() {
return !this.uniforms[0].data[0];
},
set disabled (b) {
set disabled(b) {
this.uniforms[0].data[0] = +!b;
},
get progress () {
get progress() {
return this.uniforms[3].data[0];
},
set progress (p) {
set progress(p) {
this.uniforms[3].data[0] = p;
},
get sourceScale () {
get sourceScale() {
const [x, y] = this.uniforms[4].data;
return {x, y};
return { x, y };
},
set sourceScale ({x, y}) {
if ( typeof x !== 'undefined' )
this.uniforms[4].data[0] = x;
if ( typeof y !== 'undefined' )
this.uniforms[4].data[1] = y;
set sourceScale({ x, y }) {
if (typeof x !== 'undefined') this.uniforms[4].data[0] = x;
if (typeof y !== 'undefined') this.uniforms[4].data[1] = y;
},
get toScale () {
get toScale() {
const [x, y] = this.uniforms[5].data;
return {x, y};
return { x, y };
},
set toScale ({x, y}) {
if ( typeof x !== 'undefined' )
this.uniforms[5].data[0] = x;
if ( typeof y !== 'undefined' )
this.uniforms[5].data[1] = y;
set toScale({ x, y }) {
if (typeof x !== 'undefined') this.uniforms[5].data[0] = x;
if (typeof y !== 'undefined') this.uniforms[5].data[1] = y;
},
get to () {
get to() {
return this.textures[0].data;
},
set to (media) {
set to(media) {
this.textures[0].data = media;
},
get map () {
get map() {
return this.textures[1].data;
},
set map (img) {
set map(img) {
this.textures[1].data = img;

@@ -125,3 +121,3 @@ },

v_transitionToTexCoord: 'vec2',
v_transitionDispMapTexCoord: 'vec2'
v_transitionDispMapTexCoord: 'vec2',
},

@@ -132,3 +128,3 @@ uniforms: [

type: 'i',
data: [1]
data: [1],
},

@@ -138,3 +134,3 @@ {

type: 'i',
data: [1]
data: [1],
},

@@ -144,3 +140,3 @@ {

type: 'i',
data: [2]
data: [2],
},

@@ -150,3 +146,3 @@ {

type: 'f',
data: [0]
data: [0],
},

@@ -156,3 +152,3 @@ {

type: 'f',
data: [sSx, sSy]
data: [sSx, sSy],
},

@@ -162,4 +158,4 @@ {

type: 'f',
data: [tSx, tSy]
}
data: [tSx, tSy],
},
],

@@ -169,8 +165,8 @@ attributes: [

name: 'a_transitionToTexCoord',
extends: 'a_texCoord'
extends: 'a_texCoord',
},
{
name: 'a_transitionDispMapTexCoord',
extends: 'a_texCoord'
}
extends: 'a_texCoord',
},
],

@@ -180,9 +176,9 @@ textures: [

format: 'RGBA',
update: true
update: true,
},
{
format: 'RGB'
}
]
format: 'RGB',
},
],
};
};
}

@@ -15,3 +15,3 @@ /**

color = [0.0, 0.0, 0.0, 0.0],
textureEnabled = true
textureEnabled = true,
} = {}) {

@@ -40,7 +40,7 @@ /**

a_transitionToTexCoord: 'vec2',
a_transitionDissolveMapTexCoord: 'vec2'
a_transitionDissolveMapTexCoord: 'vec2',
},
main: `
v_transitionToTexCoord = a_transitionToTexCoord;
v_transitionDissolveMapTexCoord = a_transitionDissolveMapTexCoord;`
v_transitionDissolveMapTexCoord = a_transitionDissolveMapTexCoord;`,
},

@@ -56,3 +56,3 @@ fragment: {

u_transitionTo: 'sampler2D',
u_transitionDissolveMap: 'sampler2D'
u_transitionDissolveMap: 'sampler2D',
},

@@ -78,28 +78,28 @@ main: `

alpha = mix(alpha, targetPixel.a, dissolveVector.a);
}`
}`,
},
get disabled () {
get disabled() {
return !this.uniforms[0].data[0];
},
set disabled (b) {
set disabled(b) {
this.uniforms[0].data[0] = +!b;
},
get textureEnabled () {
get textureEnabled() {
return !this.uniforms[7].data[0];
},
set textureEnabled (b) {
set textureEnabled(b) {
this.uniforms[7].data[0] = +!!b;
},
get progress () {
get progress() {
return this.uniforms[3].data[0];
},
set progress (p) {
set progress(p) {
this.uniforms[3].data[0] = Math.min(Math.max(p, 0.0), 1.0);
},
get color () {
get color() {
return this.uniforms[6].data.slice();
},
set color (colorTo) {
set color(colorTo) {
colorTo.forEach((c, i) => {
if ( ! Number.isNaN(c) ) {
if (!Number.isNaN(c)) {
this.uniforms[6].data[i] = c;

@@ -109,24 +109,24 @@ }

},
get to () {
get to() {
return this.textures[0].data;
},
set to (media) {
set to(media) {
this.textures[0].data = media;
},
get map () {
get map() {
return this.textures[1].data;
},
set map (img) {
set map(img) {
this.textures[1].data = img;
},
get low () {
get low() {
return this.uniforms[4].data[0];
},
set low (low) {
set low(low) {
this.uniforms[4].data[0] = Math.min(Math.max(low, 0.0), this.high);
},
get high () {
get high() {
return this.uniforms[5].data[0];
},
set high (high) {
set high(high) {
this.uniforms[5].data[0] = Math.min(Math.max(high, this.low), 1.0);

@@ -136,3 +136,3 @@ },

v_transitionToTexCoord: 'vec2',
v_transitionDissolveMapTexCoord: 'vec2'
v_transitionDissolveMapTexCoord: 'vec2',
},

@@ -143,3 +143,3 @@ uniforms: [

type: 'i',
data: [1]
data: [1],
},

@@ -149,3 +149,3 @@ {

type: 'i',
data: [1]
data: [1],
},

@@ -155,3 +155,3 @@ {

type: 'i',
data: [2]
data: [2],
},

@@ -161,3 +161,3 @@ {

type: 'f',
data: [0]
data: [0],
},

@@ -167,3 +167,3 @@ {

type: 'f',
data: [low]
data: [low],
},

@@ -173,3 +173,3 @@ {

type: 'f',
data: [high]
data: [high],
},

@@ -179,3 +179,3 @@ {

type: 'f',
data: color
data: color,
},

@@ -185,4 +185,4 @@ {

type: 'i',
data: [+!!textureEnabled]
}
data: [+!!textureEnabled],
},
],

@@ -192,8 +192,8 @@ attributes: [

name: 'a_transitionToTexCoord',
extends: 'a_texCoord'
extends: 'a_texCoord',
},
{
name: 'a_transitionDissolveMapTexCoord',
extends: 'a_texCoord'
}
extends: 'a_texCoord',
},
],

@@ -203,10 +203,10 @@ textures: [

format: 'RGBA',
update: true
update: true,
},
{
format: 'RGB',
update: false
}
]
update: false,
},
],
};
};
}

@@ -20,6 +20,6 @@ /**

attribute: {
a_transitionToTexCoord: 'vec2'
a_transitionToTexCoord: 'vec2',
},
main: `
v_transitionToTexCoord = a_transitionToTexCoord;`
v_transitionToTexCoord = a_transitionToTexCoord;`,
},

@@ -30,3 +30,3 @@ fragment: {

u_transitionProgress: 'float',
u_transitionTo: 'sampler2D'
u_transitionTo: 'sampler2D',
},

@@ -38,24 +38,24 @@ main: `

alpha = mix(alpha, targetPixel.a, u_transitionProgress);
}`
}`,
},
get disabled () {
get disabled() {
return !this.uniforms[0].data[0];
},
set disabled (b) {
set disabled(b) {
this.uniforms[0].data[0] = +!b;
},
get progress () {
get progress() {
return this.uniforms[2].data[0];
},
set progress (p) {
set progress(p) {
this.uniforms[2].data[0] = p;
},
get to () {
get to() {
return this.textures[0].data;
},
set to (media) {
set to(media) {
this.textures[0].data = media;
},
varying: {
v_transitionToTexCoord: 'vec2'
v_transitionToTexCoord: 'vec2',
},

@@ -66,3 +66,3 @@ uniforms: [

type: 'i',
data: [1]
data: [1],
},

@@ -72,3 +72,3 @@ {

type: 'i',
data: [1]
data: [1],
},

@@ -78,4 +78,4 @@ {

type: 'f',
data: [0]
}
data: [0],
},
],

@@ -85,4 +85,4 @@ attributes: [

name: 'a_transitionToTexCoord',
extends: 'a_texCoord'
}
extends: 'a_texCoord',
},
],

@@ -92,6 +92,6 @@ textures: [

format: 'RGBA',
update: true
}
]
update: true,
},
],
};
};
}

@@ -0,1 +1,3 @@

import type { Kampos } from './src/kampos';
declare type KamposConfig = {

@@ -15,3 +17,9 @@ target: HTMLCanvasElement;

declare type KamposSource = {
media: ArrayBufferView | ImageData | HTMLImageElement | HTMLCanvasElement | HTMLVideoElement | ImageBitmap;
media:
| ArrayBufferView
| ImageData
| HTMLImageElement
| HTMLCanvasElement
| HTMLVideoElement
| ImageBitmap;
width: number;

@@ -21,3 +29,10 @@ height: number;

declare type VaryingType = 'float' | 'vec2' | 'vec3' | 'vec4' | 'mat2' | 'mat3' | 'mat4';
declare type VaryingType =
| 'float'
| 'vec2'
| 'vec3'
| 'vec4'
| 'mat2'
| 'mat3'
| 'mat4';

@@ -34,6 +49,17 @@ declare type EffectConfig = {

declare type planeConfig = {
segments: number | { x: number, y: number };
segments: number | { x: number; y: number };
};
declare type UniformType = 'bool' | 'int' | 'float' | 'vec2' | 'vec3' | 'vec4' | 'mat2' | 'mat3' | 'mat4' | 'sampler2D' | 'samplerCube';
declare type UniformType =
| 'bool'
| 'int'
| 'float'
| 'vec2'
| 'vec3'
| 'vec4'
| 'mat2'
| 'mat3'
| 'mat4'
| 'sampler2D'
| 'samplerCube';

@@ -52,8 +78,19 @@ declare type ShaderAttributeType = 'float' | 'vec2' | 'vec3' | 'vec4';

format: 'RGBA' | 'RGB' | 'ALPHA' | 'LUMINANCE' | 'LUMINANCE_ALPHA';
data?: ArrayBufferView | ImageData | HTMLImageElement | HTMLCanvasElement | HTMLVideoElement | ImageBitmap;
data?:
| ArrayBufferView
| ImageData
| HTMLImageElement
| HTMLCanvasElement
| HTMLVideoElement
| ImageBitmap;
update?: boolean;
wrap?: 'stretch' | 'repeat' | 'mirror' | { x: string, y: string };
wrap?: 'stretch' | 'repeat' | 'mirror' | { x: string; y: string };
};
declare type AttributeType = 'BYTE' | 'SHORT' | 'UNSIGNED_BYTE' | 'UNSIGNED_SHORT' | 'FLOAT';
declare type AttributeType =
| 'BYTE'
| 'SHORT'
| 'UNSIGNED_BYTE'
| 'UNSIGNED_SHORT'
| 'FLOAT';

@@ -87,2 +124,4 @@ declare type Attribute = {

declare module "kampos";
declare type IKampos = Kampos
declare module 'kampos';

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc