@shotstack/shotstack-canvas 2.0.15 → 2.0.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +72 -13
- package/dist/entry.web.js +1 -4
- package/package.json +78 -66
- package/scripts/postinstall.js +58 -58
package/README.md
CHANGED
|
@@ -1,13 +1,72 @@
|
|
|
1
|
-
# @shotstack/shotstack-canvas
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
1
|
+
# @shotstack/shotstack-canvas
|
|
2
|
+
|
|
3
|
+
Text layout and animation engine using HarfBuzz WASM. Identical rendering on Node.js and Web.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- HarfBuzz WASM text shaping with glyph outlines
|
|
8
|
+
- Cross-platform DrawOp abstraction (Canvas2D for web, @napi-rs/canvas for Node.js)
|
|
9
|
+
- Rich text with fonts, stroke, shadow, gradients, backgrounds, and borders
|
|
10
|
+
- SVG asset rendering (11 shape types + SVG markup import)
|
|
11
|
+
- Rich caption support with word-level timing and 8 animation styles
|
|
12
|
+
- Video generation (H.264 MP4 via FFmpeg on Node.js, WebCodecs in browser)
|
|
13
|
+
- RTL and bidirectional text support
|
|
14
|
+
- Custom font registration (file, URL, or ArrayBuffer)
|
|
15
|
+
|
|
16
|
+
## Install
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
pnpm add @shotstack/shotstack-canvas
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Quick Start
|
|
23
|
+
|
|
24
|
+
### Node.js
|
|
25
|
+
|
|
26
|
+
```js
|
|
27
|
+
import { createTextEngine } from "@shotstack/shotstack-canvas";
|
|
28
|
+
|
|
29
|
+
const engine = await createTextEngine({ width: 800, height: 400 });
|
|
30
|
+
|
|
31
|
+
const asset = engine.validate({
|
|
32
|
+
type: "rich-text",
|
|
33
|
+
text: "Hello World",
|
|
34
|
+
font: { family: "Open Sans", size: 48, color: "#ffffff" },
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
const drawOps = await engine.renderFrame(asset.value, 0);
|
|
38
|
+
const renderer = await engine.createRenderer({ width: 800, height: 400 });
|
|
39
|
+
const buffer = renderer.paint(drawOps);
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### Web
|
|
43
|
+
|
|
44
|
+
```js
|
|
45
|
+
import { createTextEngine } from "@shotstack/shotstack-canvas";
|
|
46
|
+
|
|
47
|
+
const engine = await createTextEngine({ width: 800, height: 400 });
|
|
48
|
+
const asset = engine.validate({ type: "rich-text", text: "Hello World" });
|
|
49
|
+
const drawOps = await engine.renderFrame(asset.value, 0);
|
|
50
|
+
const renderer = engine.createRenderer(canvas);
|
|
51
|
+
renderer.paint(drawOps);
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Development
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
pnpm install
|
|
58
|
+
pnpm build
|
|
59
|
+
pnpm test
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Release
|
|
63
|
+
|
|
64
|
+
Releases are automated via [semantic-release](https://github.com/semantic-release/semantic-release). Pushing to `main` with Conventional Commit messages triggers a release:
|
|
65
|
+
|
|
66
|
+
- `fix: ...` — patch release (e.g., 2.0.15 → 2.0.16)
|
|
67
|
+
- `feat: ...` — minor release (e.g., 2.0.15 → 2.1.0)
|
|
68
|
+
- `feat!: ...` or `BREAKING CHANGE:` — major release (e.g., 2.0.15 → 3.0.0)
|
|
69
|
+
|
|
70
|
+
## License
|
|
71
|
+
|
|
72
|
+
MIT
|
package/dist/entry.web.js
CHANGED
|
@@ -32091,10 +32091,7 @@ var _FontRegistry = class _FontRegistry {
|
|
|
32091
32091
|
return;
|
|
32092
32092
|
}
|
|
32093
32093
|
try {
|
|
32094
|
-
const canvasMod =
|
|
32095
|
-
/* @vite-ignore */
|
|
32096
|
-
"canvas"
|
|
32097
|
-
);
|
|
32094
|
+
const canvasMod = { GlobalFonts: void 0 };
|
|
32098
32095
|
const GlobalFonts = canvasMod.GlobalFonts;
|
|
32099
32096
|
if (GlobalFonts && typeof GlobalFonts.register === "function") {
|
|
32100
32097
|
const buffer = Buffer.from(bytes);
|
package/package.json
CHANGED
|
@@ -1,66 +1,78 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@shotstack/shotstack-canvas",
|
|
3
|
-
"version": "2.0.
|
|
4
|
-
"description": "Text layout & animation engine (HarfBuzz) for Node & Web - fully self-contained.",
|
|
5
|
-
"type": "module",
|
|
6
|
-
"main": "./dist/entry.node.cjs",
|
|
7
|
-
"module": "./dist/entry.node.js",
|
|
8
|
-
"browser": "./dist/entry.web.js",
|
|
9
|
-
"types": "./dist/entry.node.d.ts",
|
|
10
|
-
"exports": {
|
|
11
|
-
".": {
|
|
12
|
-
"node": {
|
|
13
|
-
"import": "./dist/entry.node.js",
|
|
14
|
-
"require": "./dist/entry.node.cjs"
|
|
15
|
-
},
|
|
16
|
-
"browser": "./dist/entry.web.js",
|
|
17
|
-
"default": "./dist/entry.web.js"
|
|
18
|
-
}
|
|
19
|
-
},
|
|
20
|
-
"files": [
|
|
21
|
-
"dist/**",
|
|
22
|
-
"scripts/postinstall.js",
|
|
23
|
-
"README.md",
|
|
24
|
-
"LICENSE"
|
|
25
|
-
],
|
|
26
|
-
"scripts": {
|
|
27
|
-
"dev": "tsup --watch",
|
|
28
|
-
"build": "tsup",
|
|
29
|
-
"postinstall": "node scripts/postinstall.js",
|
|
30
|
-
"vendor:harfbuzz": "node scripts/vendor-harfbuzz.js",
|
|
31
|
-
"example:node": "node examples/node-example.mjs",
|
|
32
|
-
"example:video": "node examples/node-video.mjs",
|
|
33
|
-
"example:web": "vite dev examples/web-example",
|
|
34
|
-
"test:caption-web": "vite dev examples/caption-tests",
|
|
35
|
-
"prepublishOnly": "
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
"
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
"
|
|
46
|
-
|
|
47
|
-
"@resvg/resvg-
|
|
48
|
-
"
|
|
49
|
-
"@shotstack/schemas": "1.8.7",
|
|
50
|
-
"
|
|
51
|
-
"
|
|
52
|
-
"
|
|
53
|
-
"
|
|
54
|
-
"
|
|
55
|
-
"
|
|
56
|
-
"
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
"
|
|
61
|
-
"
|
|
62
|
-
"
|
|
63
|
-
"
|
|
64
|
-
"
|
|
65
|
-
|
|
66
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "@shotstack/shotstack-canvas",
|
|
3
|
+
"version": "2.0.17",
|
|
4
|
+
"description": "Text layout & animation engine (HarfBuzz) for Node & Web - fully self-contained.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/entry.node.cjs",
|
|
7
|
+
"module": "./dist/entry.node.js",
|
|
8
|
+
"browser": "./dist/entry.web.js",
|
|
9
|
+
"types": "./dist/entry.node.d.ts",
|
|
10
|
+
"exports": {
|
|
11
|
+
".": {
|
|
12
|
+
"node": {
|
|
13
|
+
"import": "./dist/entry.node.js",
|
|
14
|
+
"require": "./dist/entry.node.cjs"
|
|
15
|
+
},
|
|
16
|
+
"browser": "./dist/entry.web.js",
|
|
17
|
+
"default": "./dist/entry.web.js"
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"files": [
|
|
21
|
+
"dist/**",
|
|
22
|
+
"scripts/postinstall.js",
|
|
23
|
+
"README.md",
|
|
24
|
+
"LICENSE"
|
|
25
|
+
],
|
|
26
|
+
"scripts": {
|
|
27
|
+
"dev": "tsup --watch",
|
|
28
|
+
"build": "tsup",
|
|
29
|
+
"postinstall": "node scripts/postinstall.js",
|
|
30
|
+
"vendor:harfbuzz": "node scripts/vendor-harfbuzz.js",
|
|
31
|
+
"example:node": "node examples/node-example.mjs",
|
|
32
|
+
"example:video": "node examples/node-video.mjs",
|
|
33
|
+
"example:web": "vite dev examples/web-example",
|
|
34
|
+
"test:caption-web": "vite dev examples/caption-tests",
|
|
35
|
+
"prepublishOnly": "node scripts/publish-guard.cjs && pnpm build",
|
|
36
|
+
"test": "node --test tests/build-verify.mjs"
|
|
37
|
+
},
|
|
38
|
+
"publishConfig": {
|
|
39
|
+
"access": "public",
|
|
40
|
+
"registry": "https://registry.npmjs.org/"
|
|
41
|
+
},
|
|
42
|
+
"engines": {
|
|
43
|
+
"node": ">=18"
|
|
44
|
+
},
|
|
45
|
+
"sideEffects": false,
|
|
46
|
+
"dependencies": {
|
|
47
|
+
"@resvg/resvg-js": "^2.6.2",
|
|
48
|
+
"@resvg/resvg-wasm": "^2.6.2",
|
|
49
|
+
"@shotstack/schemas": "1.8.7",
|
|
50
|
+
"bidi-js": "^1.0.3",
|
|
51
|
+
"canvas": "npm:@napi-rs/canvas@^0.1.54",
|
|
52
|
+
"ffmpeg-static": "^5.2.0",
|
|
53
|
+
"fontkit": "^2.0.4",
|
|
54
|
+
"harfbuzzjs": "0.4.12",
|
|
55
|
+
"lru-cache": "^11.2.5",
|
|
56
|
+
"mp4-muxer": "^5.1.3",
|
|
57
|
+
"zod": "^4.2.0"
|
|
58
|
+
},
|
|
59
|
+
"devDependencies": {
|
|
60
|
+
"@semantic-release/changelog": "^6.0.3",
|
|
61
|
+
"@semantic-release/commit-analyzer": "^13.0.1",
|
|
62
|
+
"@semantic-release/git": "^10.0.1",
|
|
63
|
+
"@semantic-release/github": "^12.0.6",
|
|
64
|
+
"@semantic-release/npm": "^13.1.5",
|
|
65
|
+
"@semantic-release/release-notes-generator": "^14.1.0",
|
|
66
|
+
"@types/node": "^20.14.10",
|
|
67
|
+
"semantic-release": "^25.0.3",
|
|
68
|
+
"tsup": "^8.2.3",
|
|
69
|
+
"typescript": "^5.5.3",
|
|
70
|
+
"vite": "^5.3.3",
|
|
71
|
+
"vite-plugin-top-level-await": "1.6.0",
|
|
72
|
+
"vite-plugin-wasm": "3.5.0"
|
|
73
|
+
},
|
|
74
|
+
"repository": {
|
|
75
|
+
"type": "git",
|
|
76
|
+
"url": "https://github.com/shotstack/shotstack-canvas.git"
|
|
77
|
+
}
|
|
78
|
+
}
|
package/scripts/postinstall.js
CHANGED
|
@@ -1,58 +1,58 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Postinstall script to verify native canvas bindings are available
|
|
5
|
-
* This helps catch issues early and provides helpful guidance
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import { platform as _platform, arch as _arch } from 'os';
|
|
9
|
-
import { dirname } from 'path';
|
|
10
|
-
import { readdirSync } from 'fs';
|
|
11
|
-
import { createRequire } from 'module';
|
|
12
|
-
|
|
13
|
-
const require = createRequire(import.meta.url);
|
|
14
|
-
|
|
15
|
-
const platform = _platform();
|
|
16
|
-
const arch = _arch();
|
|
17
|
-
|
|
18
|
-
// Map platform/arch to package names
|
|
19
|
-
const platformMap = {
|
|
20
|
-
'darwin-arm64': '@napi-rs/canvas-darwin-arm64',
|
|
21
|
-
'darwin-x64': '@napi-rs/canvas-darwin-x64',
|
|
22
|
-
'linux-arm64': '@napi-rs/canvas-linux-arm64-gnu',
|
|
23
|
-
'linux-x64': '@napi-rs/canvas-linux-x64-gnu',
|
|
24
|
-
'win32-x64': '@napi-rs/canvas-win32-x64-msvc',
|
|
25
|
-
'linux-arm': '@napi-rs/canvas-linux-arm-gnueabihf',
|
|
26
|
-
'android-arm64': '@napi-rs/canvas-android-arm64',
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
const platformKey = `${platform}-${arch}`;
|
|
30
|
-
const requiredPackage = platformMap[platformKey];
|
|
31
|
-
|
|
32
|
-
if (!requiredPackage) {
|
|
33
|
-
console.warn(`\n⚠️ Warning: Unsupported platform ${platformKey} for @napi-rs/canvas`);
|
|
34
|
-
console.warn(' Canvas rendering may not work on this platform.\n');
|
|
35
|
-
process.exit(0);
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
// Check if the native binding package is installed
|
|
39
|
-
try {
|
|
40
|
-
const packagePath = require.resolve(`${requiredPackage}/package.json`);
|
|
41
|
-
const packageDir = dirname(packagePath);
|
|
42
|
-
|
|
43
|
-
// Verify the .node file exists
|
|
44
|
-
const nodeFiles = readdirSync(packageDir).filter(f => f.endsWith('.node'));
|
|
45
|
-
|
|
46
|
-
if (nodeFiles.length > 0) {
|
|
47
|
-
console.log(`✅ @shotstack/shotstack-canvas: Native canvas binding found for ${platformKey}`);
|
|
48
|
-
} else {
|
|
49
|
-
throw new Error('No .node file found');
|
|
50
|
-
}
|
|
51
|
-
} catch (error) {
|
|
52
|
-
console.warn(`\n⚠️ Warning: Native canvas binding not found for ${platformKey}`);
|
|
53
|
-
console.warn(` Expected package: ${requiredPackage}`);
|
|
54
|
-
console.warn('\n If you see "Cannot find native binding" errors, try:');
|
|
55
|
-
console.warn(' 1. Delete node_modules and package-lock.json');
|
|
56
|
-
console.warn(' 2. Run: npm install');
|
|
57
|
-
console.warn(` 3. Or manually install: npm install ${requiredPackage}\n`);
|
|
58
|
-
}
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Postinstall script to verify native canvas bindings are available
|
|
5
|
+
* This helps catch issues early and provides helpful guidance
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { platform as _platform, arch as _arch } from 'os';
|
|
9
|
+
import { dirname } from 'path';
|
|
10
|
+
import { readdirSync } from 'fs';
|
|
11
|
+
import { createRequire } from 'module';
|
|
12
|
+
|
|
13
|
+
const require = createRequire(import.meta.url);
|
|
14
|
+
|
|
15
|
+
const platform = _platform();
|
|
16
|
+
const arch = _arch();
|
|
17
|
+
|
|
18
|
+
// Map platform/arch to package names
|
|
19
|
+
const platformMap = {
|
|
20
|
+
'darwin-arm64': '@napi-rs/canvas-darwin-arm64',
|
|
21
|
+
'darwin-x64': '@napi-rs/canvas-darwin-x64',
|
|
22
|
+
'linux-arm64': '@napi-rs/canvas-linux-arm64-gnu',
|
|
23
|
+
'linux-x64': '@napi-rs/canvas-linux-x64-gnu',
|
|
24
|
+
'win32-x64': '@napi-rs/canvas-win32-x64-msvc',
|
|
25
|
+
'linux-arm': '@napi-rs/canvas-linux-arm-gnueabihf',
|
|
26
|
+
'android-arm64': '@napi-rs/canvas-android-arm64',
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
const platformKey = `${platform}-${arch}`;
|
|
30
|
+
const requiredPackage = platformMap[platformKey];
|
|
31
|
+
|
|
32
|
+
if (!requiredPackage) {
|
|
33
|
+
console.warn(`\n⚠️ Warning: Unsupported platform ${platformKey} for @napi-rs/canvas`);
|
|
34
|
+
console.warn(' Canvas rendering may not work on this platform.\n');
|
|
35
|
+
process.exit(0);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Check if the native binding package is installed
|
|
39
|
+
try {
|
|
40
|
+
const packagePath = require.resolve(`${requiredPackage}/package.json`);
|
|
41
|
+
const packageDir = dirname(packagePath);
|
|
42
|
+
|
|
43
|
+
// Verify the .node file exists
|
|
44
|
+
const nodeFiles = readdirSync(packageDir).filter(f => f.endsWith('.node'));
|
|
45
|
+
|
|
46
|
+
if (nodeFiles.length > 0) {
|
|
47
|
+
console.log(`✅ @shotstack/shotstack-canvas: Native canvas binding found for ${platformKey}`);
|
|
48
|
+
} else {
|
|
49
|
+
throw new Error('No .node file found');
|
|
50
|
+
}
|
|
51
|
+
} catch (error) {
|
|
52
|
+
console.warn(`\n⚠️ Warning: Native canvas binding not found for ${platformKey}`);
|
|
53
|
+
console.warn(` Expected package: ${requiredPackage}`);
|
|
54
|
+
console.warn('\n If you see "Cannot find native binding" errors, try:');
|
|
55
|
+
console.warn(' 1. Delete node_modules and package-lock.json');
|
|
56
|
+
console.warn(' 2. Run: npm install');
|
|
57
|
+
console.warn(` 3. Or manually install: npm install ${requiredPackage}\n`);
|
|
58
|
+
}
|