17 changed files with 6250 additions and 10 deletions
@ -0,0 +1,33 @@
@@ -0,0 +1,33 @@
|
||||
name: Build packages |
||||
|
||||
on: |
||||
push: |
||||
branches: |
||||
- master |
||||
pull_request: |
||||
|
||||
jobs: |
||||
build: |
||||
runs-on: ubuntu-latest |
||||
|
||||
steps: |
||||
- uses: actions/checkout@v1 |
||||
|
||||
- name: Setup Node.js 12.x |
||||
uses: actions/setup-node@v1 |
||||
with: |
||||
node-version: 12.x |
||||
|
||||
- name: Install dependencies |
||||
run: | |
||||
npm ci |
||||
npm ci --prefix src/packages/excalidraw |
||||
npm ci --prefix src/packages/utils |
||||
|
||||
- name: Build @excalidraw/excalidraw |
||||
run: | |
||||
npm run pack --prefix src/packages/excalidraw |
||||
|
||||
- name: Build @excalidraw/utils |
||||
run: | |
||||
npm run pack --prefix src/packages/utils |
||||
@ -1,13 +1,13 @@
@@ -1,13 +1,13 @@
|
||||
import React, { useEffect, forwardRef } from "react"; |
||||
|
||||
import { InitializeApp } from "../components/InitializeApp"; |
||||
import App, { ExcalidrawImperativeAPI } from "../components/App"; |
||||
import { InitializeApp } from "../../components/InitializeApp"; |
||||
import App, { ExcalidrawImperativeAPI } from "../../components/App"; |
||||
|
||||
import "../css/app.scss"; |
||||
import "../css/styles.scss"; |
||||
import "../../css/app.scss"; |
||||
import "../../css/styles.scss"; |
||||
|
||||
import { ExcalidrawProps } from "../types"; |
||||
import { IsMobileProvider } from "../is-mobile"; |
||||
import { ExcalidrawProps } from "../../types"; |
||||
import { IsMobileProvider } from "../../is-mobile"; |
||||
|
||||
const Excalidraw = (props: ExcalidrawProps) => { |
||||
const { |
||||
@ -0,0 +1,89 @@
@@ -0,0 +1,89 @@
|
||||
import { |
||||
exportToCanvas as _exportToCanvas, |
||||
exportToSvg as _exportToSvg, |
||||
} from "../scene/export"; |
||||
import { getDefaultAppState } from "../appState"; |
||||
import { AppState } from "../types"; |
||||
import { ExcalidrawElement } from "../element/types"; |
||||
import { getNonDeletedElements } from "../element"; |
||||
|
||||
type ExportOpts = { |
||||
elements: readonly ExcalidrawElement[]; |
||||
appState?: Omit<AppState, "offsetTop" | "offsetLeft">; |
||||
getDimensions: ( |
||||
width: number, |
||||
height: number, |
||||
) => { width: number; height: number; scale: number }; |
||||
}; |
||||
|
||||
const exportToCanvas = ({ |
||||
elements, |
||||
appState = getDefaultAppState(), |
||||
getDimensions = (width, height) => ({ width, height, scale: 1 }), |
||||
}: ExportOpts) => { |
||||
return _exportToCanvas( |
||||
getNonDeletedElements(elements), |
||||
{ ...appState, offsetTop: 0, offsetLeft: 0 }, |
||||
{ |
||||
exportBackground: appState.exportBackground ?? true, |
||||
viewBackgroundColor: appState.viewBackgroundColor ?? "#FFF", |
||||
shouldAddWatermark: appState.shouldAddWatermark ?? false, |
||||
}, |
||||
(width: number, height: number) => { |
||||
const canvas = document.createElement("canvas"); |
||||
const ret = getDimensions(width, height); |
||||
|
||||
canvas.width = ret.width; |
||||
canvas.height = ret.height; |
||||
|
||||
return canvas; |
||||
}, |
||||
); |
||||
}; |
||||
|
||||
export const exportToBlob = ( |
||||
opts: ExportOpts & { |
||||
mimeType?: string; |
||||
quality?: number; |
||||
}, |
||||
): Promise<Blob | null> => { |
||||
const canvas = exportToCanvas(opts); |
||||
|
||||
let { mimeType = "image/png", quality } = opts; |
||||
|
||||
if (mimeType === "image/png" && typeof quality === "number") { |
||||
console.warn(`"quality" will be ignored for "image/png" mimeType`); |
||||
} |
||||
|
||||
if (mimeType === "image/jpg") { |
||||
mimeType = "image/jpeg"; |
||||
} |
||||
|
||||
quality = quality ? quality : /image\/jpe?g/.test(mimeType) ? 0.92 : 0.8; |
||||
|
||||
return new Promise((resolve) => { |
||||
canvas.toBlob( |
||||
(blob: Blob | null) => { |
||||
resolve(blob); |
||||
}, |
||||
mimeType, |
||||
quality, |
||||
); |
||||
}); |
||||
}; |
||||
|
||||
export const exportToSvg = ({ |
||||
elements, |
||||
appState = getDefaultAppState(), |
||||
exportPadding, |
||||
metadata, |
||||
}: ExportOpts & { |
||||
exportPadding?: number; |
||||
metadata?: string; |
||||
}): SVGSVGElement => { |
||||
return _exportToSvg(getNonDeletedElements(elements), { |
||||
...appState, |
||||
exportPadding, |
||||
metadata, |
||||
}); |
||||
}; |
||||
@ -0,0 +1,9 @@
@@ -0,0 +1,9 @@
|
||||
# Changelog |
||||
|
||||
## [Unreleased] |
||||
|
||||
First release of `@excalidraw/utils` to provide utilities functions. |
||||
|
||||
- Added `exportToBlob` and `exportToSvg` to export an Excalidraw diagram definition, respectively, |
||||
to a [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob) and |
||||
to a [SVGElement](https://developer.mozilla.org/en-US/docs/Web/API/SVGElement) ([#2246](https://github.com/excalidraw/excalidraw/pull/2246)) |
||||
@ -0,0 +1,92 @@
@@ -0,0 +1,92 @@
|
||||
# @excalidraw/utils |
||||
|
||||
## Install |
||||
|
||||
npm i @excalidraw/utils |
||||
|
||||
If you prefer Yarn over npm, use this command to install the Excalidraw utils package: |
||||
|
||||
yarn add @excalidraw/utils |
||||
|
||||
## API |
||||
|
||||
### `exportToBlob` (async) |
||||
|
||||
Export an Excalidraw diagram to a [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob). |
||||
|
||||
### `exportToSvg` |
||||
|
||||
Export an Excalidraw diagram to a [SVGElement](https://developer.mozilla.org/en-US/docs/Web/API/SVGElement). |
||||
|
||||
## Usage |
||||
|
||||
Excalidraw utils is published as a UMD (Universal Module Definition). |
||||
If you are using a Web bundler (for instance, Webpack), you can import it as an ES6 module: |
||||
|
||||
```js |
||||
import { exportToSvg, exportToBlob } from "@excalidraw/utils"; |
||||
``` |
||||
|
||||
To use it in a browser directly: |
||||
|
||||
```html |
||||
<script src="https://unpkg.com/@excalidraw/utils@0.1.0/dist/excalidraw.min.js"></script> |
||||
<script> |
||||
// ExcalidrawUtils is a global variable defined by excalidraw.min.js |
||||
const { exportToSvg, exportToBlob } = ExcalidrawUtils; |
||||
</script> |
||||
``` |
||||
|
||||
Here's the `exportToBlob` and `exportToSvg` functions in action: |
||||
|
||||
```js |
||||
const excalidrawDiagram = { |
||||
type: "excalidraw", |
||||
version: 2, |
||||
source: "https://excalidraw.com", |
||||
elements: [ |
||||
{ |
||||
id: "vWrqOAfkind2qcm7LDAGZ", |
||||
type: "ellipse", |
||||
x: 414, |
||||
y: 237, |
||||
width: 214, |
||||
height: 214, |
||||
angle: 0, |
||||
strokeColor: "#000000", |
||||
backgroundColor: "#15aabf", |
||||
fillStyle: "hachure", |
||||
strokeWidth: 1, |
||||
strokeStyle: "solid", |
||||
roughness: 1, |
||||
opacity: 100, |
||||
groupIds: [], |
||||
strokeSharpness: "sharp", |
||||
seed: 1041657908, |
||||
version: 120, |
||||
versionNonce: 1188004276, |
||||
isDeleted: false, |
||||
boundElementIds: null, |
||||
}, |
||||
], |
||||
appState: { |
||||
viewBackgroundColor: "#ffffff", |
||||
gridSize: null, |
||||
}, |
||||
}; |
||||
|
||||
// Export the Excalidraw diagram as SVG string |
||||
const svg = exportToSvg(excalidrawDiagram); |
||||
console.log(svg.outerHTML); |
||||
|
||||
// Export the Excalidraw diagram as PNG Blob URL |
||||
(async () => { |
||||
const blob = await exportToBlob({ |
||||
...excalidrawDiagram, |
||||
mimeType: "image/png", |
||||
}); |
||||
|
||||
const urlCreator = window.URL || window.webkitURL; |
||||
console.log(urlCreator.createObjectURL(blob)); |
||||
})(); |
||||
``` |
||||
@ -0,0 +1 @@
@@ -0,0 +1 @@
|
||||
export { exportToBlob, exportToSvg } from "../utils.ts"; |
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,55 @@
@@ -0,0 +1,55 @@
|
||||
{ |
||||
"name": "@excalidraw/utils", |
||||
"version": "0.1.0", |
||||
"main": "dist/excalidraw-utils.min.js", |
||||
"files": [ |
||||
"dist/*" |
||||
], |
||||
"description": "Excalidraw utilities functions", |
||||
"license": "MIT", |
||||
"keywords": [ |
||||
"excalidraw", |
||||
"excalidraw-utils" |
||||
], |
||||
"browserslist": { |
||||
"production": [ |
||||
">0.2%", |
||||
"not dead", |
||||
"not ie <= 11", |
||||
"not op_mini all", |
||||
"not safari < 12", |
||||
"not kaios <= 2.5", |
||||
"not edge < 79", |
||||
"not chrome < 70", |
||||
"not and_uc < 13", |
||||
"not samsung < 10" |
||||
], |
||||
"development": [ |
||||
"last 1 chrome version", |
||||
"last 1 firefox version", |
||||
"last 1 safari version" |
||||
] |
||||
}, |
||||
"devDependencies": { |
||||
"@babel/core": "7.9.0", |
||||
"@babel/plugin-transform-arrow-functions": "7.8.3", |
||||
"@babel/plugin-transform-async-to-generator": "7.8.3", |
||||
"@babel/plugin-transform-runtime": "^7.12.1", |
||||
"@babel/plugin-transform-typescript": "7.9.4", |
||||
"@babel/preset-env": "7.9.5", |
||||
"@babel/preset-typescript": "7.9.0", |
||||
"babel-loader": "8.1.0", |
||||
"babel-plugin-transform-class-properties": "6.24.1", |
||||
"cross-env": "7.0.2", |
||||
"file-loader": "6.0.0", |
||||
"ts-loader": "7.0.0", |
||||
"webpack": "4.42.0", |
||||
"webpack-cli": "3.3.11" |
||||
}, |
||||
"bugs": "https://github.com/excalidraw/excalidraw/issues", |
||||
"repository": "https://github.com/excalidraw/excalidraw", |
||||
"scripts": { |
||||
"build:umd": "cross-env NODE_ENV=production webpack --config webpack.prod.config.js", |
||||
"pack": "npm run build:umd && npm pack" |
||||
} |
||||
} |
||||
@ -0,0 +1,40 @@
@@ -0,0 +1,40 @@
|
||||
const webpack = require("webpack"); |
||||
const path = require("path"); |
||||
|
||||
module.exports = { |
||||
mode: "production", |
||||
resolve: { |
||||
extensions: [".tsx", ".ts", ".js"], |
||||
}, |
||||
optimization: { |
||||
runtimeChunk: false, |
||||
}, |
||||
output: { |
||||
path: path.resolve(__dirname, "dist"), |
||||
filename: "excalidraw-utils.min.js", |
||||
library: "ExcalidrawUtils", |
||||
libraryTarget: "umd", |
||||
}, |
||||
entry: "./index.js", |
||||
module: { |
||||
rules: [ |
||||
{ |
||||
test: /\.(ts|tsx|js)$/, |
||||
use: [ |
||||
{ |
||||
loader: "ts-loader", |
||||
options: { |
||||
transpileOnly: true, |
||||
configFile: path.resolve(__dirname, "../tsconfig.prod.json"), |
||||
}, |
||||
}, |
||||
], |
||||
}, |
||||
], |
||||
}, |
||||
plugins: [ |
||||
new webpack.optimize.LimitChunkCountPlugin({ |
||||
maxChunks: 1, |
||||
}), |
||||
], |
||||
}; |
||||
Loading…
Reference in new issue