diff --git a/CHANGELOG.md b/CHANGELOG.md index e70337930e9..1ee3666aed2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## [next] +- chore(TS): Remove @ts-nocheck from Text class. [#9018](https://github.com/fabricjs/fabric.js/pull/9018) - Fix(Textbox) minimum word width calculation across all lines [#9004](https://github.com/fabricjs/fabric.js/pull/9004) - ci(): add Jest for the unit tests [#8919](https://github.com/fabricjs/fabric.js/pull/8919) - ci(): Revert "invoke tests after changelog action (#8974)" [#9013](https://github.com/fabricjs/fabric.js/pull/9013) diff --git a/src/canvas/DOMManagers/CanvasDOMManager.ts b/src/canvas/DOMManagers/CanvasDOMManager.ts index 392b43d48f9..3c0fd78abdc 100644 --- a/src/canvas/DOMManagers/CanvasDOMManager.ts +++ b/src/canvas/DOMManagers/CanvasDOMManager.ts @@ -82,8 +82,8 @@ export class CanvasDOMManager extends StaticCanvasDOMManager { ) { setStyle(element, { position: 'absolute', - left: 0, - top: 0, + left: '0', + top: '0', }); allowTouchScrolling(element, allow); makeElementUnselectable(element); diff --git a/src/parser/applyViewboxTransform.ts b/src/parser/applyViewboxTransform.ts index 625ef9a98d1..e4f81f9208a 100644 --- a/src/parser/applyViewboxTransform.ts +++ b/src/parser/applyViewboxTransform.ts @@ -1,4 +1,4 @@ -//@ts-nocheck +// @ts-nocheck import { svgNS } from './constants'; import { parsePreserveAspectRatioAttribute, @@ -10,7 +10,7 @@ import { NONE } from '../constants'; * Add a element that envelop all child elements and makes the viewbox transformMatrix descend on all elements */ -export function applyViewboxTransform(element) { +export function applyViewboxTransform(element: HTMLElement) { if (!svgViewBoxElementsRegEx.test(element.nodeName)) { return {}; } @@ -25,13 +25,12 @@ export function applyViewboxTransform(element) { const heightAttr = element.getAttribute('height'); const x = element.getAttribute('x') || 0; const y = element.getAttribute('y') || 0; - let preserveAspectRatio = element.getAttribute('preserveAspectRatio') || ''; const missingViewBox = !viewBoxAttr || !(viewBoxAttr = viewBoxAttr.match(reViewBoxAttrValue)); const missingDimAttr = !widthAttr || !heightAttr || widthAttr === '100%' || heightAttr === '100%'; const toBeParsed = missingViewBox && missingDimAttr; - const parsedDim = {}; + const parsedDim: any = {}; let translateMatrix = ''; let widthDiff = 0; let heightDiff = 0; @@ -84,7 +83,9 @@ export function applyViewboxTransform(element) { } // default is to preserve aspect ratio - preserveAspectRatio = parsePreserveAspectRatioAttribute(preserveAspectRatio); + const preserveAspectRatio = parsePreserveAspectRatioAttribute( + element.getAttribute('preserveAspectRatio') || '' + ); if (preserveAspectRatio.alignX !== NONE) { //translate all container for the effect of Mid, Min, Max if (preserveAspectRatio.meetOrSlice === 'meet') { diff --git a/src/parser/doesSomeParentMatch.ts b/src/parser/doesSomeParentMatch.ts index b1e60b34527..1356355dd41 100644 --- a/src/parser/doesSomeParentMatch.ts +++ b/src/parser/doesSomeParentMatch.ts @@ -1,19 +1,18 @@ -//@ts-nocheck import { selectorMatches } from './selectorMatches'; -export function doesSomeParentMatch(element, selectors) { - let selector, +export function doesSomeParentMatch(element: HTMLElement, selectors: string[]) { + let selector: string, parentMatching = true; while ( - element.parentNode && - element.parentNode.nodeType === 1 && + element.parentElement && + element.parentElement.nodeType === 1 && selectors.length ) { if (parentMatching) { - selector = selectors.pop(); + selector = selectors.pop()!; } - element = element.parentNode; - parentMatching = selectorMatches(element, selector); + element = element.parentElement; + parentMatching = selectorMatches(element, selector!); } return selectors.length === 0; } diff --git a/src/parser/getCSSRules.ts b/src/parser/getCSSRules.ts index b746573b29f..745d3570aec 100644 --- a/src/parser/getCSSRules.ts +++ b/src/parser/getCSSRules.ts @@ -1,23 +1,23 @@ -//@ts-nocheck - /** * Returns CSS rules for a given SVG document * @param {SVGDocument} doc SVG document to parse * @return {Object} CSS rules of this document */ -export function getCSSRules(doc) { +export function getCSSRules(doc: Document) { const styles = doc.getElementsByTagName('style'); let i; let len; - const allRules = {}; + const allRules: Record> = {}; let rules; // very crude parsing of style contents for (i = 0, len = styles.length; i < len; i++) { - let styleContents = styles[i].textContent; + const styleContents = (styles[i].textContent || '').replace( + // remove comments + /\/\*[\s\S]*?\*\//g, + '' + ); - // remove comments - styleContents = styleContents.replace(/\/\*[\s\S]*?\*\//g, ''); if (styleContents.trim() === '') { continue; } @@ -32,7 +32,7 @@ export function getCSSRules(doc) { // eslint-disable-next-line no-loop-func rules.forEach(function (rule) { const match = rule.split('{'), - ruleObj = {}, + ruleObj: Record = {}, declaration = match[1].trim(), propertyValuePairs = declaration.split(';').filter(function (pair) { return pair.trim(); @@ -45,16 +45,15 @@ export function getCSSRules(doc) { ruleObj[property] = value; } rule = match[0].trim(); - rule.split(',').forEach(function (_rule) { + rule.split(',').forEach((_rule) => { _rule = _rule.replace(/^svg/i, '').trim(); if (_rule === '') { return; } - if (allRules[_rule]) { - Object.assign(allRules[_rule], ruleObj); - } else { - allRules[_rule] = Object.assign({}, ruleObj); - } + allRules[_rule] = { + ...(allRules[_rule] || {}), + ...ruleObj, + }; }); }); } diff --git a/src/parser/getSvgRegex.ts b/src/parser/getSvgRegex.ts index 1ea5aa6f5b4..3aa987a298b 100644 --- a/src/parser/getSvgRegex.ts +++ b/src/parser/getSvgRegex.ts @@ -1,5 +1,3 @@ -//@ts-nocheck - -export function getSvgRegex(arr) { +export function getSvgRegex(arr: string[]) { return new RegExp('^(' + arr.join('|') + ')\\b', 'i'); } diff --git a/src/shapes/IText/IText.ts b/src/shapes/IText/IText.ts index 9b0af1d67da..26a5a5eb093 100644 --- a/src/shapes/IText/IText.ts +++ b/src/shapes/IText/IText.ts @@ -514,7 +514,7 @@ export class IText< } ctx.fillStyle = this.cursorColor || - this.getValueOfPropertyAt(lineIndex, charIndex, 'fill'); + (this.getValueOfPropertyAt(lineIndex, charIndex, 'fill') as string); ctx.globalAlpha = this._currentCursorOpacity; ctx.fillRect( boundaries.left + boundaries.leftOffset - cursorWidth / 2, @@ -668,7 +668,7 @@ export class IText< * Unused by the library, is for the end user * @return {String | TFiller} Character color (fill) */ - getCurrentCharColor(): string | TFiller { + getCurrentCharColor(): string | TFiller | null { const cp = this._getCurrentCharIndex(); return this.getValueOfPropertyAt(cp.l, cp.c, 'fill'); } diff --git a/src/shapes/Text/StyledText.ts b/src/shapes/Text/StyledText.ts index c188a84c1c4..a623459e697 100644 --- a/src/shapes/Text/StyledText.ts +++ b/src/shapes/Text/StyledText.ts @@ -10,7 +10,9 @@ import type { StylePropertiesType } from './constants'; import type { Text } from './Text'; import { pick } from '../../util'; -export type TextStyleDeclaration = Partial>; +export type CompleteTextStyleDeclaration = Pick; + +export type TextStyleDeclaration = Partial; export type TextStyle = { [line: number | string]: { [char: number | string]: TextStyleDeclaration }; @@ -179,21 +181,18 @@ export abstract class StyledText< } } - private _extendStyles(index: number, styles: TextStyleDeclaration) { + private _extendStyles(index: number, styles: TextStyleDeclaration): void { const { lineIndex, charIndex } = this.get2DCursorLocation(index); if (!this._getLineStyle(lineIndex)) { this._setLineStyle(lineIndex); } - if (!this._getStyleDeclaration(lineIndex, charIndex)) { + if (!Object.keys(this._getStyleDeclaration(lineIndex, charIndex)).length) { this._setStyleDeclaration(lineIndex, charIndex, {}); } - return Object.assign( - this._getStyleDeclaration(lineIndex, charIndex) || {}, - styles - ); + Object.assign(this._getStyleDeclaration(lineIndex, charIndex), styles); } /** @@ -224,11 +223,9 @@ export abstract class StyledText< */ getStyleAtPosition(position: number, complete?: boolean) { const { lineIndex, charIndex } = this.get2DCursorLocation(position); - return ( - (complete - ? this.getCompleteStyleDeclaration(lineIndex, charIndex) - : this._getStyleDeclaration(lineIndex, charIndex)) || {} - ); + return complete + ? this.getCompleteStyleDeclaration(lineIndex, charIndex) + : this._getStyleDeclaration(lineIndex, charIndex); } /** @@ -246,14 +243,18 @@ export abstract class StyledText< } /** - * get the reference, not a clone, of the style object for a given character + * get the reference, not a clone, of the style object for a given character, + * if not style is set for a pre det * @param {Number} lineIndex * @param {Number} charIndex - * @return {Object} style object + * @return {Object} style object a REFERENCE to the existing one or a new empty object */ - _getStyleDeclaration(lineIndex: number, charIndex: number) { + _getStyleDeclaration( + lineIndex: number, + charIndex: number + ): TextStyleDeclaration { const lineStyle = this.styles && this.styles[lineIndex]; - return lineStyle ? lineStyle[charIndex] : null; + return lineStyle ? lineStyle[charIndex] ?? {} : {}; } /** @@ -263,12 +264,15 @@ export abstract class StyledText< * @param {Number} charIndex position of the character on the line * @return {Object} style object */ - getCompleteStyleDeclaration(lineIndex: number, charIndex: number) { + getCompleteStyleDeclaration( + lineIndex: number, + charIndex: number + ): CompleteTextStyleDeclaration { return { // @ts-expect-error readonly ...pick(this, (this.constructor as typeof StyledText)._styleProperties), - ...(this._getStyleDeclaration(lineIndex, charIndex) || {}), - } as TextStyleDeclaration; + ...this._getStyleDeclaration(lineIndex, charIndex), + } as CompleteTextStyleDeclaration; } /** diff --git a/src/shapes/Text/Text.ts b/src/shapes/Text/Text.ts index c0bf59ecb33..0aa63745412 100644 --- a/src/shapes/Text/Text.ts +++ b/src/shapes/Text/Text.ts @@ -1,12 +1,15 @@ -// @ts-nocheck import { cache } from '../../cache'; import { DEFAULT_SVG_FONT_SIZE } from '../../constants'; import type { ObjectEvents } from '../../EventTypeDefs'; -import type { TextStyle, TextStyleDeclaration } from './StyledText'; +import type { + CompleteTextStyleDeclaration, + TextStyle, + TextStyleDeclaration, +} from './StyledText'; import { StyledText } from './StyledText'; import { SHARED_ATTRIBUTES } from '../../parser/attributes'; import { parseAttributes } from '../../parser/parseAttributes'; -import type { Point } from '../../Point'; +import type { XY } from '../../Point'; import type { TCacheCanvasDimensions, TClassProperties, @@ -30,6 +33,7 @@ import type { SerializedObjectProps, TProps, } from '../Object/types'; +import type { StylePropertiesType } from './constants'; import { additionalProps, textDefaultValues, @@ -40,6 +44,8 @@ import { JUSTIFY_RIGHT, } from './constants'; import { CENTER, LEFT, RIGHT, TOP, BOTTOM } from '../../constants'; +import { isFiller } from '../../util/typeAssertions'; +import type { Gradient, Pattern } from 'fabric'; let measuringContext: CanvasRenderingContext2D | null; @@ -63,20 +69,16 @@ type TPathAlign = 'baseline' | 'center' | 'ascender' | 'descender'; * needs the the info of previous graphemes already filled * Override to customize measuring */ -export type GraphemeBBox = { +export type GraphemeBBox = { width: number; height: number; kernedWidth: number; left: number; deltaY: number; -} & (onPath extends true - ? { - // on path - renderLeft: number; - renderTop: number; - angle: number; - } - : Record); + renderLeft?: number; + renderTop?: number; + angle?: number; +}; // @TODO this is not complete interface UniqueTextProps { @@ -276,7 +278,7 @@ export class Text< * }); * @default */ - declare path: Path | null; + declare path?: Path; /** * Offset amount for text path starting position @@ -705,7 +707,8 @@ export class Text< let currentColor; let lastColor = this.getValueOfPropertyAt(i, 0, 'textBackgroundColor'); for (let j = 0; j < jlen; j++) { - const charBox = this.__charBounds[i][j]; + // at this point charbox are either standard or full with pathInfo if there is a path. + const charBox = this.__charBounds[i][j] as Required; currentColor = this.getValueOfPropertyAt(i, j, 'textBackgroundColor'); if (this.path) { ctx.save(); @@ -773,9 +776,9 @@ export class Text< */ _measureChar( _char: string, - charStyle: TextStyleDeclaration, + charStyle: CompleteTextStyleDeclaration, previousChar: string | undefined, - prevCharStyle: any + prevCharStyle: CompleteTextStyleDeclaration | Record ) { const fontCache = cache.getFontCache(charStyle), fontDeclaration = this._getFontDeclaration(charStyle), @@ -818,12 +821,13 @@ export class Text< // we can measure the kerning couple and subtract the width of the previous character coupleWidth = ctx.measureText(couple).width; fontCache[couple] = coupleWidth; - kernedWidth = coupleWidth - previousWidth; + // safe to use the non-null since if undefined we defined it before. + kernedWidth = coupleWidth - previousWidth!; } } return { width: width * fontMultiplier, - kernedWidth: kernedWidth * fontMultiplier, + kernedWidth: kernedWidth! * fontMultiplier, }; } @@ -884,12 +888,13 @@ export class Text< width: 0, kernedWidth: 0, height: this.fontSize, - }; + deltaY: 0, + } as GraphemeBBox; if (path && path.segmentsInfo) { let positionInPath = 0; const totalPathLength = path.segmentsInfo[path.segmentsInfo.length - 1].length; - const startingPoint = getPointOnPath(path.path, 0, path.segmentsInfo); + const startingPoint = getPointOnPath(path.path, 0, path.segmentsInfo)!; startingPoint.x += path.pathOffset.x; startingPoint.y += path.pathOffset.y; switch (this.textAlign) { @@ -918,7 +923,7 @@ export class Text< } // it would probably much faster to send all the grapheme position for a line // and calculate path position/angle at once. - this._setGraphemeOnPath(positionInPath, graphemeInfo, startingPoint); + this._setGraphemeOnPath(positionInPath, graphemeInfo, startingPoint!); positionInPath += graphemeInfo.kernedWidth; } } @@ -935,14 +940,14 @@ export class Text< */ _setGraphemeOnPath( positionInPath: number, - graphemeInfo: GraphemeBBox, - startingPoint: Point + graphemeInfo: GraphemeBBox, + startingPoint: XY ) { const centerPosition = positionInPath + graphemeInfo.kernedWidth / 2, - path = this.path; + path = this.path!; // we are at currentPositionOnPath. we want to know what point on the path is. - const info = getPointOnPath(path.path, centerPosition, path.segmentsInfo); + const info = getPointOnPath(path.path, centerPosition, path.segmentsInfo)!; graphemeInfo.renderLeft = info.x - startingPoint.x; graphemeInfo.renderTop = info.y - startingPoint.y; graphemeInfo.angle = info.angle + (this.pathSide === RIGHT ? Math.PI : 0); @@ -1162,7 +1167,7 @@ export class Text< for (let i = 0, len = line.length - 1; i <= len; i++) { timeToRender = i === len || this.charSpacing || path; charsToRender += line[i]; - charBox = this.__charBounds[lineIndex][i]; + charBox = this.__charBounds[lineIndex][i] as Required; if (boxWidth === 0) { left += sign * (charBox.kernedWidth - charBox.width); boxWidth += charBox.width; @@ -1253,13 +1258,13 @@ export class Text< ctx: CanvasRenderingContext2D, property: `${T}Style`, filler: TFiller | string - ) { - let offsetX, offsetY; - if (filler.toLive) { + ): { offsetX: number; offsetY: number } { + let offsetX: number, offsetY: number; + if (isFiller(filler)) { if ( - filler.gradientUnits === 'percentage' || - filler.gradientTransform || - filler.patternTransform + (filler as Gradient<'linear'>).gradientUnits === 'percentage' || + (filler as Gradient<'linear'>).gradientTransform || + (filler as Pattern).patternTransform ) { // need to transform gradient in a pattern. // this is a slow process. If you are hitting this codepath, and the object @@ -1269,10 +1274,10 @@ export class Text< offsetY = -this.height / 2; ctx.translate(offsetX, offsetY); ctx[property] = this._applyPatternGradientTransformText(filler); - return { offsetX: offsetX, offsetY: offsetY }; + return { offsetX, offsetY }; } else { // is a simple gradient or pattern - ctx[property] = filler.toLive(ctx, this)!; + ctx[property] = filler.toLive(ctx)!; return this._applyPatternGradientTransform(ctx, filler); } } else { @@ -1282,20 +1287,37 @@ export class Text< return { offsetX: 0, offsetY: 0 }; } + /** + * This function prepare the canvas for a stroke style, and stroke and strokeWidth + * need to be sent in as defined + * @param {CanvasRenderingContext2D} ctx + * @param {CompleteTextStyleDeclaration} style with stroke and strokeWidth defined + * @returns + */ _setStrokeStyles( ctx: CanvasRenderingContext2D, - { stroke, strokeWidth }: Pick + { + stroke, + strokeWidth, + }: Pick ) { ctx.lineWidth = strokeWidth; ctx.lineCap = this.strokeLineCap; ctx.lineDashOffset = this.strokeDashOffset; ctx.lineJoin = this.strokeLineJoin; ctx.miterLimit = this.strokeMiterLimit; - return this.handleFiller(ctx, 'strokeStyle', stroke); + return this.handleFiller(ctx, 'strokeStyle', stroke!); } + /** + * This function prepare the canvas for a ill style, and fill + * need to be sent in as defined + * @param {CanvasRenderingContext2D} ctx + * @param {CompleteTextStyleDeclaration} style with ill defined + * @returns + */ _setFillStyles(ctx: CanvasRenderingContext2D, { fill }: Pick) { - return this.handleFiller(ctx, 'fillStyle', fill); + return this.handleFiller(ctx, 'fillStyle', fill!); } /** @@ -1323,36 +1345,39 @@ export class Text< shouldFill = method === 'fillText' && fullDecl.fill, shouldStroke = method === 'strokeText' && fullDecl.stroke && fullDecl.strokeWidth; - let fillOffsets, strokeOffsets; if (!shouldStroke && !shouldFill) { return; } ctx.save(); - shouldFill && (fillOffsets = this._setFillStyles(ctx, fullDecl)); - shouldStroke && (strokeOffsets = this._setStrokeStyles(ctx, fullDecl)); - ctx.font = this._getFontDeclaration(fullDecl); - if (decl && decl.textBackgroundColor) { + if (decl.textBackgroundColor) { this._removeShadow(ctx); } - if (decl && decl.deltaY) { + if (decl.deltaY) { top += decl.deltaY; } - shouldFill && + + if (shouldFill) { + const fillOffsets = this._setFillStyles(ctx, fullDecl); ctx.fillText( _char, left - fillOffsets.offsetX, top - fillOffsets.offsetY ); - shouldStroke && + } + + if (shouldStroke) { + const strokeOffsets = this._setStrokeStyles(ctx, fullDecl); ctx.strokeText( _char, left - strokeOffsets.offsetX, top - strokeOffsets.offsetY ); + } + ctx.restore(); } @@ -1492,12 +1517,13 @@ export class Text< * @param {String} property the property name * @returns the value of 'property' */ - getValueOfPropertyAt(lineIndex: number, charIndex: number, property: string) { + getValueOfPropertyAt( + lineIndex: number, + charIndex: number, + property: T + ): this[T] { const charStyle = this._getStyleDeclaration(lineIndex, charIndex); - if (charStyle && typeof charStyle[property] !== 'undefined') { - return charStyle[property]; - } - return this[property]; + return (charStyle[property] ?? this[property]) as this[T]; } /** @@ -1536,14 +1562,15 @@ export class Text< let size = this.getHeightOfChar(i, 0); let dy = this.getValueOfPropertyAt(i, 0, 'deltaY'); for (let j = 0, jlen = line.length; j < jlen; j++) { - const charBox = this.__charBounds[i][j]; + const charBox = this.__charBounds[i][j] as Required; currentDecoration = this.getValueOfPropertyAt(i, j, type); currentFill = this.getValueOfPropertyAt(i, j, 'fill'); const currentSize = this.getHeightOfChar(i, j); const currentDy = this.getValueOfPropertyAt(i, j, 'deltaY'); if (path && currentDecoration && currentFill) { ctx.save(); - ctx.fillStyle = lastFill; + // bug? verify lastFill is a valid fill here. + ctx.fillStyle = lastFill as string; ctx.translate(charBox.renderLeft, charBox.renderTop); ctx.rotate(charBox.angle); ctx.fillRect( @@ -1565,7 +1592,8 @@ export class Text< drawStart = this.width - drawStart - boxWidth; } if (lastDecoration && lastFill) { - ctx.fillStyle = lastFill; + // bug? verify lastFill is a valid fill here. + ctx.fillStyle = lastFill as string; ctx.fillRect( drawStart, top + offsetY * size + dy, @@ -1587,7 +1615,7 @@ export class Text< if (this.direction === 'rtl') { drawStart = this.width - drawStart - boxWidth; } - ctx.fillStyle = currentFill; + ctx.fillStyle = currentFill as string; currentDecoration && currentFill && ctx.fillRect( @@ -1780,7 +1808,7 @@ export class Text< const parsedAttributes = parseAttributes(element, Text.ATTRIBUTE_NAMES); const { - textAnchor = LEFT, + textAnchor = LEFT as typeof LEFT | typeof CENTER | typeof RIGHT, textDecoration = '', dx = 0, dy = 0, @@ -1791,22 +1819,7 @@ export class Text< ...restOfOptions } = { ...options, ...parsedAttributes }; - let textContent = ''; - - // The XML is not properly parsed in IE9 so a workaround to get - // textContent is through firstChild.data. Another workaround would be - // to convert XML loaded from a file to be converted using DOMParser (same way loadSVGFromString() does) - if (!('textContent' in element)) { - if ('firstChild' in element && element.firstChild !== null) { - if ('data' in element.firstChild && element.firstChild.data !== null) { - textContent = element.firstChild.data; - } - } - } else { - textContent = element.textContent; - } - - textContent = textContent + const textContent = (element.textContent || '') .replace(/^\s+|\s+$|\n+/g, '') .replace(/\s+/g, ' '); diff --git a/src/shapes/Text/TextSVGExportMixin.ts b/src/shapes/Text/TextSVGExportMixin.ts index fc166d80207..f6d5ba58065 100644 --- a/src/shapes/Text/TextSVGExportMixin.ts +++ b/src/shapes/Text/TextSVGExportMixin.ts @@ -193,7 +193,7 @@ export class TextSVGExportMixin extends FabricObjectSVGExportMixin { timeToRender = hasStyleChanged(actualStyle, nextStyle, true); } if (timeToRender) { - style = this._getStyleDeclaration(lineIndex, i) || {}; + style = this._getStyleDeclaration(lineIndex, i); textSpans.push( this._createTextCharSpan( charsToRender, diff --git a/src/shapes/Text/constants.ts b/src/shapes/Text/constants.ts index 44322372902..88c5d8c1ff2 100644 --- a/src/shapes/Text/constants.ts +++ b/src/shapes/Text/constants.ts @@ -87,7 +87,7 @@ export const textDefaultValues: Partial> = { textBackgroundColor: '', stroke: null, shadow: null, - path: null, + path: undefined, pathStartOffset: 0, pathSide: LEFT, pathAlign: 'baseline', diff --git a/src/shapes/Textbox.ts b/src/shapes/Textbox.ts index e88ae17a3ba..7169ebcc7cc 100644 --- a/src/shapes/Textbox.ts +++ b/src/shapes/Textbox.ts @@ -4,6 +4,7 @@ import { IText } from './IText/IText'; import { classRegistry } from '../ClassRegistry'; import { createTextboxDefaultControls } from '../controls/commonControls'; import { JUSTIFY } from './Text/constants'; +import type { TextStyleDeclaration } from 'fabric'; // @TODO: Many things here are configuration related and shouldn't be on the class nor prototype // regexes, list of properties that are not suppose to change by instances, magic consts. // this will be a separated effort @@ -195,11 +196,14 @@ export class Textbox extends IText { * @param {Number} charIndex * @private */ - _getStyleDeclaration(lineIndex: number, charIndex: number) { + _getStyleDeclaration( + lineIndex: number, + charIndex: number + ): TextStyleDeclaration { if (this._styleMap && !this.isWrapping) { const map = this._styleMap[lineIndex]; if (!map) { - return null; + return {}; } lineIndex = map.line; charIndex = map.offset + charIndex; @@ -213,7 +217,11 @@ export class Textbox extends IText { * @param {Object} style * @private */ - _setStyleDeclaration(lineIndex: number, charIndex: number, style: object) { + protected _setStyleDeclaration( + lineIndex: number, + charIndex: number, + style: object + ) { const map = this._styleMap[lineIndex]; lineIndex = map.line; charIndex = map.offset + charIndex; @@ -241,7 +249,7 @@ export class Textbox extends IText { * @returns {Boolean} if the line exists or not * @private */ - _getLineStyle(lineIndex: number): boolean { + protected _getLineStyle(lineIndex: number): boolean { const map = this._styleMap[lineIndex]; return !!this.styles[map.line]; } @@ -252,7 +260,7 @@ export class Textbox extends IText { * @param {Object} style * @private */ - _setLineStyle(lineIndex: number) { + protected _setLineStyle(lineIndex: number) { const map = this._styleMap[lineIndex]; this.styles[map.line] = {}; } diff --git a/src/util/misc/svgParsing.ts b/src/util/misc/svgParsing.ts index c20593826f5..cce5dabc647 100644 --- a/src/util/misc/svgParsing.ts +++ b/src/util/misc/svgParsing.ts @@ -50,12 +50,9 @@ export const getSvgAttributes = (type: SVGElementName) => { * @param {number} fontSize * @return {number} */ -export const parseUnit = (value: string, fontSize: number) => { +export const parseUnit = (value: string, fontSize = DEFAULT_SVG_FONT_SIZE) => { const unit = /\D{0,2}$/.exec(value), number = parseFloat(value); - if (!fontSize) { - fontSize = DEFAULT_SVG_FONT_SIZE; - } const dpi = config.DPI; switch (unit?.[0] as SupportedSVGUnit) { case 'mm': diff --git a/test/unit/itext.js b/test/unit/itext.js index 16363ad83a2..2de2df44ae2 100644 --- a/test/unit/itext.js +++ b/test/unit/itext.js @@ -46,7 +46,7 @@ charSpacing: 0, styles: [], strokeUniform: false, - path: null, + path: undefined, direction: 'ltr', pathStartOffset: 0, pathSide: 'left', diff --git a/test/unit/text.js b/test/unit/text.js index 1ce747af84f..fa6c3919f6b 100644 --- a/test/unit/text.js +++ b/test/unit/text.js @@ -59,7 +59,7 @@ skewY: 0, charSpacing: 0, styles: [], - path: null, + path: undefined, strokeUniform: false, direction: 'ltr', pathStartOffset: 0, diff --git a/test/unit/textbox.js b/test/unit/textbox.js index 660d49f61c7..5db9078e79f 100644 --- a/test/unit/textbox.js +++ b/test/unit/textbox.js @@ -69,7 +69,7 @@ minWidth: 20, splitByGrapheme: false, strokeUniform: false, - path: null, + path: undefined, direction: 'ltr', pathStartOffset: 0, pathSide: 'left',