Skip to content

Commit

Permalink
Adjust build targets and fix typings
Browse files Browse the repository at this point in the history
- ESM/MJS builds will target "full" ESM support with ES2020+
- CJS/UMD builds will target ES2019+ because this will transpile
  nullish coalescing and optional chaining operators, among other
  ES2020 features, which is syntax that older versions of Webpack,
  for example, may not support (just to increase compatibility
  a bit from ES2020)
- Had to resort to non-bundled typings as the bundled typings that
  the TSC produces, it cannot consume for some strange reason

Also added reference to canvas-txt PR that resulted in this new
package in the README.
  • Loading branch information
stefcameron committed Mar 13, 2024
1 parent 706bfd9 commit 3c2de18
Show file tree
Hide file tree
Showing 8 changed files with 82 additions and 20 deletions.
12 changes: 6 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ Render multiline plain or rich text into textboxes on HTML Canvas with automatic

🙌 This library would not exist were it not for all the work done by its original author, [Geon George](https://geongeorge.com/), in his [canvas-txt](https://github.com/geongeorge/Canvas-Txt) library.

The main feature that sparked `text-to-canvas` is a significant update to (departure from) the original code base in order to support rich text formatting, which introduced the concept of a `Word` specifying both `text` and (optional) associated CSS-based `format` styles. A sentence is then simply a `Word[]` with/out whitespace (optionally inferred).
The main feature that sparked `text-to-canvas` is a significant [update](https://github.com/geongeorge/Canvas-Txt/pull/95) to the original code base in order to support rich text formatting, which introduced the concept of a `Word` specifying both `text` and (optional) associated CSS-based `format` styles. A sentence is then simply a `Word[]` with/out whitespace (optionally inferred).

Plain text (i.e. a `string`) is still supported as a convenience via the `drawText()`, `splitText()`, and `textToWords()` [APIs](#api).

Expand Down Expand Up @@ -74,8 +74,8 @@ Use in Node is only supported to the extent that appropriate bundles are provide

Two bundles are provided for this type of target:

- `./dist/text-to-canvas.esm.min.js` (ESM)
- `./dist/text-to-canvas.min.js` (CJS)
- `./dist/text-to-canvas.esm.min.js` (ESM, `import`, ES2020+)
- `./dist/text-to-canvas.min.js` (CJS, `require()`, ES2019+)

Used implicitly when using the library in a larger app bundled with a bundler like Webpack, Rollup, or Vite.

Expand Down Expand Up @@ -127,7 +127,7 @@ const { height } = drawText(...);

One bundle is provided for this type of target:

- `./dist/text-to-canvas.umd.min.js` (UMD)
- `./dist/text-to-canvas.umd.min.js` (UMD, ES2019+)

Used implicitly when loading the library directly in a browser:

Expand All @@ -146,8 +146,8 @@ Used implicitly when loading the library directly in a browser:

Two bundles are provided for this type of target:

- `./dist/text-to-canvas.mjs` (ESM/MJS)
- `./dist/text-to-canvas.cjs` (CJS)
- `./dist/text-to-canvas.mjs` (ESM/MJS, `import`, Node v20.11.1+)
- `./dist/text-to-canvas.cjs` (CJS, `require()`, Node v20.11.1+)

> ⚠️ Other than the bundles, __Node is not formally supported by this library__, and neither is the `node-canvas` library used in the demo. Whatever "Node Canvas" library you use, make sure it supports the [HTMLCanvasElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement) API and it _should_ work.
Expand Down
11 changes: 11 additions & 0 deletions config/build-util.mts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/**
* Minimum targets for major browsers with native ES Modules, native ESM dynamic import,
* and `import.meta` support.
* @see https://vitejs.dev/config/build-options.html#build-target
*/
export const esmBrowserTargets = [
'edge88',
'firefox78',
'chrome87',
'safari14',
];
47 changes: 47 additions & 0 deletions config/vite.config.cjs.mts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
//
// Browser library bundles
//

import path from 'node:path';
import url from 'node:url';
import { createRequire } from 'node:module';
import { defineConfig } from 'vite';
import { esmBrowserTargets } from './build-util.mjs';

const __dirname = path.basename(url.fileURLToPath(import.meta.url));

const require = createRequire(import.meta.url);
const pkg: { name: string } = require(
path.resolve(__dirname, '../package.json')
) as { name: string };
const pkgName = pkg.name;

export default defineConfig({
root: 'src',
build: {
// @see https://vitejs.dev/config/build-options.html#build-target
// would be nice to make it es2020 but that means a lot of newer features
// like dynamic imports, `import.meta`, nullish coalescing and optional
// chaining operators, etc, that tend to not be supported in older bundlers
target: ['es2019', ...esmBrowserTargets],
outDir: '../dist',
emptyOutDir: false,
sourcemap: true,
lib: {
entry: 'lib/index.ts',
name: 'textToCanvas',
formats: ['cjs', 'umd'],
fileName: (format) => {
switch (format) {
case 'umd':
return `${pkgName}.umd.min.js`;
case 'cjs':
case 'commonjs':
return `${pkgName}.min.js`;
default:
throw new Error(`Unknown build format "${format}"`);
}
},
},
},
});
4 changes: 4 additions & 0 deletions config/vite.config.docs.mts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import vue from '@vitejs/plugin-vue';
import AutoImport from 'unplugin-auto-import/vite';
import Components from 'unplugin-vue-components/vite';
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers';
import { esmBrowserTargets } from './build-util.mjs';

export default defineConfig({
plugins: [
Expand All @@ -30,6 +31,9 @@ export default defineConfig({
},
base: '/text-to-canvas/', // ultimately deployed to https://stefcameron.github.io/text-to-canvas/
build: {
// @see https://vitejs.dev/config/build-options.html#build-target
// ES2020 is first version with dynamic import and `import.meta`, in particular
target: ['es2020', ...esmBrowserTargets],
outDir: '../../dist-docs',
emptyOutDir: true,
},
Expand Down
11 changes: 5 additions & 6 deletions config/vite.config.browser.mts → config/vite.config.esm.mts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import path from 'node:path';
import url from 'node:url';
import { createRequire } from 'node:module';
import { defineConfig } from 'vite';
import { esmBrowserTargets } from './build-util.mjs';

const __dirname = path.basename(url.fileURLToPath(import.meta.url));

Expand All @@ -18,22 +19,20 @@ const pkgName = pkg.name;
export default defineConfig({
root: 'src',
build: {
// @see https://vitejs.dev/config/build-options.html#build-target
// ES2020 is first version with dynamic import and `import.meta`, in particular
target: ['es2020', ...esmBrowserTargets],
outDir: '../dist',
emptyOutDir: false,
sourcemap: true,
lib: {
entry: 'lib/index.ts',
name: 'textToCanvas',
formats: ['es', 'cjs', 'umd'],
formats: ['es'],
fileName: (format) => {
switch (format) {
case 'es':
return `${pkgName}.esm.min.js`;
case 'umd':
return `${pkgName}.umd.min.js`;
case 'cjs':
case 'commonjs':
return `${pkgName}.min.js`;
default:
throw new Error(`Unknown build format "${format}"`);
}
Expand Down
2 changes: 2 additions & 0 deletions config/vite.config.node.mts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ const pkgName = pkg.name;
export default defineConfig({
root: 'src',
build: {
// @see // @see https://vitejs.dev/config/build-options.html#build-target
target: 'node20.11.1', // should match package.json#engines.node minimum
outDir: '../dist',
emptyOutDir: false,
sourcemap: false,
Expand Down
13 changes: 6 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,18 +33,17 @@
"README.md",
"CHANGELOG.md"
],
"main": "./dist/text-to-canvas.umd.min.js",
"module": "./dist/text-to-canvas.esm.min.js",
"types": "./dist/text-to-canvas.d.ts",
"main": "./dist/text-to-canvas.min.js",
"types": "./dist/types/index.d.ts",
"exports": {
"types": "./dist/text-to-canvas.d.ts",
"types": "./dist/types/index.d.ts",
"node": {
"import": "./dist/text-to-canvas.mjs",
"require": "./dist/text-to-canvas.cjs"
},
"default": {
"import": "./dist/text-to-canvas.esm.min.js",
"require": "./dist/text-to-canvas.cjs.min.js",
"require": "./dist/text-to-canvas.min.js",
"browser": "./dist/text-to-canvas.umd.min.js"
}
},
Expand All @@ -54,9 +53,9 @@
},
"scripts": {
"build": "rm -rf ./dist && npm run build:browser && npm run build:node && npm run build:types",
"build:browser": "vite build --config config/vite.config.browser.mts",
"build:browser": "vite build --config config/vite.config.esm.mts && vite build --config config/vite.config.cjs.mts",
"build:node": "vite build --config config/vite.config.node.mts",
"build:types": "tsc src/lib/index.ts --declaration --emitDeclarationOnly --outFile dist/text-to-canvas.d.ts",
"build:types": "tsc src/lib/index.ts --declaration --emitDeclarationOnly --outDir dist/types",
"ci:build": "npm run build && npm run docs",
"ci:lint": "npm run lint",
"ci:test": "npm run test:unit && npm run demo:node",
Expand Down
2 changes: 1 addition & 1 deletion src/demos/node-demo.mts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ const OUT_FILEPATH = './demo/node-demo-output.png';
async function main() {
let createCanvas;
try {
// @ts-expect-error -- `canvas` package is an optional dependency so may not exist, hence this dynamic import
({ createCanvas } = await import('canvas'));
} catch {
console.error(
Expand Down Expand Up @@ -38,6 +37,7 @@ async function main() {
// `node-canvas` claim to support the full `HTMLCanvasElement` API; but it supports enough
// of it that this should work :) -- if it fails, we'll need to find another Node-based
// Canvas library that has more complete support for the Web Canvas API.
// @ts-expect-error -- because `node-canvas` doesn't support exactly the same API as the `HTMLCanvasElement` on the 2D context
({ height } = drawText(ctx, words, {
x: 100,
y: 100,
Expand Down

0 comments on commit 3c2de18

Please sign in to comment.