diff --git a/.github/release-drafter.yml b/.github/release-drafter.yml new file mode 100644 index 00000000..dafe6fd5 --- /dev/null +++ b/.github/release-drafter.yml @@ -0,0 +1,36 @@ +name-template: 'v$RESOLVED_VERSION 🌈' +tag-template: 'v$RESOLVED_VERSION' +categories: + - title: '🚀 Features' + labels: + - 'feature' + - 'enhancement' + - 'feat' + - title: '🐛 Bug Fixes' + labels: + - 'fix' + - 'bugfix' + - 'bug' + - 'fixed' + - title: '🧰 Maintenance' + labels: + - 'chore' + - 'ci' + - 'refactor' +change-template: '- $TITLE @$AUTHOR (#$NUMBER)' +change-title-escapes: '\<*_&' # You can add # and @ to disable mentions, and add ` to disable code blocks. +version-resolver: + major: + labels: + - 'major' + minor: + labels: + - 'minor' + patch: + labels: + - 'patch' + default: patch +template: | + ## Changes + + $CHANGES \ No newline at end of file diff --git a/example/src/App.tsx b/example/src/App.tsx index 4fd224ea..b71bebc4 100644 --- a/example/src/App.tsx +++ b/example/src/App.tsx @@ -462,8 +462,8 @@ function useViewModel() { textBackgroundStyle: useTextBgStyle ? { type: textBgStretch, - paddingX: 10, - paddingY: 10, + paddingBottom: '15%', + paddingRight: '10%', color: '#0f0A', } : null, @@ -495,8 +495,7 @@ function useViewModel() { textBackgroundStyle: useTextBgStyle ? { type: textBgStretch, - paddingX: 10, - paddingY: 10, + padding: '10%', color: '#0fA', } : null, diff --git a/ios/RCTImageMarker/Constants.swift b/ios/RCTImageMarker/Constants.swift new file mode 100644 index 00000000..829c7bbe --- /dev/null +++ b/ios/RCTImageMarker/Constants.swift @@ -0,0 +1,13 @@ +// +// Constants.swift +// react-native-image-marker +// +// Created by Jimmydaddy on 2023/8/10. +// + +enum ErrorDomainEnum: String { + case PARAMS_REQUIRED = "com.jimmydaddy.imagemarker.PARAMS_REQUIRED" + case PARAMS_INVALID = "com.jimmydaddy.imagemarker.PARAMS_INVALID" + case BASE = "com.jimmydaddy.imagemarker" +} + diff --git a/ios/RCTImageMarker/ImageMarker.swift b/ios/RCTImageMarker/ImageMarker.swift index 4233865e..87fa211e 100644 --- a/ios/RCTImageMarker/ImageMarker.swift +++ b/ios/RCTImageMarker/ImageMarker.swift @@ -20,7 +20,7 @@ public final class ImageMarker: NSObject, RCTBridgeModule { let className = "RCTImageLoader" let classType: AnyClass? = NSClassFromString(className) guard let imageLoader = self.bridge.module(for: classType) as? RCTImageLoader else { - throw NSError(domain: "com.jimmydaddy.imagemarker", code: 1, userInfo: [NSLocalizedDescriptionKey: "Failed to get ImageLoader module"]) + throw NSError(domain: ErrorDomainEnum.BASE.rawValue, code: 1, userInfo: [NSLocalizedDescriptionKey: "Failed to get ImageLoader module"]) } let images = try await withThrowingTaskGroup(of: (Int, UIImage).self) { group in for (index, img) in imageOptions.enumerated() { @@ -30,7 +30,7 @@ public final class ImageMarker: NSObject, RCTBridgeModule { if let image = UIImage.transBase64(img.uri) { continuation.resume(returning: (index, image)) } else { - let error = NSError(domain: "com.jimmydaddy.imagemarker", code: 3, userInfo: [NSLocalizedDescriptionKey: "Failed to load image"]) + let error = NSError(domain: ErrorDomainEnum.BASE.rawValue, code: 3, userInfo: [NSLocalizedDescriptionKey: "Failed to load image"]) continuation.resume(throwing: error) } } else { @@ -41,7 +41,7 @@ public final class ImageMarker: NSObject, RCTBridgeModule { } else if let error = error { continuation.resume(throwing: error) } else { - let error = NSError(domain: "com.jimmydaddy.imagemarker", code: 3, userInfo: [NSLocalizedDescriptionKey: "Failed to load image"]) + let error = NSError(domain: ErrorDomainEnum.BASE.rawValue, code: 3, userInfo: [NSLocalizedDescriptionKey: "Failed to load image"]) continuation.resume(throwing: error) } } @@ -225,14 +225,19 @@ public final class ImageMarker: NSObject, RCTBridgeModule { } if let textBackground = textOpts.style!.textBackground { + let bgEdgeInsets = textOpts.style?.textBackground?.toEdgeInsets(width: CGFloat(w), height: CGFloat(h)) context.setFillColor(textBackground.colorBg!.cgColor) + let stretchX = (bgEdgeInsets?.left ?? 0) + (bgEdgeInsets?.right ?? 0); + let stretchY = (bgEdgeInsets?.top ?? 0) + (bgEdgeInsets?.bottom ?? 0); + var bgRect = CGRect(x: CGFloat(CGFloat(posX) - (bgEdgeInsets?.left ?? 0)), y: CGFloat(CGFloat(posY) - (bgEdgeInsets?.top ?? 0)), width: size.width + stretchX, height: size.height + stretchY) if textBackground.typeBg == "stretchX" { - context.fill(CGRect(x: 0, y: CGFloat(posY) - textBackground.paddingY, width: CGFloat(w), height: size.height + 2 * textBackground.paddingY)) + bgRect = CGRect(x: 0, y: CGFloat(posY) - (bgEdgeInsets?.top ?? 0), width: CGFloat(w), height: size.height + stretchY) } else if textBackground.typeBg == "stretchY" { - context.fill(CGRect(x: CGFloat(CGFloat(posX) - textBackground.paddingX), y: 0, width: size.width + 2 * textBackground.paddingX, height: CGFloat(h))) - } else { - context.fill(CGRect(x: CGFloat(CGFloat(posX) - textBackground.paddingX), y: CGFloat(CGFloat(posY) - textBackground.paddingY), width: size.width + 2 * textBackground.paddingX, height: size.height + 2 * textBackground.paddingY)) + bgRect = CGRect(x: CGFloat(CGFloat(posX) - (bgEdgeInsets?.left ?? 0)), y: 0, width: size.width + stretchX, height: CGFloat(h)) } + + bgRect.inset(by: bgEdgeInsets!) + context.fill(bgRect) } let rect = CGRect(origin: CGPoint(x: posX, y: posY), size: size) @@ -353,7 +358,7 @@ public final class ImageMarker: NSObject, RCTBridgeModule { func mark(withText opts: [AnyHashable: Any], resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) -> Void { let markOpts = MarkTextOptions.checkTextParams(opts, rejecter: rejecter) if markOpts === nil { - rejecter("OPTS_INVALID", "opts invalid", nil) + rejecter(ErrorDomainEnum.PARAMS_INVALID.rawValue, "opts invalid", nil) } Task(priority: .userInitiated) { do { @@ -372,7 +377,7 @@ public final class ImageMarker: NSObject, RCTBridgeModule { func mark(withImage opts: [AnyHashable: Any], resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) -> Void { let markOpts = MarkImageOptions.checkImageParams(opts, rejecter: rejecter) if markOpts === nil { - rejecter("OPTS_INVALID", "opts invalid", nil) + rejecter(ErrorDomainEnum.PARAMS_INVALID.rawValue, "opts invalid", nil) } Task(priority: .userInitiated) { do { diff --git a/ios/RCTImageMarker/ImageOptions.swift b/ios/RCTImageMarker/ImageOptions.swift index 8648f53f..3b8a5153 100644 --- a/ios/RCTImageMarker/ImageOptions.swift +++ b/ios/RCTImageMarker/ImageOptions.swift @@ -17,7 +17,7 @@ class ImageOptions: NSObject { init(dicOpts opts: [AnyHashable: Any]) throws { guard let src = opts["src"] as? [AnyHashable: Any], !Utils.isNULL(src) else { - throw NSError(domain: "PARAMS_REQUIRED", code: 0, userInfo: [NSLocalizedDescriptionKey: "image is required"]) + throw NSError(domain: ErrorDomainEnum.PARAMS_REQUIRED.rawValue, code: 0, userInfo: [NSLocalizedDescriptionKey: "image is required"]) } self.src = src self.uri = src["uri"] as! String diff --git a/ios/RCTImageMarker/MarkImageOptions.swift b/ios/RCTImageMarker/MarkImageOptions.swift index ce239395..fd6dc7f4 100644 --- a/ios/RCTImageMarker/MarkImageOptions.swift +++ b/ios/RCTImageMarker/MarkImageOptions.swift @@ -17,7 +17,7 @@ class MarkImageOptions: Options { let watermarkImageOpts = opts["watermarkImage"] let watermarkImagesOpts = opts["watermarkImages"] as? [[AnyHashable: Any]] if Utils.isNULL(watermarkImageOpts) && (Utils.isNULL(watermarkImagesOpts) || watermarkImagesOpts!.count <= 0) { - throw NSError(domain: "PARAMS_REQUIRED", code: 0, userInfo: [NSLocalizedDescriptionKey: "marker image is required"]) + throw NSError(domain: ErrorDomainEnum.PARAMS_REQUIRED.rawValue, code: 0, userInfo: [NSLocalizedDescriptionKey: "marker image is required"]) } if watermarkImagesOpts!.count > 0 { self.watermarkImages = try watermarkImagesOpts!.map { try WatermarkImageOptions(dicOpts: $0) } diff --git a/ios/RCTImageMarker/MarkTextOptions.swift b/ios/RCTImageMarker/MarkTextOptions.swift index 8fb3ca67..f18104bd 100644 --- a/ios/RCTImageMarker/MarkTextOptions.swift +++ b/ios/RCTImageMarker/MarkTextOptions.swift @@ -14,7 +14,7 @@ class MarkTextOptions: Options { override init(dicOpts opts: [AnyHashable: Any]) throws { try super.init(dicOpts: opts) guard let watermarkTextsOpts = opts["watermarkTexts"] as? [[AnyHashable: Any]], watermarkTextsOpts.count > 0 else { - throw NSError(domain: "PARAMS_REQUIRED", code: 0, userInfo: [NSLocalizedDescriptionKey: "text is required"]) + throw NSError(domain: ErrorDomainEnum.PARAMS_REQUIRED.rawValue, code: 0, userInfo: [NSLocalizedDescriptionKey: "text is required"]) } self.watermarkTexts = try watermarkTextsOpts.map { try TextOptions(dicOpts: $0) } } diff --git a/ios/RCTImageMarker/Options.swift b/ios/RCTImageMarker/Options.swift index dce68c38..afe5d5e2 100644 --- a/ios/RCTImageMarker/Options.swift +++ b/ios/RCTImageMarker/Options.swift @@ -17,7 +17,7 @@ class Options: NSObject { init(dicOpts opts: [AnyHashable: Any]) throws { guard let backgroundImageOpts = opts["backgroundImage"] as? [AnyHashable: Any], !Utils.isNULL(backgroundImageOpts) else { - throw NSError(domain: "PARAMS_REQUIRED", code: 0, userInfo: [NSLocalizedDescriptionKey: "backgroundImage is required"]) + throw NSError(domain: ErrorDomainEnum.PARAMS_REQUIRED.rawValue, code: 0, userInfo: [NSLocalizedDescriptionKey: "backgroundImage is required"]) } self.backgroundImage = try ImageOptions(dicOpts: backgroundImageOpts) self.quality = opts["quality"] as? Int ?? 100 diff --git a/ios/RCTImageMarker/Padding.swift b/ios/RCTImageMarker/Padding.swift new file mode 100644 index 00000000..1d95fc23 --- /dev/null +++ b/ios/RCTImageMarker/Padding.swift @@ -0,0 +1,135 @@ +// +// Padding.swift +// react-native-image-marker +// +// Created by Jimmydaddy on 2023/8/9. +// + +import Foundation + +class Padding { + var paddingTop: String = "0" + var paddingLeft: String = "0" + var paddingBottom: String = "0" + var paddingRight: String = "0" + + init(paddingData: [AnyHashable: Any]) throws { + var topValue: String = "0" + var leftValue: String = "0" + var bottomValue: String = "0" + var rightValue: String = "0" + + for (key, paddingValue) in paddingData { + switch key { + case "padding" as String: + if var paddingValue = paddingValue as? String { + paddingValue = paddingValue.trimmingCharacters(in: .whitespaces) + if !Utils.checkSpreadValue(str: paddingValue, maxLength: 4) { + throw NSError(domain: ErrorDomainEnum.PARAMS_INVALID.rawValue, code: 0, userInfo: [NSLocalizedDescriptionKey: "padding is invalid"]) + } + let values = paddingValue.components(separatedBy: " ") + if values.count == 1 { + topValue = values[0] + leftValue = values[0] + bottomValue = values[0] + rightValue = values[0] + } else if values.count == 2 { + topValue = values[0] + leftValue = values[1] + bottomValue = values[0] + rightValue = values[1] + } else if values.count == 3 { + topValue = values[0] + leftValue = values[1] + bottomValue = values[2] + rightValue = values[1] + } else if values.count == 4 { + topValue = values[0] + leftValue = values[1] + bottomValue = values[2] + rightValue = values[3] + } + break + } else if let paddingValue = paddingValue as? CGFloat { + topValue = String(format: "%f", paddingValue) + leftValue = String(format: "%f", paddingValue) + bottomValue = String(format: "%f", paddingValue) + rightValue = String(format: "%f", paddingValue) + } + case "paddingLeft" as String: + if let paddingValue = paddingValue as? String { + if !Utils.checkSpreadValue(str: paddingValue, maxLength: 1) { + throw NSError(domain: ErrorDomainEnum.PARAMS_INVALID.rawValue, code: 0, userInfo: [NSLocalizedDescriptionKey: "padding is invalid"]) + } + leftValue = paddingValue; + } else if let paddingValue = paddingValue as? CGFloat { + leftValue = String(format: "%f", paddingValue) + } + case "paddingRight" as String: + if let paddingValue = paddingValue as? String { + if !Utils.checkSpreadValue(str: paddingValue, maxLength: 1) { + throw NSError(domain: ErrorDomainEnum.PARAMS_INVALID.rawValue, code: 0, userInfo: [NSLocalizedDescriptionKey: "padding is invalid"]) + } + rightValue = paddingValue; + } else if let paddingValue = paddingValue as? CGFloat { + rightValue = String(format: "%f", paddingValue) + } + case "paddingTop" as String: + if let paddingValue = paddingValue as? String { + if !Utils.checkSpreadValue(str: paddingValue, maxLength: 1) { + throw NSError(domain: ErrorDomainEnum.PARAMS_INVALID.rawValue, code: 0, userInfo: [NSLocalizedDescriptionKey: "padding is invalid"]) + } + topValue = paddingValue; + } else if let paddingValue = paddingValue as? CGFloat { + topValue = String(format: "%f", paddingValue) + } + case "paddingBottom" as String: + if let paddingValue = paddingValue as? String { + if !Utils.checkSpreadValue(str: paddingValue, maxLength: 1) { + throw NSError(domain: ErrorDomainEnum.PARAMS_INVALID.rawValue, code: 0, userInfo: [NSLocalizedDescriptionKey: "padding is invalid"]) + } + bottomValue = paddingValue; + } else if let paddingValue = paddingValue as? CGFloat { + bottomValue = String(format: "%f", paddingValue) + } + case "paddingHorizontal" as String, "paddingX" as String: + if let paddingValue = paddingValue as? String { + if !Utils.checkSpreadValue(str: paddingValue, maxLength: 1) { + throw NSError(domain: ErrorDomainEnum.PARAMS_INVALID.rawValue, code: 0, userInfo: [NSLocalizedDescriptionKey: "padding is invalid"]) + } + rightValue = paddingValue; + leftValue = paddingValue; + } else if let paddingValue = paddingValue as? CGFloat { + leftValue = String(format: "%f", paddingValue) + rightValue = String(format: "%f", paddingValue) + } + case "paddingVertical" as String, "paddingY" as String: + if let paddingValue = paddingValue as? String { + if !Utils.checkSpreadValue(str: paddingValue, maxLength: 1) { + throw NSError(domain: ErrorDomainEnum.PARAMS_INVALID.rawValue, code: 0, userInfo: [NSLocalizedDescriptionKey: "padding is invalid"]) + } + topValue = paddingValue; + bottomValue = paddingValue; + } else if let paddingValue = paddingValue as? CGFloat { + topValue = String(format: "%f", paddingValue) + bottomValue = String(format: "%f", paddingValue) + } + default: + break + } + } + + self.paddingTop = topValue + self.paddingLeft = leftValue + self.paddingBottom = bottomValue + self.paddingRight = rightValue + } + + func toEdgeInsets(width: CGFloat, height: CGFloat) -> UIEdgeInsets { + let topValue = Utils.parseSpreadValue(v: self.paddingTop, relativeTo: height) ?? 0 + let leftValue = Utils.parseSpreadValue(v: self.paddingLeft, relativeTo: width) ?? 0 + let bottomValue = Utils.parseSpreadValue(v: self.paddingBottom, relativeTo: height) ?? 0 + let rightValue = Utils.parseSpreadValue(v: self.paddingRight, relativeTo: width) ?? 0 + return UIEdgeInsets(top: topValue, left: leftValue, bottom: bottomValue, right: rightValue) + } +} diff --git a/ios/RCTImageMarker/RCTConvert+ImageMarker.swift b/ios/RCTImageMarker/RCTConvert+ImageMarker.swift index 203e24aa..b97e1d21 100644 --- a/ios/RCTImageMarker/RCTConvert+ImageMarker.swift +++ b/ios/RCTImageMarker/RCTConvert+ImageMarker.swift @@ -60,6 +60,6 @@ extension RCTConvert { guard let value = value as? String, let mv = MyEnumMap[value] else { return MarkerPositionEnum.topLeft } - return mv ?? MarkerPositionEnum.none + return mv } } diff --git a/ios/RCTImageMarker/TextBackground.swift b/ios/RCTImageMarker/TextBackground.swift index 12970aec..33ea18b1 100644 --- a/ios/RCTImageMarker/TextBackground.swift +++ b/ios/RCTImageMarker/TextBackground.swift @@ -10,19 +10,16 @@ import Foundation import UIKit import React -class TextBackground: NSObject { +class TextBackground: Padding { var typeBg: String? - var paddingX: CGFloat = 0.0 - var paddingY: CGFloat = 0.0 var colorBg: UIColor? - init?(textBackgroundStyle textBackground: [AnyHashable: Any]?) { + init?(textBackgroundStyle textBackground: [AnyHashable: Any]?) throws { guard let textBackground = textBackground, !Utils.isNULL(textBackground) else { return nil } + try super.init(paddingData: textBackground) self.typeBg = textBackground["type"] as? String - self.paddingX = RCTConvert.cgFloat(textBackground["paddingX"]) - self.paddingY = RCTConvert.cgFloat(textBackground["paddingY"]) self.colorBg = UIColor(hex: textBackground["color"] as! String) ?? UIColor.clear } } diff --git a/ios/RCTImageMarker/TextOptions.swift b/ios/RCTImageMarker/TextOptions.swift index 9a683ea3..90f8f4e2 100644 --- a/ios/RCTImageMarker/TextOptions.swift +++ b/ios/RCTImageMarker/TextOptions.swift @@ -18,7 +18,7 @@ class TextOptions: NSObject { init(dicOpts opts: [AnyHashable: Any]) throws { guard let text = opts["text"] as? String else { - throw NSError(domain: "PARAMS_REQUIRED", code: 0, userInfo: [NSLocalizedDescriptionKey: "text is required"]) + throw NSError(domain: ErrorDomainEnum.PARAMS_REQUIRED.rawValue, code: 0, userInfo: [NSLocalizedDescriptionKey: "text is required"]) } if let positionOpts = opts["positionOptions"] as? [AnyHashable: Any] { diff --git a/ios/RCTImageMarker/TextStyle.swift b/ios/RCTImageMarker/TextStyle.swift index 81092062..269b0ee9 100644 --- a/ios/RCTImageMarker/TextStyle.swift +++ b/ios/RCTImageMarker/TextStyle.swift @@ -22,14 +22,14 @@ class TextStyle: NSObject { var rotate: CGFloat = 0 var textAlign: String? - init(dicOpts opts: [AnyHashable: Any]) { + init(dicOpts opts: [AnyHashable: Any]) throws { self.color = UIColor(hex: opts["color"] as! String) ?? UIColor.clear if let shadowStyle = opts["shadowStyle"] as? [AnyHashable: Any] { self.shadow = Utils.getShadowStyle(shadowStyle) } else { self.shadow = nil } - self.textBackground = TextBackground(textBackgroundStyle: (opts["textBackgroundStyle"] as? [AnyHashable : Any])) + self.textBackground = try TextBackground(textBackgroundStyle: (opts["textBackgroundStyle"] as? [AnyHashable : Any])) let scale = UIScreen.main.scale let fontSize = opts["fontSize"] != nil ? (RCTConvert.cgFloat(opts["fontSize"]) * scale) : (14.0 * scale) self.font = UIFont(name: opts["fontName"] as? String ?? "", size: fontSize) diff --git a/ios/RCTImageMarker/Utils.swift b/ios/RCTImageMarker/Utils.swift index 04d71278..96ea1ba4 100644 --- a/ios/RCTImageMarker/Utils.swift +++ b/ios/RCTImageMarker/Utils.swift @@ -126,4 +126,24 @@ class Utils: NSObject { static func isNULL(_ obj: Any?) -> Bool { return obj == nil || obj is NSNull } + + static func checkSpreadValue(str: String?, maxLength: Int = 1) -> Bool { + if str == nil { return false } + let pattern = #"^((\d+|\d+%)\s?){1,\#(maxLength)}$"# + if (str?.range(of: pattern, options: .regularExpression)) != nil { + return true + } else { + return false + } + } + + static func parseSpreadValue(v: String?, relativeTo length: CGFloat) -> CGFloat? { + if v == nil { return nil } + if v?.hasSuffix(String(describing: "%")) ?? false { + let percent = CGFloat(Double(v!.dropLast()) ?? 0) / 100 + return length * percent + } else { + return CGFloat(Double(v!) ?? 0) + } + } } diff --git a/package.json b/package.json index b077af44..9ac8244b 100644 --- a/package.json +++ b/package.json @@ -35,7 +35,7 @@ "example": "yarn --cwd example", "bootstrap": "yarn example && yarn install && yarn example pods", "clean": "del-cli android/build example/android/build example/android/app/build example/ios/build", - "docs": "typedoc --excludePrivate" + "docs": "typedoc --excludePrivate --tsconfig tsconfig.build.json" }, "keywords": [ "react-native", @@ -61,7 +61,7 @@ "@commitlint/config-conventional": "^17.0.2", "@evilmartians/lefthook": "^1.2.2", "@react-native-community/eslint-config": "^3.0.2", - "@release-it/conventional-changelog": "^5.1.1", + "@release-it/conventional-changelog": "^7.0.2", "@types/jest": "^28.1.2", "@types/react": "~17.0.21", "@types/react-native": "0.70.0", @@ -70,13 +70,14 @@ "eslint": "^8.4.1", "eslint-config-prettier": "^8.5.0", "eslint-plugin-prettier": "^4.0.0", + "husky": "^8.0.3", "jest": "^28.1.1", "pod-install": "^0.1.0", "prettier": "^2.0.5", "react": "18.2.0", "react-native": "0.71.11", "react-native-builder-bob": "^0.20.0", - "release-it": "^15.0.0", + "release-it": "^16.2.0", "typedoc": "^0.24.8", "typedoc-plugin-localization": "^3.0.1", "typedoc-plugin-rename-defaults": "^0.6.5", diff --git a/src/index.ts b/src/index.ts index 6e7cf81a..74ef34e1 100644 --- a/src/index.ts +++ b/src/index.ts @@ -42,6 +42,110 @@ export enum ImageFormat { base64 = 'base64', } +/** + * @description Padding style for text background + * @example + * padding: 10 + * // or + * padding: '10%' + * // or + * padding: '10% 20%' + * // or + * padding: '10% 20% 30%' + * // or + * paddingLeft: '10%' + * // or + * paddingVertical: '10%' + */ +interface Padding { + /** + * @description padding for text background + * @example + * padding: 10 + * // or + * padding: '10%' + * // or + * padding: '10% 20%' + * // or + * padding: '10% 20% 30%' + * // or + * padding: '10% 20% 30% 40%' + * // or + * padding: '10 20% 30 40%' + * // or + * padding: '10 20 30' + */ + padding?: number | string; + /** + * @description padding left for text background + * @example + * paddingLeft: 10 + * // or + * paddingLeft: '10%' + */ + paddingLeft?: number | string; + /** + * @description padding top for text background + * @example + * paddingTop: 10 + * // or + * paddingTop: '10%' + */ + paddingRight?: number | string; + /** + * @description padding right for text background + * @example + * paddingRight: 10 + * // or + * paddingRight: '10%' + */ + paddingTop?: number | string; + /** + * @description padding bottom for text background + * @example + * paddingBottom: 10 + * // or + * paddingBottom: '10%' + */ + paddingBottom?: number | string; + /** + * @description padding left and right (horizontal) for text background + * @example + * paddingHorizontal: 10 + * // or + * paddingHorizontal: '10%' + * @since 2.0.0 + **/ + paddingHorizontal?: number | string; + /** + * @description padding top and bottom (vertical) for text background + * @example + * paddingVertical: 10 + * // or + * paddingVertical: '10%' + * @since 2.0.0 + */ + paddingVertical?: number | string; + + /** + * @description padding x, alias of paddingHorizontal + * @example + * paddingX: 10 + * // or + * paddingX: '10%' + **/ + paddingX?: number | string; + + /** + * @description padding y, alias of paddingVertical + * @example + * paddingY: 10 + * // or + * paddingY: '10%' + **/ + paddingY?: number | string; +} + /** * @description PositionOptions for text watermark and image watermark, if you set position you don't need to set X and Y * @example @@ -53,6 +157,11 @@ export enum ImageFormat { * positionOptions: { * position: Position.topLeft, * } + * // or + * positionOptions: { + * offsetX: 10, + * offsetY: 10, + * } */ export interface PositionOptions { X?: number; @@ -227,19 +336,7 @@ export interface ShadowLayerStyle { * color: '#aacc22' * } */ -export interface TextBackgroundStyle { - /** - * @description padding x - * @example - * paddingX: 10 - **/ - paddingX: number; - /** - * @description padding y - * @example - * paddingY: 10 - **/ - paddingY: number; +export interface TextBackgroundStyle extends Padding { /** * @description background type * @defaultValue TextBackgroundType.stretchX diff --git a/tsconfig.json b/tsconfig.json index c51791af..366c24a1 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -26,7 +26,6 @@ "strict": true, "target": "esnext" }, - "exclude": [ "example" ], "typedocOptions": { "exclude": [ "**/node_modules/**/*.*", "example/" ], "entryPoints": ["src/index.ts"],