first commit
This commit is contained in:
419
node_modules/dom-to-image-more/README.md
generated
vendored
Normal file
419
node_modules/dom-to-image-more/README.md
generated
vendored
Normal file
@@ -0,0 +1,419 @@
|
||||
# DOM to Image
|
||||
|
||||
[](https://npmjs.com/package/dom-to-image-more)
|
||||
[](https://bundlephobia.com/result?p=dom-to-image-more)
|
||||
[](https://github.com/1904labs/dom-to-image-more/issues)
|
||||
[](https://github.com/1904labs/dom-to-image-more)
|
||||
[](https://www.twitter.com/idisposable)
|
||||
|
||||
## Breaking Change Notice
|
||||
|
||||
The 3.x release branch included some breaking changes in the very infrequently used
|
||||
ability to configure some utility methods used in this internal processing of
|
||||
dom-to-image-more. As browsers have matured, many of the hacks we're accumulated over the
|
||||
years are not needed, or better ways have been found to handle some edge-cases. With the
|
||||
help of folks like @meche-gh, in #99 we're stripping out the following members:
|
||||
|
||||
- `.mimes` - was the not-very-comprehensive list of mime types used to handle inlining
|
||||
things
|
||||
- `.parseExtension` - was a method to extract the extension from a filename, used to guess
|
||||
mime types
|
||||
- `.mimeType` - was a method to map file extensions to mime types
|
||||
- `.dataAsUrl` - was a method to reassemble a `data:` URI from a Base64 representation and
|
||||
mime type
|
||||
|
||||
The 3.x release branch should also fix more node compatibility and `iframe` issues.
|
||||
|
||||
## What is it
|
||||
|
||||
**dom-to-image-more** is a library which can turn arbitrary DOM node, including same
|
||||
origin and blob iframes, into a vector (SVG) or raster (PNG or JPEG) image, written in
|
||||
JavaScript.
|
||||
|
||||
This fork of
|
||||
[dom-to-image by Anatolii Saienko (tsayen)](https://github.com/tsayen/dom-to-image) with
|
||||
some important fixes merged. We are eternally grateful for his starting point.
|
||||
|
||||
Anatolii's version was based on [domvas by Paul Bakaus](https://github.com/pbakaus/domvas)
|
||||
and has been completely rewritten, with some bugs fixed and some new features (like web
|
||||
font and image support) added.
|
||||
|
||||
Moved to [1904labs organization](https://github.com/1904labs/) from my repositories
|
||||
2019-02-06 as of version 2.7.3
|
||||
|
||||
## Installation
|
||||
|
||||
### NPM
|
||||
|
||||
`npm install dom-to-image-more`
|
||||
|
||||
Then load
|
||||
|
||||
```javascript
|
||||
/* in ES 6 */
|
||||
import domtoimage from 'dom-to-image-more';
|
||||
/* in ES 5 */
|
||||
var domtoimage = require('dom-to-image-more');
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
All the top level functions accept DOM node and rendering options, and return promises,
|
||||
which are fulfilled with corresponding data URLs. Get a PNG image base64-encoded data URL
|
||||
and display right away:
|
||||
|
||||
```javascript
|
||||
var node = document.getElementById('my-node');
|
||||
|
||||
domtoimage
|
||||
.toPng(node)
|
||||
.then(function (dataUrl) {
|
||||
var img = new Image();
|
||||
img.src = dataUrl;
|
||||
document.body.appendChild(img);
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.error('oops, something went wrong!', error);
|
||||
});
|
||||
```
|
||||
|
||||
Get a PNG image blob and download it (using
|
||||
[FileSaver](https://github.com/eligrey/FileSaver.js/), for example):
|
||||
|
||||
```javascript
|
||||
domtoimage.toBlob(document.getElementById('my-node')).then(function (blob) {
|
||||
window.saveAs(blob, 'my-node.png');
|
||||
});
|
||||
```
|
||||
|
||||
Save and download a compressed JPEG image:
|
||||
|
||||
```javascript
|
||||
domtoimage
|
||||
.toJpeg(document.getElementById('my-node'), { quality: 0.95 })
|
||||
.then(function (dataUrl) {
|
||||
var link = document.createElement('a');
|
||||
link.download = 'my-image-name.jpeg';
|
||||
link.href = dataUrl;
|
||||
link.click();
|
||||
});
|
||||
```
|
||||
|
||||
Get an SVG data URL, but filter out all the `<i>` elements:
|
||||
|
||||
```javascript
|
||||
function filter(node) {
|
||||
return node.tagName !== 'i';
|
||||
}
|
||||
|
||||
domtoimage
|
||||
.toSvg(document.getElementById('my-node'), { filter: filter })
|
||||
.then(function (dataUrl) {
|
||||
/* do something */
|
||||
});
|
||||
```
|
||||
|
||||
Get the raw pixel data as a
|
||||
[Uint8Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array)
|
||||
with every 4 array elements representing the RGBA data of a pixel:
|
||||
|
||||
```javascript
|
||||
var node = document.getElementById('my-node');
|
||||
|
||||
domtoimage.toPixelData(node).then(function (pixels) {
|
||||
for (var y = 0; y < node.scrollHeight; ++y) {
|
||||
for (var x = 0; x < node.scrollWidth; ++x) {
|
||||
pixelAtXYOffset = 4 * y * node.scrollHeight + 4 * x;
|
||||
/* pixelAtXY is a Uint8Array[4] containing RGBA values of the pixel at (x, y) in the range 0..255 */
|
||||
pixelAtXY = pixels.slice(pixelAtXYOffset, pixelAtXYOffset + 4);
|
||||
}
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
Get a canvas object:
|
||||
|
||||
```javascript
|
||||
domtoimage.toCanvas(document.getElementById('my-node')).then(function (canvas) {
|
||||
console.log('canvas', canvas.width, canvas.height);
|
||||
});
|
||||
```
|
||||
|
||||
Adjust cloned nodes before/after children are cloned
|
||||
[sample fiddle](https://jsfiddle.net/IDisposable/grLtjwe5/12/)
|
||||
|
||||
```javascript
|
||||
const adjustClone = (node, clone, after) => {
|
||||
if (!after && clone.id === 'element') {
|
||||
clone.style.transform = 'translateY(100px)';
|
||||
}
|
||||
return clone;
|
||||
};
|
||||
|
||||
const wrapper = document.getElementById('wrapper');
|
||||
const blob = domtoimage.toBlob(wrapper, { adjustClonedNode: adjustClone });
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
_All the functions under `impl` are not public API and are exposed only for unit testing._
|
||||
|
||||
---
|
||||
|
||||
### Rendering options
|
||||
|
||||
#### filter
|
||||
|
||||
A function taking DOM node as argument. Should return true if passed node should be
|
||||
included in the output (excluding node means excluding it's children as well). Not called
|
||||
on the root node.
|
||||
|
||||
#### filterStyles
|
||||
|
||||
A function taking style propertie name as argument. Should return true if passed propertie
|
||||
should be included in the output
|
||||
|
||||
Sample use:
|
||||
|
||||
```javascript
|
||||
filterStyles(node, propertyName) {
|
||||
return !propertyName.startssWith('--'); // to filter out CSS variables
|
||||
}
|
||||
```
|
||||
|
||||
#### adjustClonedNode
|
||||
|
||||
A function that will be invoked on each node as they are cloned. Useful to adjust nodes in
|
||||
any way needed before the conversion. Note that this be invoked before the onclone
|
||||
callback. The handler gets the original node, the cloned node, and a boolean that says if
|
||||
we've cloned the children already (so you can handle either before or after)
|
||||
|
||||
Sample use:
|
||||
|
||||
```javascript
|
||||
const adjustClone = (node, clone, after) => {
|
||||
if (!after && clone.id === 'element') {
|
||||
clone.style.transform = 'translateY(100px)';
|
||||
}
|
||||
return clone;
|
||||
};
|
||||
```
|
||||
|
||||
const wrapper = document.getElementById('wrapper'); const blob =
|
||||
domtoimage.toBlob(wrapper, { adjustClonedNode: adjustClone});
|
||||
|
||||
#### onclone
|
||||
|
||||
A function taking the cloned and modified DOM node as argument. It allows to make final
|
||||
adjustements to the elements before rendering, on the whole clone, after all elements have
|
||||
been individually cloned. Note that this will be invoked after all the onclone callbacks
|
||||
have been fired.
|
||||
|
||||
The cloned DOM might differ a lot from the original DOM, for example canvas will be
|
||||
replaced with image tags, some class might have changed, the style are inlined. It can be
|
||||
useful to log the clone to get a better senses of the transformations.
|
||||
|
||||
#### bgcolor
|
||||
|
||||
A string value for the background color, any valid CSS color value.
|
||||
|
||||
#### height, width
|
||||
|
||||
Height and width in pixels to be applied to node before rendering.
|
||||
|
||||
#### style
|
||||
|
||||
An object whose properties to be copied to node's style before rendering. You might want
|
||||
to check
|
||||
[this reference](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Properties_Reference)
|
||||
for JavaScript names of CSS properties.
|
||||
|
||||
#### quality
|
||||
|
||||
A number between 0 and 1 indicating image quality (e.g. 0.92 => 92%) of the JPEG image.
|
||||
Defaults to 1.0 (100%)
|
||||
|
||||
#### cacheBust
|
||||
|
||||
Set to true to append the current time as a query string to URL requests to enable cache
|
||||
busting. Defaults to false
|
||||
|
||||
#### imagePlaceholder
|
||||
|
||||
A data URL for a placeholder image that will be used when fetching an image fails.
|
||||
Defaults to undefined and will throw an error on failed images
|
||||
|
||||
#### copyDefaultStyles
|
||||
|
||||
Set to true to enable the copying of the default styles of elements. This will make the
|
||||
process faster. Try disabling it if seeing extra padding and using resetting / normalizing
|
||||
in CSS. Defaults to true.
|
||||
|
||||
#### disableInlineImages
|
||||
|
||||
Set to true to disable the normal inlining images into the SVG output. This will generate
|
||||
SVGs that reference the original image files, so they my break if a referenced URL fails.
|
||||
This is always safe to use when generating a PNG/JPG file because the entire SVG image is
|
||||
rendered.
|
||||
|
||||
#### useCredentialFeatures
|
||||
|
||||
Allows optionally setting the `useCredentials` option if the resource matches a pattern in
|
||||
the `useCredentialFilters` array.
|
||||
|
||||
#### scale
|
||||
|
||||
Scale value to be applied on canvas's `ctx.scale()` on both x and y axis. Can be used to
|
||||
increase the image quality with higher image size.
|
||||
|
||||
### Alternative Solutions to CORS Policy Issue
|
||||
|
||||
Are you facing a [CORS policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS)
|
||||
issue in your app? Don't worry, there are alternative solutions to this problem that you
|
||||
can explore. Here are some options to consider:
|
||||
|
||||
1. **Use the option.corsImg support by passing images** With this option, you can setup a
|
||||
proxy service that will process the requests in a safe CORS context.
|
||||
|
||||
2. **Use third-party services like [allOrigins](https://allorigins.win/).** With this
|
||||
service, you can fetch the source code or an image in base64 format from any website.
|
||||
However, this method can be a bit slow.
|
||||
|
||||
3. **Set up your own API service.** Compared to third-party services like
|
||||
[allOrigins](https://allorigins.win/), this method can be faster, but you'll need to
|
||||
convert the image URL to base64 format. You can use the
|
||||
"[image-to-base64](https://github.com/renanbastos93/image-to-base64)" package for this
|
||||
purpose.
|
||||
|
||||
4. **Utilize
|
||||
[server-side functions](https://nextjs.org/docs/basic-features/data-fetching/get-server-side-props)
|
||||
features of frameworks like [Next.js](https://nextjs.org/).** This is the easiest and
|
||||
most convenient method, where you can directly fetch a URL source within
|
||||
[server-side functions](https://nextjs.org/docs/basic-features/data-fetching/get-server-side-props)
|
||||
and convert it to base64 format if needed.
|
||||
|
||||
By exploring these alternative solutions, you can overcome
|
||||
[the CORS policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) issue in your
|
||||
app and ensure that your images are accessible to everyone.
|
||||
|
||||
## Browsers
|
||||
|
||||
It's tested on latest Chrome and Firefox (49 and 45 respectively at the time of writing),
|
||||
with Chrome performing significantly better on big DOM trees, possibly due to it's more
|
||||
performant SVG support, and the fact that it supports `CSSStyleDeclaration.cssText`
|
||||
property.
|
||||
|
||||
_Internet Explorer is not (and will not be) supported, as it does not support SVG
|
||||
`<foreignObject>` tag_
|
||||
|
||||
_Safari [is not supported](https://github.com/tsayen/dom-to-image/issues/27), as it uses a
|
||||
stricter security model on `<foreignObject`> tag. Suggested workaround is to use `toSvg`
|
||||
and render on the server._`
|
||||
|
||||
## Dependencies
|
||||
|
||||
Uses Object.hasOwn() so needs at least Chrome/Edge 93, Firefox 92, Opera 79. Safari 15.4
|
||||
or Node 16.9.0
|
||||
|
||||
### Source
|
||||
|
||||
Only standard lib is currently used, but make sure your browser supports:
|
||||
|
||||
- [Promise](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise)
|
||||
- SVG `<foreignObject>` tag
|
||||
|
||||
### Tests
|
||||
|
||||
As of this v3 branch chain, the testing jig is taking advantage of the `onclone` hook to
|
||||
insert the clone-output into the testing page. This should make it a tiny bit easier to
|
||||
track down where exactly the inlining of CSS styles against the DOM nodes is wrong.
|
||||
|
||||
Most importantly, tests **only** depend on:
|
||||
|
||||
- [ocrad.js](https://github.com/antimatter15/ocrad.js), for the parts when you can't
|
||||
compare images (due to the browser rendering differences) and just have to test whether
|
||||
the text is rendered
|
||||
|
||||
## How it works
|
||||
|
||||
There might some day exist (or maybe already exists?) a simple and standard way of
|
||||
exporting parts of the HTML to image (and then this script can only serve as an evidence
|
||||
of all the hoops I had to jump through in order to get such obvious thing done) but I
|
||||
haven't found one so far.
|
||||
|
||||
This library uses a feature of SVG that allows having arbitrary HTML content inside of the
|
||||
`<foreignObject>` tag. So, in order to render that DOM node for you, following steps are
|
||||
taken:
|
||||
|
||||
1. Clone the original DOM node recursively
|
||||
|
||||
1. Compute the style for the node and each sub-node and copy it to corresponding clone
|
||||
- and don't forget to recreate pseudo-elements, as they are not cloned in any way, of
|
||||
course
|
||||
|
||||
1. Embed web fonts
|
||||
- find all the `@font-face` declarations that might represent web fonts
|
||||
|
||||
- parse file URLs, download corresponding files
|
||||
|
||||
- base64-encode and inline content as `data:` URLs
|
||||
|
||||
- concatenate all the processed CSS rules and put them into one `<style>` element,
|
||||
then attach it to the clone
|
||||
|
||||
1. Embed images
|
||||
- embed image URLs in `<img>` elements
|
||||
|
||||
- inline images used in `background` CSS property, in a fashion similar to fonts
|
||||
|
||||
1. Serialize the cloned node to XML
|
||||
|
||||
1. Wrap XML into the `<foreignObject>` tag, then into the SVG, then make it a data URL
|
||||
|
||||
1. Optionally, to get PNG content or raw pixel data as a Uint8Array, create an Image
|
||||
element with the SVG as a source, and render it on an off-screen canvas, that you have
|
||||
also created, then read the content from the canvas
|
||||
|
||||
1. Done!
|
||||
|
||||
## Using Typescript
|
||||
|
||||
1. Use original `dom-to-image` type definition
|
||||
`npm install @types/dom-to-image --save-dev`
|
||||
|
||||
1. Create dom-to-image-more type definition (`dom-to-image-more.d.ts`)
|
||||
|
||||
```javascript
|
||||
declare module 'dom-to-image-more' {
|
||||
import domToImage = require('dom-to-image-more');
|
||||
export = domToImage;
|
||||
}
|
||||
```
|
||||
|
||||
## Things to watch out for
|
||||
|
||||
- if the DOM node you want to render includes a `<canvas>` element with something drawn on
|
||||
it, it should be handled fine, unless the canvas is
|
||||
[tainted](https://developer.mozilla.org/en-US/docs/Web/HTML/CORS_enabled_image) - in
|
||||
this case rendering will rather not succeed.
|
||||
|
||||
- at the time of writing, Firefox has a problem with some external stylesheets (see issue
|
||||
#13). In such case, the error will be caught and logged.
|
||||
|
||||
## Authors
|
||||
|
||||
Marc Brooks, Anatolii Saienko (original dom-to-image), Paul Bakaus (original idea), Aidas
|
||||
Klimas (fixes), Edgardo Di Gesto (fixes), 樊冬 Fan Dong (fixes), Shrijan Tripathi (docs),
|
||||
SNDST00M (optimize), Joseph White (performance CSS), Phani Rithvij (test), David
|
||||
DOLCIMASCOLO (packaging), Zee (ZM) @zm-cttae (many major updates), Joshua Walsh
|
||||
@JoshuaWalsh (Firefox issues), Emre Coban @emrecoban (documentation), Nate Stuyvesant
|
||||
@nstuyvesant (fixes), King Wang @eachmawzw (CORS image proxy), TMM Schmit @tmmschmit
|
||||
(useCredentialsFilters), Aravind @codesculpture (fix overridden props), Shi Wenyu @cWenyu
|
||||
(shadow slot fix), David Burns @davidburns573 and Yujia Cheng @YujiaCheng1996 (font copy
|
||||
optional), Julien Dorra @juliendorra (documentation), Sean Zhang @SeanZhang-eaton (regex
|
||||
fixes), Ludovic Bouges @ludovic (style property filter), Roland Ma @RolandMa1986 (URL
|
||||
regex)", Kasim Tan @kasimtan
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
||||
Reference in New Issue
Block a user