mirror of
https://github.com/niklasvh/html2canvas.git
synced 2023-08-10 21:13:10 +03:00
Compare commits
9 Commits
Author | SHA1 | Date | |
---|---|---|---|
11d16d2b77 | |||
e9f7f48d57 | |||
4c360fc1f0 | |||
578bb771bf | |||
522e5aac5f | |||
dd6d8856ec | |||
45efe54da8 | |||
cd99f11b1b | |||
fa60716d07 |
22
CHANGELOG.md
22
CHANGELOG.md
@ -2,6 +2,28 @@
|
||||
|
||||
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
||||
|
||||
## [1.1.4](https://github.com/niklasvh/html2canvas/compare/v1.1.3...v1.1.4) (2021-07-15)
|
||||
|
||||
|
||||
### feat
|
||||
|
||||
* add support for webkit-text-stroke and paint-order (#2591) ([522e5aa](https://github.com/niklasvh/html2canvas/commit/522e5aac5fdad090953d095b5d558053a5e2d43d)), closes [#2591](https://github.com/niklasvh/html2canvas/issues/2591)
|
||||
|
||||
### fix
|
||||
|
||||
* don't copy 'all' css property (#2586) ([fa60716](https://github.com/niklasvh/html2canvas/commit/fa60716d07ed590ec64543a586a7960cbc8557df)), closes [#2586](https://github.com/niklasvh/html2canvas/issues/2586)
|
||||
* svg d path getting truncated on copy (#2589) ([dd6d885](https://github.com/niklasvh/html2canvas/commit/dd6d8856eca820a13a0990c467b9e531433fd4a9)), closes [#2589](https://github.com/niklasvh/html2canvas/issues/2589)
|
||||
* text position for form elements and list markers (#2588) ([cd99f11](https://github.com/niklasvh/html2canvas/commit/cd99f11b1b9eb1260a548a63e2a370a0a5ddafa0)), closes [#2588](https://github.com/niklasvh/html2canvas/issues/2588)
|
||||
* this.canvas.ownerDocument is undefined (#2590) ([45efe54](https://github.com/niklasvh/html2canvas/commit/45efe54da8145f97b9ee0463e686103280e3c8b1)), closes [#2590](https://github.com/niklasvh/html2canvas/issues/2590)
|
||||
* word-break seperators (#2593) ([e9f7f48](https://github.com/niklasvh/html2canvas/commit/e9f7f48d571304be14610a181feedca3c3b42864)), closes [#2593](https://github.com/niklasvh/html2canvas/issues/2593)
|
||||
|
||||
### test
|
||||
|
||||
* refactor language tests (#2594) ([4c360fc](https://github.com/niklasvh/html2canvas/commit/4c360fc1f059f4dcab71a79f9dc8a5b2e25411ea)), closes [#2594](https://github.com/niklasvh/html2canvas/issues/2594)
|
||||
* update box-shadow with radius ([578bb77](https://github.com/niklasvh/html2canvas/commit/578bb771bfeb7e81362e9e355d6cc9ae910e3920))
|
||||
|
||||
|
||||
|
||||
## [1.1.3](https://github.com/niklasvh/html2canvas/compare/v1.1.2...v1.1.3) (2021-07-14)
|
||||
|
||||
|
||||
|
@ -50,6 +50,7 @@ Below is a list of all the supported CSS properties and values.
|
||||
- overflow
|
||||
- overflow-wrap
|
||||
- padding
|
||||
- paint-order
|
||||
- position
|
||||
- right
|
||||
- text-align
|
||||
@ -64,6 +65,7 @@ Below is a list of all the supported CSS properties and values.
|
||||
- visibility
|
||||
- white-space
|
||||
- width
|
||||
- webkit-text-stroke
|
||||
- word-break
|
||||
- word-spacing
|
||||
- word-wrap
|
||||
|
2
package-lock.json
generated
2
package-lock.json
generated
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "html2canvas",
|
||||
"version": "1.1.3",
|
||||
"version": "1.1.4",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
|
@ -6,7 +6,7 @@
|
||||
"module": "dist/html2canvas.esm.js",
|
||||
"typings": "dist/types/index.d.ts",
|
||||
"browser": "dist/html2canvas.js",
|
||||
"version": "1.1.3",
|
||||
"version": "1.1.4",
|
||||
"author": {
|
||||
"name": "Niklas von Hertzen",
|
||||
"email": "niklasvh@gmail.com",
|
||||
|
@ -73,6 +73,9 @@ import {counterIncrement} from './property-descriptors/counter-increment';
|
||||
import {counterReset} from './property-descriptors/counter-reset';
|
||||
import {quotes} from './property-descriptors/quotes';
|
||||
import {boxShadow} from './property-descriptors/box-shadow';
|
||||
import {paintOrder} from './property-descriptors/paint-order';
|
||||
import {webkitTextStrokeColor} from './property-descriptors/webkit-text-stroke-color';
|
||||
import {webkitTextStrokeWidth} from './property-descriptors/webkit-text-stroke-width';
|
||||
|
||||
export class CSSParsedDeclaration {
|
||||
backgroundClip: ReturnType<typeof backgroundClip.parse>;
|
||||
@ -125,6 +128,7 @@ export class CSSParsedDeclaration {
|
||||
paddingRight: LengthPercentage;
|
||||
paddingBottom: LengthPercentage;
|
||||
paddingLeft: LengthPercentage;
|
||||
paintOrder: ReturnType<typeof paintOrder.parse>;
|
||||
position: ReturnType<typeof position.parse>;
|
||||
textAlign: ReturnType<typeof textAlign.parse>;
|
||||
textDecorationColor: Color;
|
||||
@ -134,6 +138,8 @@ export class CSSParsedDeclaration {
|
||||
transform: ReturnType<typeof transform.parse>;
|
||||
transformOrigin: ReturnType<typeof transformOrigin.parse>;
|
||||
visibility: ReturnType<typeof visibility.parse>;
|
||||
webkitTextStrokeColor: Color;
|
||||
webkitTextStrokeWidth: ReturnType<typeof webkitTextStrokeWidth.parse>;
|
||||
wordBreak: ReturnType<typeof wordBreak.parse>;
|
||||
zIndex: ReturnType<typeof zIndex.parse>;
|
||||
|
||||
@ -189,6 +195,7 @@ export class CSSParsedDeclaration {
|
||||
this.paddingRight = parse(paddingRight, declaration.paddingRight);
|
||||
this.paddingBottom = parse(paddingBottom, declaration.paddingBottom);
|
||||
this.paddingLeft = parse(paddingLeft, declaration.paddingLeft);
|
||||
this.paintOrder = parse(paintOrder, declaration.paintOrder);
|
||||
this.position = parse(position, declaration.position);
|
||||
this.textAlign = parse(textAlign, declaration.textAlign);
|
||||
this.textDecorationColor = parse(textDecorationColor, declaration.textDecorationColor ?? declaration.color);
|
||||
@ -201,6 +208,8 @@ export class CSSParsedDeclaration {
|
||||
this.transform = parse(transform, declaration.transform);
|
||||
this.transformOrigin = parse(transformOrigin, declaration.transformOrigin);
|
||||
this.visibility = parse(visibility, declaration.visibility);
|
||||
this.webkitTextStrokeColor = parse(webkitTextStrokeColor, declaration.webkitTextStrokeColor);
|
||||
this.webkitTextStrokeWidth = parse(webkitTextStrokeWidth, declaration.webkitTextStrokeWidth);
|
||||
this.wordBreak = parse(wordBreak, declaration.wordBreak);
|
||||
this.zIndex = parse(zIndex, declaration.zIndex);
|
||||
}
|
||||
|
@ -70,6 +70,9 @@ const breakText = (value: string, styles: CSSParsedDeclaration): string[] => {
|
||||
return styles.letterSpacing !== 0 ? toCodePoints(value).map((i) => fromCodePoint(i)) : breakWords(value, styles);
|
||||
};
|
||||
|
||||
// https://drafts.csswg.org/css-text/#word-separator
|
||||
const wordSeparators = [0x0020, 0x00a0, 0x1361, 0x10100, 0x10101, 0x1039, 0x1091];
|
||||
|
||||
const breakWords = (str: string, styles: CSSParsedDeclaration): string[] => {
|
||||
const breaker = LineBreaker(str, {
|
||||
lineBreak: styles.lineBreak,
|
||||
@ -81,7 +84,24 @@ const breakWords = (str: string, styles: CSSParsedDeclaration): string[] => {
|
||||
|
||||
while (!(bk = breaker.next()).done) {
|
||||
if (bk.value) {
|
||||
words.push(bk.value.slice());
|
||||
const value = bk.value.slice();
|
||||
const codePoints = toCodePoints(value);
|
||||
let word = '';
|
||||
codePoints.forEach((codePoint) => {
|
||||
if (wordSeparators.indexOf(codePoint) === -1) {
|
||||
word += fromCodePoint(codePoint);
|
||||
} else {
|
||||
if (word.length) {
|
||||
words.push(word);
|
||||
}
|
||||
words.push(fromCodePoint(codePoint));
|
||||
word = '';
|
||||
}
|
||||
});
|
||||
|
||||
if (word.length) {
|
||||
words.push(word);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
86
src/css/property-descriptors/__tests__/paint-order.ts
Normal file
86
src/css/property-descriptors/__tests__/paint-order.ts
Normal file
@ -0,0 +1,86 @@
|
||||
import {deepStrictEqual} from 'assert';
|
||||
import {Parser} from '../../syntax/parser';
|
||||
import {paintOrder, PAINT_ORDER_LAYER} from '../paint-order';
|
||||
|
||||
const paintOrderParse = (value: string) => paintOrder.parse(Parser.parseValues(value));
|
||||
|
||||
describe('property-descriptors', () => {
|
||||
describe('paint-order', () => {
|
||||
it('none', () =>
|
||||
deepStrictEqual(paintOrderParse('none'), [
|
||||
PAINT_ORDER_LAYER.FILL,
|
||||
PAINT_ORDER_LAYER.STROKE,
|
||||
PAINT_ORDER_LAYER.MARKERS
|
||||
]));
|
||||
|
||||
it('EMPTY', () =>
|
||||
deepStrictEqual(paintOrderParse(''), [
|
||||
PAINT_ORDER_LAYER.FILL,
|
||||
PAINT_ORDER_LAYER.STROKE,
|
||||
PAINT_ORDER_LAYER.MARKERS
|
||||
]));
|
||||
|
||||
it('other values', () =>
|
||||
deepStrictEqual(paintOrderParse('other values'), [
|
||||
PAINT_ORDER_LAYER.FILL,
|
||||
PAINT_ORDER_LAYER.STROKE,
|
||||
PAINT_ORDER_LAYER.MARKERS
|
||||
]));
|
||||
|
||||
it('normal', () =>
|
||||
deepStrictEqual(paintOrderParse('normal'), [
|
||||
PAINT_ORDER_LAYER.FILL,
|
||||
PAINT_ORDER_LAYER.STROKE,
|
||||
PAINT_ORDER_LAYER.MARKERS
|
||||
]));
|
||||
|
||||
it('stroke', () =>
|
||||
deepStrictEqual(paintOrderParse('stroke'), [
|
||||
PAINT_ORDER_LAYER.STROKE,
|
||||
PAINT_ORDER_LAYER.FILL,
|
||||
PAINT_ORDER_LAYER.MARKERS
|
||||
]));
|
||||
|
||||
it('fill', () =>
|
||||
deepStrictEqual(paintOrderParse('fill'), [
|
||||
PAINT_ORDER_LAYER.FILL,
|
||||
PAINT_ORDER_LAYER.STROKE,
|
||||
PAINT_ORDER_LAYER.MARKERS
|
||||
]));
|
||||
|
||||
it('markers', () =>
|
||||
deepStrictEqual(paintOrderParse('markers'), [
|
||||
PAINT_ORDER_LAYER.MARKERS,
|
||||
PAINT_ORDER_LAYER.FILL,
|
||||
PAINT_ORDER_LAYER.STROKE
|
||||
]));
|
||||
|
||||
it('stroke fill', () =>
|
||||
deepStrictEqual(paintOrderParse('stroke fill'), [
|
||||
PAINT_ORDER_LAYER.STROKE,
|
||||
PAINT_ORDER_LAYER.FILL,
|
||||
PAINT_ORDER_LAYER.MARKERS
|
||||
]));
|
||||
|
||||
it('markers stroke', () =>
|
||||
deepStrictEqual(paintOrderParse('markers stroke'), [
|
||||
PAINT_ORDER_LAYER.MARKERS,
|
||||
PAINT_ORDER_LAYER.STROKE,
|
||||
PAINT_ORDER_LAYER.FILL
|
||||
]));
|
||||
|
||||
it('markers stroke fill', () =>
|
||||
deepStrictEqual(paintOrderParse('markers stroke fill'), [
|
||||
PAINT_ORDER_LAYER.MARKERS,
|
||||
PAINT_ORDER_LAYER.STROKE,
|
||||
PAINT_ORDER_LAYER.FILL
|
||||
]));
|
||||
|
||||
it('stroke fill markers', () =>
|
||||
deepStrictEqual(paintOrderParse('stroke fill markers'), [
|
||||
PAINT_ORDER_LAYER.STROKE,
|
||||
PAINT_ORDER_LAYER.FILL,
|
||||
PAINT_ORDER_LAYER.MARKERS
|
||||
]));
|
||||
});
|
||||
});
|
41
src/css/property-descriptors/paint-order.ts
Normal file
41
src/css/property-descriptors/paint-order.ts
Normal file
@ -0,0 +1,41 @@
|
||||
import {IPropertyListDescriptor, PropertyDescriptorParsingType} from '../IPropertyDescriptor';
|
||||
import {CSSValue, isIdentToken} from '../syntax/parser';
|
||||
export enum PAINT_ORDER_LAYER {
|
||||
FILL,
|
||||
STROKE,
|
||||
MARKERS
|
||||
}
|
||||
|
||||
export type PaintOrder = PAINT_ORDER_LAYER[];
|
||||
|
||||
export const paintOrder: IPropertyListDescriptor<PaintOrder> = {
|
||||
name: 'paint-order',
|
||||
initialValue: 'normal',
|
||||
prefix: false,
|
||||
type: PropertyDescriptorParsingType.LIST,
|
||||
parse: (tokens: CSSValue[]): PaintOrder => {
|
||||
const DEFAULT_VALUE = [PAINT_ORDER_LAYER.FILL, PAINT_ORDER_LAYER.STROKE, PAINT_ORDER_LAYER.MARKERS];
|
||||
let layers: PaintOrder = [];
|
||||
|
||||
tokens.filter(isIdentToken).forEach((token) => {
|
||||
switch (token.value) {
|
||||
case 'stroke':
|
||||
layers.push(PAINT_ORDER_LAYER.STROKE);
|
||||
break;
|
||||
case 'fill':
|
||||
layers.push(PAINT_ORDER_LAYER.FILL);
|
||||
break;
|
||||
case 'markers':
|
||||
layers.push(PAINT_ORDER_LAYER.MARKERS);
|
||||
break;
|
||||
}
|
||||
});
|
||||
DEFAULT_VALUE.forEach((value) => {
|
||||
if (layers.indexOf(value) === -1) {
|
||||
layers.push(value);
|
||||
}
|
||||
});
|
||||
|
||||
return layers;
|
||||
}
|
||||
};
|
8
src/css/property-descriptors/webkit-text-stroke-color.ts
Normal file
8
src/css/property-descriptors/webkit-text-stroke-color.ts
Normal file
@ -0,0 +1,8 @@
|
||||
import {IPropertyTypeValueDescriptor, PropertyDescriptorParsingType} from '../IPropertyDescriptor';
|
||||
export const webkitTextStrokeColor: IPropertyTypeValueDescriptor = {
|
||||
name: `-webkit-text-stroke-color`,
|
||||
initialValue: 'currentcolor',
|
||||
prefix: false,
|
||||
type: PropertyDescriptorParsingType.TYPE_VALUE,
|
||||
format: 'color'
|
||||
};
|
14
src/css/property-descriptors/webkit-text-stroke-width.ts
Normal file
14
src/css/property-descriptors/webkit-text-stroke-width.ts
Normal file
@ -0,0 +1,14 @@
|
||||
import {CSSValue, isDimensionToken} from '../syntax/parser';
|
||||
import {IPropertyValueDescriptor, PropertyDescriptorParsingType} from '../IPropertyDescriptor';
|
||||
export const webkitTextStrokeWidth: IPropertyValueDescriptor<number> = {
|
||||
name: `-webkit-text-stroke-width`,
|
||||
initialValue: '0',
|
||||
type: PropertyDescriptorParsingType.VALUE,
|
||||
prefix: false,
|
||||
parse: (token: CSSValue): number => {
|
||||
if (isDimensionToken(token)) {
|
||||
return token.number;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
};
|
@ -443,12 +443,17 @@ const iframeLoader = (iframe: HTMLIFrameElement): Promise<HTMLIFrameElement> =>
|
||||
});
|
||||
};
|
||||
|
||||
const ignoredStyleProperties = [
|
||||
'all', // #2476
|
||||
'd', // #2483
|
||||
'content' // Safari shows pseudoelements if content is set
|
||||
];
|
||||
|
||||
export const copyCSSStyles = <T extends HTMLElement | SVGElement>(style: CSSStyleDeclaration, target: T): T => {
|
||||
// Edge does not provide value for cssText
|
||||
for (let i = style.length - 1; i >= 0; i--) {
|
||||
const property = style.item(i);
|
||||
// Safari shows pseudoelements if content is set
|
||||
if (property !== 'content') {
|
||||
if (ignoredStyleProperties.indexOf(property) === -1) {
|
||||
target.style.setProperty(property, style.getPropertyValue(property));
|
||||
}
|
||||
}
|
||||
|
@ -43,6 +43,7 @@ import {TextareaElementContainer} from '../../dom/elements/textarea-element-cont
|
||||
import {SelectElementContainer} from '../../dom/elements/select-element-container';
|
||||
import {IFrameElementContainer} from '../../dom/replaced-elements/iframe-element-container';
|
||||
import {TextShadow} from '../../css/property-descriptors/text-shadow';
|
||||
import {PAINT_ORDER_LAYER} from '../../css/property-descriptors/paint-order';
|
||||
|
||||
export type RenderConfigurations = RenderOptions & {
|
||||
backgroundColor: Color | null;
|
||||
@ -179,11 +180,15 @@ export class CanvasRenderer {
|
||||
const [font, fontFamily, fontSize] = this.createFontStyle(styles);
|
||||
|
||||
this.ctx.font = font;
|
||||
this.ctx.textBaseline = 'alphabetic';
|
||||
|
||||
this.ctx.textBaseline = 'alphabetic';
|
||||
const {baseline, middle} = this.fontMetrics.getMetrics(fontFamily, fontSize);
|
||||
const paintOrder = styles.paintOrder;
|
||||
|
||||
text.textBounds.forEach((text) => {
|
||||
paintOrder.forEach((paintOrderLayer) => {
|
||||
switch (paintOrderLayer) {
|
||||
case PAINT_ORDER_LAYER.FILL:
|
||||
this.ctx.fillStyle = asString(styles.color);
|
||||
this.renderTextWithLetterSpacing(text, styles.letterSpacing, baseline);
|
||||
const textShadows: TextShadow = styles.textShadow;
|
||||
@ -224,7 +229,12 @@ export class CanvasRenderer {
|
||||
|
||||
break;
|
||||
case TEXT_DECORATION_LINE.OVERLINE:
|
||||
this.ctx.fillRect(text.bounds.left, Math.round(text.bounds.top), text.bounds.width, 1);
|
||||
this.ctx.fillRect(
|
||||
text.bounds.left,
|
||||
Math.round(text.bounds.top),
|
||||
text.bounds.width,
|
||||
1
|
||||
);
|
||||
break;
|
||||
case TEXT_DECORATION_LINE.LINE_THROUGH:
|
||||
// TODO try and find exact position for line-through
|
||||
@ -238,6 +248,20 @@ export class CanvasRenderer {
|
||||
}
|
||||
});
|
||||
}
|
||||
break;
|
||||
case PAINT_ORDER_LAYER.STROKE:
|
||||
if (styles.webkitTextStrokeWidth && text.text.trim().length) {
|
||||
this.ctx.strokeStyle = asString(styles.webkitTextStrokeColor);
|
||||
this.ctx.lineWidth = styles.webkitTextStrokeWidth;
|
||||
this.ctx.lineJoin = !!(window as any).chrome ? 'miter' : 'round';
|
||||
this.ctx.strokeText(text.text, text.bounds.left, text.bounds.top + baseline);
|
||||
}
|
||||
this.ctx.strokeStyle = '';
|
||||
this.ctx.lineWidth = 0;
|
||||
this.ctx.lineJoin = 'miter';
|
||||
break;
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@ -376,7 +400,7 @@ export class CanvasRenderer {
|
||||
this.ctx.font = fontFamily;
|
||||
this.ctx.fillStyle = asString(styles.color);
|
||||
|
||||
this.ctx.textBaseline = 'middle';
|
||||
this.ctx.textBaseline = 'alphabetic';
|
||||
this.ctx.textAlign = canvasTextAlign(container.styles.textAlign);
|
||||
|
||||
const bounds = contentBox(container);
|
||||
@ -409,7 +433,7 @@ export class CanvasRenderer {
|
||||
baseline
|
||||
);
|
||||
this.ctx.restore();
|
||||
this.ctx.textBaseline = 'bottom';
|
||||
this.ctx.textBaseline = 'alphabetic';
|
||||
this.ctx.textAlign = 'left';
|
||||
}
|
||||
|
||||
@ -427,7 +451,7 @@ export class CanvasRenderer {
|
||||
}
|
||||
}
|
||||
} else if (paint.listValue && container.styles.listStyleType !== LIST_STYLE_TYPE.NONE) {
|
||||
const [fontFamily, fontSize] = this.createFontStyle(styles);
|
||||
const [fontFamily] = this.createFontStyle(styles);
|
||||
|
||||
this.ctx.font = fontFamily;
|
||||
this.ctx.fillStyle = asString(styles.color);
|
||||
@ -441,12 +465,10 @@ export class CanvasRenderer {
|
||||
computeLineHeight(styles.lineHeight, styles.fontSize.number) / 2 + 1
|
||||
);
|
||||
|
||||
const {baseline} = this.fontMetrics.getMetrics(fontFamily, fontSize);
|
||||
|
||||
this.renderTextWithLetterSpacing(
|
||||
new TextBounds(paint.listValue, bounds),
|
||||
styles.letterSpacing,
|
||||
baseline
|
||||
computeLineHeight(styles.lineHeight, styles.fontSize.number) / 2 + 2
|
||||
);
|
||||
this.ctx.textBaseline = 'bottom';
|
||||
this.ctx.textAlign = 'left';
|
||||
@ -554,7 +576,8 @@ export class CanvasRenderer {
|
||||
return image;
|
||||
}
|
||||
|
||||
const canvas = (this.canvas.ownerDocument as Document).createElement('canvas');
|
||||
const ownerDocument = this.canvas.ownerDocument ?? document;
|
||||
const canvas = ownerDocument.createElement('canvas');
|
||||
canvas.width = Math.max(1, width);
|
||||
canvas.height = Math.max(1, height);
|
||||
const ctx = canvas.getContext('2d') as CanvasRenderingContext2D;
|
||||
|
@ -9,7 +9,7 @@
|
||||
margin: 10px;
|
||||
display: inline-block;
|
||||
min-height: 50px;
|
||||
// border-radius: 10px;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
body {
|
||||
|
@ -40,5 +40,13 @@
|
||||
<text x="65" y="35" class="canvas">canvas</text>
|
||||
</svg>
|
||||
<img width="200" height="200" src="data:image/svg+xml;base64,PHN2ZyB4bWxuczpzdmc9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZlcnNpb249IjEuMSIgd2lkdGg9IjMwNiIgaGVpZ2h0PSIyOTYiPjxkZWZzIGlkPSJkZWZzNCIgLz48ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtMTYyLjQ2OTk1LC00NzcuMjg2MykiIGlkPSJsYXllcjEiPjxwYXRoIGQ9Im0gMzE0LjE1NzQ1LDQ4MS42OTU1OCBjIC01OS4yMDA4OSwwLjUzNzc0IC0xMTQuODA5NzksMzYuNzIyMTkgLTEzNy4zMTI1LDk1LjM0Mzc1IC0yOS4zOTEyOSw3Ni41NjY5MyA4LjgzOTMyLDE2Mi40NTI0NiA4NS40MDYyNSwxOTEuODQzNzUgbCAzNC4wMzEyNSwtODguNjg3NSBjIC0yMC4wNjc4LC03LjcxMzU4IC0zNC4zMTI1LC0yNy4xNTMyNCAtMzQuMzEyNSwtNDkuOTM3NSAwLC0yOS41NDcyMyAyMy45NTI3NywtNTMuNSA1My41LC01My41IDI5LjU0NzIzLDAgNTMuNSwyMy45NTI3NyA1My41LDUzLjUgMCwyMi43ODQyNiAtMTQuMjQ0Nyw0Mi4yMjM5MiAtMzQuMzEyNSw0OS45Mzc1IGwgMzQuMDMxMjUsODguNjg3NSBjIDM5LjI5MDg1LC0xNS4wODIzNCA3MC4zMjM5LC00Ni4xMTU0IDg1LjQwNjI1LC04NS40MDYyNSAyOS4zOTEyOSwtNzYuNTY2OTMgLTguODM5MzIsLTE2Mi40ODM3MSAtODUuNDA2MjUsLTE5MS44NzUgLTE3Ljk0NTM3LC02Ljg4ODU5IC0zNi40MDg1MywtMTAuMDcwODcgLTU0LjUzMTI1LC05LjkwNjI1IHoiIGlkPSJwYXRoMjgzMCIgc3R5bGU9ImZpbGw6IzQwYWE1NDtmaWxsLW9wYWNpdHk6MTtzdHJva2U6IzIwNTUyYTtzdHJva2Utd2lkdGg6Ny45OTk5OTk1MjtzdHJva2UtbWl0ZXJsaW1pdDo0O3N0cm9rZS1vcGFjaXR5OjE7c3Ryb2tlLWRhc2hhcnJheTpub25lIiAvPjwvZz48L3N2Zz4=" /></div>
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width=50 height=20>
|
||||
<g data-z-index="0.1" opacity="1" transform="translate(-974,-30) scale(1 1)">
|
||||
<path fill="#7cb5ec" d="M 990 37.734399999999994 A 4 4 0 1 1 990.0039999993332 37.73439800000016 Z" opacity="1" stroke-width="0.00015790535835003006"></path>
|
||||
<path fill="#7cb5ec" d="M 999 37.734399999999994 A 4 4 0 1 1 999.0039999993332 37.73439800000016 Z" opacity="1" stroke-width="0.00015790535835003006"></path>
|
||||
<path fill="#7cb5ec" d="M 1009 37.734399999999994 A 4 4 0 1 1 1009.0039999993332 37.73439800000016 Z" opacity="1" stroke-width="0.00015790535835003006"></path>
|
||||
<path fill="#7cb5ec" d="M 1019 37.734399999999994 A 4 4 0 1 1 1019.0039999993332 37.73439800000016 Z" opacity="1" stroke-width="0.00015790535835003006"></path>
|
||||
</g>
|
||||
</svg>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -3,7 +3,7 @@
|
||||
<head>
|
||||
<title>Chinese text</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<script type="text/javascript" src="../../test.js"></script>
|
||||
<script type="text/javascript" src="../../../test.js"></script>
|
||||
<style>
|
||||
.chn-text-block {
|
||||
width: 500px;
|
26
tests/reftests/text/lang/persian.html
Normal file
26
tests/reftests/text/lang/persian.html
Normal file
@ -0,0 +1,26 @@
|
||||
<!DOCTYPE html>
|
||||
<html dir="rtl" lang="fa-IR">
|
||||
<head>
|
||||
<title>Persian rtl</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{
|
||||
padding: 10px 25px;
|
||||
direction: rtl;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="test" lang="fa">
|
||||
<p>
|
||||
سلام دنیا! این یک تست است...
|
||||
</p>
|
||||
</div>
|
||||
<span class="test" lang="fa">من میتوانم. این است قدرت جاوااسکریپت!</span>
|
||||
</body>
|
||||
</html>
|
@ -3,7 +3,7 @@
|
||||
<head>
|
||||
<title>Thai text</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<script type="text/javascript" src="../../test.js"></script>
|
||||
<script type="text/javascript" src="../../../test.js"></script>
|
||||
<style>
|
||||
.text-block {
|
||||
width: 500px;
|
@ -1,6 +1,6 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<head>
|
||||
<title>Text tests</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<script type="text/javascript" src="../../test.js"></script>
|
||||
@ -8,25 +8,30 @@
|
||||
body {
|
||||
font-family: Arial;
|
||||
}
|
||||
.small{
|
||||
font-size:14px;
|
||||
|
||||
.small {
|
||||
font-size: 14px;
|
||||
line-height: 1vw;
|
||||
}
|
||||
|
||||
.medium{
|
||||
font-size:18px;
|
||||
.medium {
|
||||
font-size: 18px;
|
||||
line-height: 2vw;
|
||||
}
|
||||
.large{
|
||||
font-size:24px;
|
||||
|
||||
.large {
|
||||
font-size: 24px;
|
||||
line-height: 3vw;
|
||||
}
|
||||
div{
|
||||
float:left;
|
||||
|
||||
div {
|
||||
float: left;
|
||||
}
|
||||
|
||||
h2 {
|
||||
clear:both;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 36px;
|
||||
line-height: 4vw;
|
||||
@ -41,11 +46,18 @@
|
||||
font-size: 16px;
|
||||
line-height: 2vw;
|
||||
}
|
||||
|
||||
.raw {
|
||||
font-size: 60px;
|
||||
word-spacing: 30px;
|
||||
}
|
||||
</style>
|
||||
|
||||
</head>
|
||||
<body> <h1><h1> text-decoration</h1>
|
||||
<div style="font-family:Arial;">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h1><h1> text-decoration</h1>
|
||||
<div style="font-family:Arial;">
|
||||
<h2>Arial</h2>
|
||||
<ol class="small">
|
||||
<li style="text-decoration:none;">text-decoration:none;</li>
|
||||
@ -66,9 +78,9 @@
|
||||
<li style="text-decoration:overline;">text-decoration:overline;</li>
|
||||
<li style="text-decoration:line-through;">text-decoration:line-through;</li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="font-family:Verdana;">
|
||||
<div style="font-family:Verdana;">
|
||||
<h2>Verdana</h2>
|
||||
<ol class="small">
|
||||
<li style="text-decoration:none;">text-decoration:none;</li>
|
||||
@ -77,18 +89,8 @@
|
||||
<li style="text-decoration:line-through;">text-decoration:line-through;</li>
|
||||
</ol>
|
||||
|
||||
<ol class="medium">
|
||||
<li style="text-decoration:none;">text-decoration:none;</li>
|
||||
<li style="text-decoration:underline;">text-decoration:underline;</li>
|
||||
<li style="text-decoration:overline;">text-decoration:overline;</li>
|
||||
<li style="text-decoration:line-through;">text-decoration:line-through;</li>
|
||||
</ol>
|
||||
<ol class="large">
|
||||
<li style="text-decoration:none;">text-decoration:none;</li>
|
||||
<li style="text-decoration:underline;">text-decoration:underline;</li>
|
||||
<li style="text-decoration:overline;">text-decoration:overline;</li>
|
||||
<li style="text-decoration:line-through;">text-decoration:line-through;</li>
|
||||
</ol>
|
||||
<div class="raw">
|
||||
<span>[AB / CD]</span>
|
||||
</div>
|
||||
|
||||
<div style="font-family:Tahoma;">
|
||||
@ -117,21 +119,27 @@
|
||||
<h2><h2> text-transform</h2>
|
||||
<ul>
|
||||
<li style="text-transform:none;">text-transform:none;</li>
|
||||
<li style="text-transform:capitalize;">text-transform: capitalize; (including foreign characters such as Öaäå)</li>
|
||||
<li style="text-transform:capitalize;">text-transform: capitalize; (including foreign characters such as Öaäå)
|
||||
</li>
|
||||
<li style="text-transform:uppercase;">text-transform:uppercase;</li>
|
||||
<li style="text-transform:lowercase;">text-transform:lowercase;</li>
|
||||
</ul>
|
||||
<h3><h3> misc text alignments</h3>
|
||||
<ul>
|
||||
<li style="word-spacing:5px;">word-spacing:5px; (as each letter is rendered individually, the bounds will always be correct)</li>
|
||||
<li style="line-height:35px;">line-height:35px; <br />(same goes for line-height)</li>
|
||||
<li style="word-spacing:5px;">word-spacing:5px; (as each letter is rendered individually, the bounds will always
|
||||
be correct)
|
||||
</li>
|
||||
<li style="line-height:35px;">line-height:35px; <br/>(same goes for line-height)</li>
|
||||
<li style="letter-spacing:5px;">letter-spacing:5px;</li>
|
||||
<li style="letter-spacing:0.9px;">letter-spacing:0.9px;</li>
|
||||
<li style="text-align:right;width:300px;">text-align:right;width:300px;</li>
|
||||
<li style="font-variant:small-caps;">font-variant:small-caps; </li>
|
||||
<li style="font-variant:small-caps;">font-variant:small-caps;</li>
|
||||
</ul>
|
||||
|
||||
<div style="font-family: 'Inconsolata', Monaco, Consolas, 'Andale Mono', monospace">npm install --save html2canvas</div>
|
||||
|
||||
</body>
|
||||
<div class="raw" style="">
|
||||
<span>[AB / CD]</span>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
Reference in New Issue
Block a user