mirror of
https://github.com/niklasvh/html2canvas.git
synced 2023-08-10 21:13:10 +03:00
Compare commits
11 Commits
v1.0.0-alp
...
v1.0.0-alp
Author | SHA1 | Date | |
---|---|---|---|
b7c7464c5f | |||
ae019f174c | |||
ea6062c85b | |||
9a4a506366 | |||
cb93b80d0d | |||
79e1c857e6 | |||
cc9d1f89dc | |||
d0f7ecfa9a | |||
1870433307 | |||
3a5ed43e97 | |||
8429761e8f |
20
CHANGELOG.md
20
CHANGELOG.md
@ -1,33 +1,41 @@
|
|||||||
### Changelog ###
|
### Changelog ###
|
||||||
|
|
||||||
#### v1.0.0-alpha6 - 28.12.2017 ####
|
#### v1.0.0-alpha.8 - 2.1.2018 ####
|
||||||
|
* Use correct doctype in cloned Document (Fix #1298)
|
||||||
|
* Fix individual border rendering (Fix #1349)
|
||||||
|
|
||||||
|
#### v1.0.0-alpha.7 - 31.12.2017 ####
|
||||||
|
* Fix form input rendering (#1338)
|
||||||
|
* Improve word line breaking algorithm
|
||||||
|
|
||||||
|
#### v1.0.0-alpha.6 - 28.12.2017 ####
|
||||||
* Fix list-style: none (#1340)
|
* Fix list-style: none (#1340)
|
||||||
* Extend supported values for pseudo element content
|
* Extend supported values for pseudo element content
|
||||||
|
|
||||||
#### v1.0.0-alpha5 - 21.12.2017 ####
|
#### v1.0.0-alpha.5 - 21.12.2017 ####
|
||||||
* Fix underline positioning
|
* Fix underline positioning
|
||||||
* Fix canvas rendering on Chrome
|
* Fix canvas rendering on Chrome
|
||||||
* Fix overflow: auto
|
* Fix overflow: auto
|
||||||
* Added support for rendering list-style
|
* Added support for rendering list-style
|
||||||
|
|
||||||
#### v1.0.0-alpha4 - 12.12.2017 ####
|
#### v1.0.0-alpha.4 - 12.12.2017 ####
|
||||||
* Fix rendering with multiple fonts defined (Fix #796)
|
* Fix rendering with multiple fonts defined (Fix #796)
|
||||||
* Add support for radial-gradients
|
* Add support for radial-gradients
|
||||||
* Fix logging option (#1302)
|
* Fix logging option (#1302)
|
||||||
* Add support for rendering webgl canvas content (#646)
|
* Add support for rendering webgl canvas content (#646)
|
||||||
* Fix external SVG loading with proxies (#802)
|
* Fix external SVG loading with proxies (#802)
|
||||||
|
|
||||||
#### v1.0.0-alpha3 - 9.12.2017 ####
|
#### v1.0.0-alpha.3 - 9.12.2017 ####
|
||||||
* Disable `foreignObjectRendering` by default (#1295)
|
* Disable `foreignObjectRendering` by default (#1295)
|
||||||
* Fix background-size when using background-origin and background-size: cover/contain (#1299)
|
* Fix background-size when using background-origin and background-size: cover/contain (#1299)
|
||||||
* Added support for background-origin: content-box (#1299)
|
* Added support for background-origin: content-box (#1299)
|
||||||
|
|
||||||
#### v1.0.0-alpha2 - 7.12.2017 ####
|
#### v1.0.0-alpha.2 - 7.12.2017 ####
|
||||||
* Fix scroll positions for CanvasRenderer (#1259)
|
* Fix scroll positions for CanvasRenderer (#1259)
|
||||||
* Fix `data-html2canvas-ignore` attribute (#1253)
|
* Fix `data-html2canvas-ignore` attribute (#1253)
|
||||||
* Fix decimal `letter-spacing` values (#1293)
|
* Fix decimal `letter-spacing` values (#1293)
|
||||||
|
|
||||||
#### v1.0.0-alpha1 - 5.12.2017 ####
|
#### v1.0.0-alpha.1 - 5.12.2017 ####
|
||||||
* Complete rewrite of library
|
* Complete rewrite of library
|
||||||
##### Breaking Changes #####
|
##### Breaking Changes #####
|
||||||
* Remove deprecated onrendered callback, calling `html2canvas` returns a `Promise<HTMLCanvasElement>`
|
* Remove deprecated onrendered callback, calling `html2canvas` returns a `Promise<HTMLCanvasElement>`
|
||||||
|
@ -36,6 +36,7 @@ Below is a list of all the supported CSS properties and values.
|
|||||||
- height
|
- height
|
||||||
- left
|
- left
|
||||||
- letter-spacing
|
- letter-spacing
|
||||||
|
- line-break
|
||||||
- list-style
|
- list-style
|
||||||
- list-style-image
|
- list-style-image
|
||||||
- list-style-position
|
- list-style-position
|
||||||
@ -47,6 +48,7 @@ Below is a list of all the supported CSS properties and values.
|
|||||||
- min-width
|
- min-width
|
||||||
- opacity
|
- opacity
|
||||||
- overflow
|
- overflow
|
||||||
|
- overflow-wrap
|
||||||
- padding
|
- padding
|
||||||
- position
|
- position
|
||||||
- right
|
- right
|
||||||
@ -62,7 +64,9 @@ Below is a list of all the supported CSS properties and values.
|
|||||||
- visibility
|
- visibility
|
||||||
- white-space
|
- white-space
|
||||||
- width
|
- width
|
||||||
|
- word-break
|
||||||
- word-spacing
|
- word-spacing
|
||||||
|
- word-wrap
|
||||||
- z-index
|
- z-index
|
||||||
|
|
||||||
## Unsupported CSS properties
|
## Unsupported CSS properties
|
||||||
@ -76,8 +80,6 @@ These CSS properties are **NOT** currently supported
|
|||||||
- [mix-blend-mode](https://github.com/niklasvh/html2canvas/issues/580)
|
- [mix-blend-mode](https://github.com/niklasvh/html2canvas/issues/580)
|
||||||
- [object-fit](https://github.com/niklasvh/html2canvas/issues/1064)
|
- [object-fit](https://github.com/niklasvh/html2canvas/issues/1064)
|
||||||
- [repeating-linear-gradient()](https://github.com/niklasvh/html2canvas/issues/1162)
|
- [repeating-linear-gradient()](https://github.com/niklasvh/html2canvas/issues/1162)
|
||||||
- word-break
|
|
||||||
- [word-wrap](https://github.com/niklasvh/html2canvas/issues/664)
|
|
||||||
- [writing-mode](https://github.com/niklasvh/html2canvas/issues/1258)
|
- [writing-mode](https://github.com/niklasvh/html2canvas/issues/1258)
|
||||||
- [zoom](https://github.com/niklasvh/html2canvas/issues/732)
|
- [zoom](https://github.com/niklasvh/html2canvas/issues/732)
|
||||||
|
|
||||||
|
1685
package-lock.json
generated
1685
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -3,7 +3,7 @@
|
|||||||
"name": "html2canvas",
|
"name": "html2canvas",
|
||||||
"description": "Screenshots with JavaScript",
|
"description": "Screenshots with JavaScript",
|
||||||
"main": "dist/npm/index.js",
|
"main": "dist/npm/index.js",
|
||||||
"version": "1.0.0-alpha.6",
|
"version": "1.0.0-alpha.8",
|
||||||
"author": {
|
"author": {
|
||||||
"name": "Niklas von Hertzen",
|
"name": "Niklas von Hertzen",
|
||||||
"email": "niklasvh@gmail.com",
|
"email": "niklasvh@gmail.com",
|
||||||
@ -77,6 +77,6 @@
|
|||||||
"homepage": "https://html2canvas.hertzen.com",
|
"homepage": "https://html2canvas.hertzen.com",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"punycode": "2.1.0"
|
"css-line-break": "1.0.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
28
src/Clone.js
28
src/Clone.js
@ -614,7 +614,7 @@ export const cloneWindow = (
|
|||||||
});
|
});
|
||||||
|
|
||||||
documentClone.open();
|
documentClone.open();
|
||||||
documentClone.write('<!DOCTYPE html><html></html>');
|
documentClone.write(`${serializeDoctype(document.doctype)}<html></html>`);
|
||||||
// Chrome scrolls the parent document for some reason after the write to the cloned window???
|
// Chrome scrolls the parent document for some reason after the write to the cloned window???
|
||||||
restoreOwnerScroll(referenceElement.ownerDocument, scrollX, scrollY);
|
restoreOwnerScroll(referenceElement.ownerDocument, scrollX, scrollY);
|
||||||
documentClone.replaceChild(
|
documentClone.replaceChild(
|
||||||
@ -626,3 +626,29 @@ export const cloneWindow = (
|
|||||||
return iframeLoad;
|
return iframeLoad;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const serializeDoctype = (doctype: ?DocumentType): string => {
|
||||||
|
let str = '';
|
||||||
|
if (doctype) {
|
||||||
|
str += '<!DOCTYPE ';
|
||||||
|
if (doctype.name) {
|
||||||
|
str += doctype.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (doctype.internalSubset) {
|
||||||
|
str += doctype.internalSubset;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (doctype.publicId) {
|
||||||
|
str += `"${doctype.publicId}"`;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (doctype.systemId) {
|
||||||
|
str += `"${doctype.systemId}"`;
|
||||||
|
}
|
||||||
|
|
||||||
|
str += '>';
|
||||||
|
}
|
||||||
|
|
||||||
|
return str;
|
||||||
|
};
|
||||||
|
@ -133,7 +133,7 @@ const inlineFormElement = (
|
|||||||
if (value.length > 0 && body) {
|
if (value.length > 0 && body) {
|
||||||
const wrapper = node.ownerDocument.createElement('html2canvaswrapper');
|
const wrapper = node.ownerDocument.createElement('html2canvaswrapper');
|
||||||
copyCSSStyles(node.ownerDocument.defaultView.getComputedStyle(node, null), wrapper);
|
copyCSSStyles(node.ownerDocument.defaultView.getComputedStyle(node, null), wrapper);
|
||||||
wrapper.style.position = 'fixed';
|
wrapper.style.position = 'absolute';
|
||||||
wrapper.style.left = `${container.bounds.left}px`;
|
wrapper.style.left = `${container.bounds.left}px`;
|
||||||
wrapper.style.top = `${container.bounds.top}px`;
|
wrapper.style.top = `${container.bounds.top}px`;
|
||||||
if (!allowLinebreak) {
|
if (!allowLinebreak) {
|
||||||
|
@ -7,9 +7,11 @@ import type {BorderRadius} from './parsing/borderRadius';
|
|||||||
import type {DisplayBit} from './parsing/display';
|
import type {DisplayBit} from './parsing/display';
|
||||||
import type {Float} from './parsing/float';
|
import type {Float} from './parsing/float';
|
||||||
import type {Font} from './parsing/font';
|
import type {Font} from './parsing/font';
|
||||||
|
import type {LineBreak} from './parsing/lineBreak';
|
||||||
import type {ListStyle} from './parsing/listStyle';
|
import type {ListStyle} from './parsing/listStyle';
|
||||||
import type {Margin} from './parsing/margin';
|
import type {Margin} from './parsing/margin';
|
||||||
import type {Overflow} from './parsing/overflow';
|
import type {Overflow} from './parsing/overflow';
|
||||||
|
import type {OverflowWrap} from './parsing/overflowWrap';
|
||||||
import type {Padding} from './parsing/padding';
|
import type {Padding} from './parsing/padding';
|
||||||
import type {Position} from './parsing/position';
|
import type {Position} from './parsing/position';
|
||||||
import type {TextShadow} from './parsing/textShadow';
|
import type {TextShadow} from './parsing/textShadow';
|
||||||
@ -17,6 +19,7 @@ import type {TextTransform} from './parsing/textTransform';
|
|||||||
import type {TextDecoration} from './parsing/textDecoration';
|
import type {TextDecoration} from './parsing/textDecoration';
|
||||||
import type {Transform} from './parsing/transform';
|
import type {Transform} from './parsing/transform';
|
||||||
import type {Visibility} from './parsing/visibility';
|
import type {Visibility} from './parsing/visibility';
|
||||||
|
import type {WordBreak} from './parsing/word-break';
|
||||||
import type {zIndex} from './parsing/zIndex';
|
import type {zIndex} from './parsing/zIndex';
|
||||||
|
|
||||||
import type {Bounds, BoundCurves} from './Bounds';
|
import type {Bounds, BoundCurves} from './Bounds';
|
||||||
@ -34,9 +37,11 @@ import {parseDisplay, DISPLAY} from './parsing/display';
|
|||||||
import {parseCSSFloat, FLOAT} from './parsing/float';
|
import {parseCSSFloat, FLOAT} from './parsing/float';
|
||||||
import {parseFont} from './parsing/font';
|
import {parseFont} from './parsing/font';
|
||||||
import {parseLetterSpacing} from './parsing/letterSpacing';
|
import {parseLetterSpacing} from './parsing/letterSpacing';
|
||||||
|
import {parseLineBreak} from './parsing/lineBreak';
|
||||||
import {parseListStyle} from './parsing/listStyle';
|
import {parseListStyle} from './parsing/listStyle';
|
||||||
import {parseMargin} from './parsing/margin';
|
import {parseMargin} from './parsing/margin';
|
||||||
import {parseOverflow, OVERFLOW} from './parsing/overflow';
|
import {parseOverflow, OVERFLOW} from './parsing/overflow';
|
||||||
|
import {parseOverflowWrap} from './parsing/overflowWrap';
|
||||||
import {parsePadding} from './parsing/padding';
|
import {parsePadding} from './parsing/padding';
|
||||||
import {parsePosition, POSITION} from './parsing/position';
|
import {parsePosition, POSITION} from './parsing/position';
|
||||||
import {parseTextDecoration} from './parsing/textDecoration';
|
import {parseTextDecoration} from './parsing/textDecoration';
|
||||||
@ -44,6 +49,7 @@ import {parseTextShadow} from './parsing/textShadow';
|
|||||||
import {parseTextTransform} from './parsing/textTransform';
|
import {parseTextTransform} from './parsing/textTransform';
|
||||||
import {parseTransform} from './parsing/transform';
|
import {parseTransform} from './parsing/transform';
|
||||||
import {parseVisibility, VISIBILITY} from './parsing/visibility';
|
import {parseVisibility, VISIBILITY} from './parsing/visibility';
|
||||||
|
import {parseWordBreak} from './parsing/word-break';
|
||||||
import {parseZIndex} from './parsing/zIndex';
|
import {parseZIndex} from './parsing/zIndex';
|
||||||
|
|
||||||
import {parseBounds, parseBoundCurves, calculatePaddingBoxPath} from './Bounds';
|
import {parseBounds, parseBoundCurves, calculatePaddingBoxPath} from './Bounds';
|
||||||
@ -65,10 +71,12 @@ type StyleDeclaration = {
|
|||||||
float: Float,
|
float: Float,
|
||||||
font: Font,
|
font: Font,
|
||||||
letterSpacing: number,
|
letterSpacing: number,
|
||||||
|
lineBreak: LineBreak,
|
||||||
listStyle: ListStyle | null,
|
listStyle: ListStyle | null,
|
||||||
margin: Margin,
|
margin: Margin,
|
||||||
opacity: number,
|
opacity: number,
|
||||||
overflow: Overflow,
|
overflow: Overflow,
|
||||||
|
overflowWrap: OverflowWrap,
|
||||||
padding: Padding,
|
padding: Padding,
|
||||||
position: Position,
|
position: Position,
|
||||||
textDecoration: TextDecoration | null,
|
textDecoration: TextDecoration | null,
|
||||||
@ -76,6 +84,7 @@ type StyleDeclaration = {
|
|||||||
textTransform: TextTransform,
|
textTransform: TextTransform,
|
||||||
transform: Transform,
|
transform: Transform,
|
||||||
visibility: Visibility,
|
visibility: Visibility,
|
||||||
|
wordBreak: WordBreak,
|
||||||
zIndex: zIndex
|
zIndex: zIndex
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -134,12 +143,16 @@ export default class NodeContainer {
|
|||||||
font: parseFont(style),
|
font: parseFont(style),
|
||||||
letterSpacing: parseLetterSpacing(style.letterSpacing),
|
letterSpacing: parseLetterSpacing(style.letterSpacing),
|
||||||
listStyle: display === DISPLAY.LIST_ITEM ? parseListStyle(style) : null,
|
listStyle: display === DISPLAY.LIST_ITEM ? parseListStyle(style) : null,
|
||||||
|
lineBreak: parseLineBreak(style.lineBreak),
|
||||||
margin: parseMargin(style),
|
margin: parseMargin(style),
|
||||||
opacity: parseFloat(style.opacity),
|
opacity: parseFloat(style.opacity),
|
||||||
overflow:
|
overflow:
|
||||||
INPUT_TAGS.indexOf(node.tagName) === -1
|
INPUT_TAGS.indexOf(node.tagName) === -1
|
||||||
? parseOverflow(style.overflow)
|
? parseOverflow(style.overflow)
|
||||||
: OVERFLOW.HIDDEN,
|
: OVERFLOW.HIDDEN,
|
||||||
|
overflowWrap: parseOverflowWrap(
|
||||||
|
style.overflowWrap ? style.overflowWrap : style.wordWrap
|
||||||
|
),
|
||||||
padding: parsePadding(style),
|
padding: parsePadding(style),
|
||||||
position: position,
|
position: position,
|
||||||
textDecoration: parseTextDecoration(style),
|
textDecoration: parseTextDecoration(style),
|
||||||
@ -147,6 +160,7 @@ export default class NodeContainer {
|
|||||||
textTransform: parseTextTransform(style.textTransform),
|
textTransform: parseTextTransform(style.textTransform),
|
||||||
transform: parseTransform(style),
|
transform: parseTransform(style),
|
||||||
visibility: parseVisibility(style.visibility),
|
visibility: parseVisibility(style.visibility),
|
||||||
|
wordBreak: parseWordBreak(style.wordBreak),
|
||||||
zIndex: parseZIndex(position !== POSITION.STATIC ? style.zIndex : 'auto')
|
zIndex: parseZIndex(position !== POSITION.STATIC ? style.zIndex : 'auto')
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -165,7 +165,7 @@ export default class Renderer {
|
|||||||
!container.style.background.backgroundColor.isTransparent() ||
|
!container.style.background.backgroundColor.isTransparent() ||
|
||||||
container.style.background.backgroundImage.length;
|
container.style.background.backgroundImage.length;
|
||||||
|
|
||||||
const renderableBorders = container.style.border.filter(
|
const hasRenderableBorders = container.style.border.some(
|
||||||
border =>
|
border =>
|
||||||
border.borderStyle !== BORDER_STYLE.NONE && !border.borderColor.isTransparent()
|
border.borderStyle !== BORDER_STYLE.NONE && !border.borderColor.isTransparent()
|
||||||
);
|
);
|
||||||
@ -186,12 +186,17 @@ export default class Renderer {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
renderableBorders.forEach((border, side) => {
|
container.style.border.forEach((border, side) => {
|
||||||
this.renderBorder(border, side, container.curvedBounds);
|
if (
|
||||||
|
border.borderStyle !== BORDER_STYLE.NONE &&
|
||||||
|
!border.borderColor.isTransparent()
|
||||||
|
) {
|
||||||
|
this.renderBorder(border, side, container.curvedBounds);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
if (HAS_BACKGROUND || renderableBorders.length) {
|
if (HAS_BACKGROUND || hasRenderableBorders) {
|
||||||
const paths = container.parent ? container.parent.getClipPaths() : [];
|
const paths = container.parent ? container.parent.getClipPaths() : [];
|
||||||
if (paths.length) {
|
if (paths.length) {
|
||||||
this.target.clip(paths, callback);
|
this.target.clip(paths, callback);
|
||||||
|
@ -1,18 +1,12 @@
|
|||||||
/* @flow */
|
/* @flow */
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
import {ucs2} from 'punycode';
|
|
||||||
import type NodeContainer from './NodeContainer';
|
import type NodeContainer from './NodeContainer';
|
||||||
import {Bounds, parseBounds} from './Bounds';
|
import {Bounds, parseBounds} from './Bounds';
|
||||||
import {TEXT_DECORATION} from './parsing/textDecoration';
|
import {TEXT_DECORATION} from './parsing/textDecoration';
|
||||||
|
|
||||||
import FEATURES from './Feature';
|
import FEATURES from './Feature';
|
||||||
|
import {breakWords, toCodePoints, fromCodePoint} from './Unicode';
|
||||||
const UNICODE = /[^\u0000-\u00ff]/;
|
|
||||||
|
|
||||||
const hasUnicodeCharacters = (text: string): boolean => UNICODE.test(text);
|
|
||||||
|
|
||||||
const encodeCodePoint = (codePoint: number): string => ucs2.encode([codePoint]);
|
|
||||||
|
|
||||||
export class TextBounds {
|
export class TextBounds {
|
||||||
text: string;
|
text: string;
|
||||||
@ -29,9 +23,10 @@ export const parseTextBounds = (
|
|||||||
parent: NodeContainer,
|
parent: NodeContainer,
|
||||||
node: Text
|
node: Text
|
||||||
): Array<TextBounds> => {
|
): Array<TextBounds> => {
|
||||||
const codePoints = ucs2.decode(value);
|
const letterRendering = parent.style.letterSpacing !== 0;
|
||||||
const letterRendering = parent.style.letterSpacing !== 0 || hasUnicodeCharacters(value);
|
const textList = letterRendering
|
||||||
const textList = letterRendering ? codePoints.map(encodeCodePoint) : splitWords(codePoints);
|
? toCodePoints(value).map(i => fromCodePoint(i))
|
||||||
|
: breakWords(value, parent);
|
||||||
const length = textList.length;
|
const length = textList.length;
|
||||||
const defaultView = node.parentNode ? node.parentNode.ownerDocument.defaultView : null;
|
const defaultView = node.parentNode ? node.parentNode.ownerDocument.defaultView : null;
|
||||||
const scrollX = defaultView ? defaultView.pageXOffset : 0;
|
const scrollX = defaultView ? defaultView.pageXOffset : 0;
|
||||||
@ -88,42 +83,3 @@ const getRangeBounds = (
|
|||||||
range.setEnd(node, offset + length);
|
range.setEnd(node, offset + length);
|
||||||
return Bounds.fromClientRect(range.getBoundingClientRect(), scrollX, scrollY);
|
return Bounds.fromClientRect(range.getBoundingClientRect(), scrollX, scrollY);
|
||||||
};
|
};
|
||||||
|
|
||||||
const splitWords = (codePoints: Array<number>): Array<string> => {
|
|
||||||
const words = [];
|
|
||||||
let i = 0;
|
|
||||||
let onWordBoundary = false;
|
|
||||||
let word;
|
|
||||||
while (codePoints.length) {
|
|
||||||
if (isWordBoundary(codePoints[i]) === onWordBoundary) {
|
|
||||||
word = codePoints.splice(0, i);
|
|
||||||
if (word.length) {
|
|
||||||
words.push(ucs2.encode(word));
|
|
||||||
}
|
|
||||||
onWordBoundary = !onWordBoundary;
|
|
||||||
i = 0;
|
|
||||||
} else {
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i >= codePoints.length) {
|
|
||||||
word = codePoints.splice(0, i);
|
|
||||||
if (word.length) {
|
|
||||||
words.push(ucs2.encode(word));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return words;
|
|
||||||
};
|
|
||||||
|
|
||||||
const isWordBoundary = (characterCode: number): boolean => {
|
|
||||||
return (
|
|
||||||
[
|
|
||||||
32, // <space>
|
|
||||||
13, // \r
|
|
||||||
10, // \n
|
|
||||||
9, // \t
|
|
||||||
45 // -
|
|
||||||
].indexOf(characterCode) !== -1
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
@ -1,32 +1,27 @@
|
|||||||
/* @flow */
|
/* @flow */
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
export const fromCodePoint = (...codePoints: Array<number>): string => {
|
import NodeContainer from './NodeContainer';
|
||||||
if (String.fromCodePoint) {
|
import {LineBreaker, fromCodePoint, toCodePoints} from 'css-line-break';
|
||||||
return String.fromCodePoint(...codePoints);
|
import {OVERFLOW_WRAP} from './parsing/overflowWrap';
|
||||||
|
|
||||||
|
export {toCodePoints, fromCodePoint} from 'css-line-break';
|
||||||
|
|
||||||
|
export const breakWords = (str: string, parent: NodeContainer): Array<string> => {
|
||||||
|
const breaker = LineBreaker(str, {
|
||||||
|
lineBreak: parent.style.lineBreak,
|
||||||
|
wordBreak:
|
||||||
|
parent.style.overflowWrap === OVERFLOW_WRAP.BREAK_WORD
|
||||||
|
? 'break-word'
|
||||||
|
: parent.style.wordBreak
|
||||||
|
});
|
||||||
|
|
||||||
|
const words = [];
|
||||||
|
let bk;
|
||||||
|
|
||||||
|
while (!(bk = breaker.next()).done) {
|
||||||
|
words.push(bk.value.slice());
|
||||||
}
|
}
|
||||||
|
|
||||||
const length = codePoints.length;
|
return words;
|
||||||
if (!length) {
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
|
|
||||||
const codeUnits = [];
|
|
||||||
|
|
||||||
let index = -1;
|
|
||||||
let result = '';
|
|
||||||
while (++index < length) {
|
|
||||||
let codePoint = codePoints[index];
|
|
||||||
if (codePoint <= 0xffff) {
|
|
||||||
codeUnits.push(codePoint);
|
|
||||||
} else {
|
|
||||||
codePoint -= 0x10000;
|
|
||||||
codeUnits.push((codePoint >> 10) + 0xd800, codePoint % 0x400 + 0xdc00);
|
|
||||||
}
|
|
||||||
if (index + 1 === length || codeUnits.length > 0x4000) {
|
|
||||||
result += String.fromCharCode(...codeUnits);
|
|
||||||
codeUnits.length = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
};
|
};
|
||||||
|
19
src/parsing/lineBreak.js
Normal file
19
src/parsing/lineBreak.js
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
/* @flow */
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
export const LINE_BREAK = {
|
||||||
|
NORMAL: 'normal',
|
||||||
|
STRICT: 'strict'
|
||||||
|
};
|
||||||
|
|
||||||
|
export type LineBreak = $Values<typeof LINE_BREAK>;
|
||||||
|
|
||||||
|
export const parseLineBreak = (wordBreak: string): LineBreak => {
|
||||||
|
switch (wordBreak) {
|
||||||
|
case 'strict':
|
||||||
|
return LINE_BREAK.STRICT;
|
||||||
|
case 'normal':
|
||||||
|
default:
|
||||||
|
return LINE_BREAK.NORMAL;
|
||||||
|
}
|
||||||
|
};
|
19
src/parsing/overflowWrap.js
Normal file
19
src/parsing/overflowWrap.js
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
/* @flow */
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
export const OVERFLOW_WRAP = {
|
||||||
|
NORMAL: 0,
|
||||||
|
BREAK_WORD: 1
|
||||||
|
};
|
||||||
|
|
||||||
|
export type OverflowWrap = $Values<typeof OVERFLOW_WRAP>;
|
||||||
|
|
||||||
|
export const parseOverflowWrap = (overflow: string): OverflowWrap => {
|
||||||
|
switch (overflow) {
|
||||||
|
case 'break-word':
|
||||||
|
return OVERFLOW_WRAP.BREAK_WORD;
|
||||||
|
case 'normal':
|
||||||
|
default:
|
||||||
|
return OVERFLOW_WRAP.NORMAL;
|
||||||
|
}
|
||||||
|
};
|
22
src/parsing/word-break.js
Normal file
22
src/parsing/word-break.js
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
/* @flow */
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
export const WORD_BREAK = {
|
||||||
|
NORMAL: 'normal',
|
||||||
|
BREAK_ALL: 'break-all',
|
||||||
|
KEEP_ALL: 'keep-all'
|
||||||
|
};
|
||||||
|
|
||||||
|
export type WordBreak = $Values<typeof WORD_BREAK>;
|
||||||
|
|
||||||
|
export const parseWordBreak = (wordBreak: string): WordBreak => {
|
||||||
|
switch (wordBreak) {
|
||||||
|
case 'break-all':
|
||||||
|
return WORD_BREAK.BREAK_ALL;
|
||||||
|
case 'keep-all':
|
||||||
|
return WORD_BREAK.KEEP_ALL;
|
||||||
|
case 'normal':
|
||||||
|
default:
|
||||||
|
return WORD_BREAK.NORMAL;
|
||||||
|
}
|
||||||
|
};
|
@ -12,6 +12,7 @@
|
|||||||
margin: 10px;
|
margin: 10px;
|
||||||
background:#6F428C;
|
background:#6F428C;
|
||||||
border-style: solid;
|
border-style: solid;
|
||||||
|
border-width: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.box1 {
|
.box1 {
|
||||||
@ -33,6 +34,12 @@
|
|||||||
border-color: green;
|
border-color: green;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.box5 {
|
||||||
|
border-style: none;
|
||||||
|
border-bottom: 50px solid #807d32;
|
||||||
|
border-bottom-width: 50px;
|
||||||
|
}
|
||||||
|
|
||||||
html {
|
html {
|
||||||
background: #3a84c3;
|
background: #3a84c3;
|
||||||
}
|
}
|
||||||
@ -43,5 +50,6 @@
|
|||||||
<div class="box2"> </div>
|
<div class="box2"> </div>
|
||||||
<div class="box3"> </div>
|
<div class="box3"> </div>
|
||||||
<div class="box4"> </div>
|
<div class="box4"> </div>
|
||||||
|
<div class="box5"> </div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
11
tests/reftests/images/doctype.html
Normal file
11
tests/reftests/images/doctype.html
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<script type="text/javascript" src="../../test.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<img src="../../assets/image.jpg" />
|
||||||
|
<img src="../../assets/image2.jpg" style="display:block;" />
|
||||||
|
<br>
|
||||||
|
</body>
|
||||||
|
</html>
|
40
tests/reftests/text/line-break.html
Normal file
40
tests/reftests/text/line-break.html
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>word-break</title>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||||
|
<script type="text/javascript" src="../../test.js"></script>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
font-family: Arial;
|
||||||
|
}
|
||||||
|
.test span {
|
||||||
|
line-break: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.strict span {
|
||||||
|
line-break: strict;
|
||||||
|
}
|
||||||
|
p.test{
|
||||||
|
border: 1px solid gray;
|
||||||
|
color: blue;
|
||||||
|
width: 6em;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<!-- iteration marks -->
|
||||||
|
<p class="test" lang="ja">
|
||||||
|
<span>サンプルぁルぁルぁルぁルぁルぁルぁぁぁぁ文ンプル–文々サンプル文</span>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p class="test strict" lang="ja">
|
||||||
|
<span>サンプルぁルぁルぁルぁルぁルぁルぁぁぁぁ文文文文文‐–〜゠サンプル文々サンプル文</span>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
<hr />
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
58
tests/reftests/text/overflow-wrap.html
Normal file
58
tests/reftests/text/overflow-wrap.html
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>word-break</title>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||||
|
<script type="text/javascript" src="../../test.js"></script>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
font-family: Arial;
|
||||||
|
}
|
||||||
|
.normal {
|
||||||
|
width: 13em;
|
||||||
|
background: gold;
|
||||||
|
overflow-wrap: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.break-word {
|
||||||
|
width: 13em;
|
||||||
|
background: lime;
|
||||||
|
overflow-wrap: break-word;
|
||||||
|
}
|
||||||
|
|
||||||
|
.word-normal {
|
||||||
|
width: 13em;
|
||||||
|
background: gold;
|
||||||
|
word-wrap: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.word-break-word {
|
||||||
|
width: 13em;
|
||||||
|
background: lime;
|
||||||
|
word-wrap: break-word;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div>
|
||||||
|
<p>1. <code>overflow-wrap: normal</code></p>
|
||||||
|
<p class="normal">FStrPrivFinÄndG (Gesetz zur Änderung des
|
||||||
|
Fernstraßenbauprivatfinanzierungsgesetzes
|
||||||
|
und straßenverkehrsrechtlicher Vorschriften)</p>
|
||||||
|
<p>2. <code>overflow-wrap: break-word</code></p>
|
||||||
|
<p class="break-word">FStrPrivFinÄndG (Gesetz zur Änderung des
|
||||||
|
Fernstraßenbauprivatfinanzierungsgesetzes
|
||||||
|
und straßenverkehrsrechtlicher Vorschriften)</p>
|
||||||
|
<p>3. <code>word-wrap: normal</code></p>
|
||||||
|
<p class="word-normal">FStrPrivFinÄndG (Gesetz zur Änderung des
|
||||||
|
Fernstraßenbauprivatfinanzierungsgesetzes
|
||||||
|
und straßenverkehrsrechtlicher Vorschriften)</p>
|
||||||
|
<p>4. <code>word-wrap: break-word</code></p>
|
||||||
|
<p class="word-break-word">FStrPrivFinÄndG (Gesetz zur Änderung des
|
||||||
|
Fernstraßenbauprivatfinanzierungsgesetzes
|
||||||
|
und straßenverkehrsrechtlicher Vorschriften)</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
28
tests/reftests/text/thai.html
Normal file
28
tests/reftests/text/thai.html
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Thai text</title>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||||
|
<script type="text/javascript" src="../../test.js"></script>
|
||||||
|
<style>
|
||||||
|
.text-block {
|
||||||
|
width: 500px;
|
||||||
|
font-family: serif;
|
||||||
|
float:left;
|
||||||
|
text-align:justify;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div id="text" class="text-block">
|
||||||
|
<p>.....</p>
|
||||||
|
<p>ทดสอบ แบบกำหนดรูปแบบ ทำ ที นี่ นู่น นั่น นี้ มี หรือ ไม่ </p>
|
||||||
|
<p>ภาษาไทย เป็นภาษาราชการของประเทศไทย และภาษาแม่ของชาวไทย และชนเชื้อสายอื่นในประเทศไทย ภาษาไทยเป็นภาษาในกลุ่มภาษาไท ซึ่งเป็นกลุ่มย่อยของตระกูลภาษาไท-กะได สันนิษฐานว่า ภาษาในตระกูลนี้มีถิ่นกำเนิดจากทางตอนใต้ของประเทศจีน และนักภาษาศาสตร์บางส่วนเสนอว่า ภาษาไทยน่าจะมีความเชื่อมโยงกับตระกูลภาษาออสโตร-เอเชียติก ตระกูลภาษาออสโตรนีเซียน และตระกูลภาษาจีน-ทิเบต</p>
|
||||||
|
<p>ภาษาไทยเป็นภาษาที่มีระดับเสียงของคำแน่นอนหรือวรรณยุกต์เช่นเดียวกับภาษาจีน และออกเสียงแยกคำต่อคำ ทำให้เป็นที่ลำบากของชาวต่างชาติเนื่องจากการออกเสียงวรรณยุกต์ที่เป็นเอกลักษณ์ของแต่ละคำ และการสะกดคำที่ซับซ้อน</p>
|
||||||
|
<p>คำว่า ไทย หมายความว่า อิสรภาพ เสรีภาพ หรืออีกความหมายหนึ่งคือ ใหญ่ ยิ่งใหญ่ เพราะการจะเป็นอิสระได้จะต้องมีกำลังที่มากกว่า แข็งแกร่งกว่า เพื่อป้องกันการรุกรานจากข้าศึก คำนี้เป็นคำไทยแท้ที่เกิดจากการสร้างคำที่เรียก "การลากคำเข้าวัด" ซึ่งเป็นการลากความวิธีหนึ่ง ตามหลักคติชนวิทยา คนไทยเป็นชนชาติที่นับถือกันว่า ภาษาบาลี ซึ่งเป็นภาษาที่บันทึกพระธรรมคำสอนของพระพุทธเจ้าเป็นภาษาอันศักดิ์สิทธิ์และเป็นมงคล เมื่อคนไทยต้องการตั้งชื่อประเทศว่า ไท ซึ่งเป็นคำไทยแท้ จึงเติมตัว ย เข้าไปข้างท้าย เพื่อให้มีลักษณะคล้ายคำในภาษาบาลี - สันสกฤตเพื่อความเป็นมงคลตามความเชื่อของตน ภาษาไทยจึงหมายถึงภาษาของชนชาติไทยผู้เป็นไทนั่นเอง</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
50
tests/reftests/text/word-break.html
Normal file
50
tests/reftests/text/word-break.html
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>word-break</title>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||||
|
<script type="text/javascript" src="../../test.js"></script>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
font-family: Arial;
|
||||||
|
}
|
||||||
|
.narrow {
|
||||||
|
padding: 5px;
|
||||||
|
border: 1px solid;
|
||||||
|
width: 8em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.normal {
|
||||||
|
word-break: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.breakAll {
|
||||||
|
word-break: break-all;
|
||||||
|
}
|
||||||
|
|
||||||
|
.keep {
|
||||||
|
word-break: keep-all;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div>
|
||||||
|
<p>1. <code>word-break: normal</code></p>
|
||||||
|
<p class="normal narrow">This is a long and
|
||||||
|
Supercalifragilisticexpialidocious sentence.
|
||||||
|
次の単語グレートブリテンおよび北アイルランド連合王国で本当に大きな言葉</p>
|
||||||
|
|
||||||
|
<p>2. <code>word-break: break-all</code></p>
|
||||||
|
<p class="breakAll narrow">This is a long and
|
||||||
|
Supercalifragilisticexpialidocious sentence.
|
||||||
|
次の単語グレートブリテンおよび北アイルランド連合王国で本当に大きな言葉</p>
|
||||||
|
|
||||||
|
<p>3. <code>word-break: keep-all</code></p>
|
||||||
|
<p class="keep narrow">This is a long and
|
||||||
|
Supercalifragilisticexpialidocious sentence.
|
||||||
|
次の単語グレートブリテンおよび北アイルランド連合王国で本当に大きな言葉</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
Reference in New Issue
Block a user