From 82db0a349532afcdbb2af871e7d6f005c4c73509 Mon Sep 17 00:00:00 2001 From: Jono Hayward <157665284+jono-pov@users.noreply.github.com> Date: Sat, 7 Feb 2026 12:47:43 +1100 Subject: [PATCH 1/2] =?UTF-8?q?=F0=9F=A4=96=20Merge=20PR=20#74487=20Featur?= =?UTF-8?q?e/add=20hyphen=20exceptions=20param=20by=20@jono-pov?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- types/hyphen/hyphen-tests.ts | 8 ++++++++ types/hyphen/index.d.ts | 14 ++++++++++++++ types/hyphen/package.json | 2 +- 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/types/hyphen/hyphen-tests.ts b/types/hyphen/hyphen-tests.ts index 4f95c007db57ca..06bbecefd5e54f 100644 --- a/types/hyphen/hyphen-tests.ts +++ b/types/hyphen/hyphen-tests.ts @@ -39,3 +39,11 @@ if (hyphenateEnUsSyncWithMinWordLength("sabotaging") !== "sabotaging") { // sabotaging has 10 chars => don't hyphenate throw new Error("Test failed"); } + +// Test with exceptions +const hyphenateWithExceptions = createHyphenator(hyphenationPatternsEnGb, { + exceptions: ["Bland-thorn"], +}) as HyphenationFunctionSync; +if (hyphenateWithExceptions("Blandthorn") !== "Bland-thorn") { + throw new Error("Test failed"); +} diff --git a/types/hyphen/index.d.ts b/types/hyphen/index.d.ts index 6cd9587e5374b8..2ab28f0c67dff9 100644 --- a/types/hyphen/index.d.ts +++ b/types/hyphen/index.d.ts @@ -43,6 +43,13 @@ declare namespace hyphen { * @default 5 */ minWordLength?: number | undefined; + + /** + * An array of values with exceptions of hyphenation in words. + * Hard hyphen symbol `-` should be used to mark the position of further configured hyphenation symbol. + * @default [] + */ + exceptions?: string[] | undefined; } /** @@ -66,6 +73,13 @@ declare namespace hyphen { * @default 5 */ minWordLength?: number | undefined; + + /** + * An array of values with exceptions of hyphenation in words. + * Hard hyphen symbol `-` should be used to mark the position of further configured hyphenation symbol. + * @default [] + */ + exceptions?: string[] | undefined; } /** diff --git a/types/hyphen/package.json b/types/hyphen/package.json index 36d19dcf0f7dc9..5e3bf3e1f40405 100644 --- a/types/hyphen/package.json +++ b/types/hyphen/package.json @@ -1,7 +1,7 @@ { "private": true, "name": "@types/hyphen", - "version": "1.6.9999", + "version": "1.14.9999", "projects": [ "https://github.com/ytiurin/hyphen" ], From be69cfdd81b429acb57359907a4d5edb3c69ca0a Mon Sep 17 00:00:00 2001 From: Au <18971501210@189.cn> Date: Sat, 7 Feb 2026 11:46:07 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=F0=9F=A4=96=20Merge=20PR=20#74490=20Add=20?= =?UTF-8?q?types=20for=20svgcanvas=20by=20@Aurouscia?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- types/svgcanvas/.npmignore | 5 + types/svgcanvas/index.d.ts | 250 +++++++++++++++++++++++++++++ types/svgcanvas/package.json | 17 ++ types/svgcanvas/svgcanvas-tests.ts | 133 +++++++++++++++ types/svgcanvas/tsconfig.json | 20 +++ 5 files changed, 425 insertions(+) create mode 100644 types/svgcanvas/.npmignore create mode 100644 types/svgcanvas/index.d.ts create mode 100644 types/svgcanvas/package.json create mode 100644 types/svgcanvas/svgcanvas-tests.ts create mode 100644 types/svgcanvas/tsconfig.json diff --git a/types/svgcanvas/.npmignore b/types/svgcanvas/.npmignore new file mode 100644 index 00000000000000..93e307400a5456 --- /dev/null +++ b/types/svgcanvas/.npmignore @@ -0,0 +1,5 @@ +* +!**/*.d.ts +!**/*.d.cts +!**/*.d.mts +!**/*.d.*.ts diff --git a/types/svgcanvas/index.d.ts b/types/svgcanvas/index.d.ts new file mode 100644 index 00000000000000..724679ec278eb0 --- /dev/null +++ b/types/svgcanvas/index.d.ts @@ -0,0 +1,250 @@ +/** + * SVGCanvas - Draw on SVG using Canvas's 2D Context API + * + * This library provides a Canvas 2D Context API implementation that generates SVG + * instead of drawing to a bitmap canvas. + * + * @example + * ```javascript + * import { Context } from 'svgcanvas'; + * + * const ctx = new Context({ width: 500, height: 500 }); + * ctx.fillStyle = 'red'; + * ctx.fillRect(10, 10, 100, 100); + * const svgElement = ctx.getSvg(); + * document.body.appendChild(svgElement); + * ``` + */ + +/** + * Options for creating a Context or Element + */ +export interface C2SOptions { + /** Width of the canvas (default: 500) */ + width?: number; + /** Height of the canvas (default: 500) */ + height?: number; + /** Enable mirroring for getImageData (default: false) */ + enableMirroring?: boolean; + /** Document object (default: global document) */ + document?: Document; + /** Existing Context2D to wrap around */ + ctx?: CanvasRenderingContext2D; + /** Enable debug logging */ + debug?: boolean; +} + +/** + * CanvasGradient for creating color gradients + */ +export interface CanvasGradient { + /** + * Adds a color stop to the gradient + * @param offset - A number between 0 and 1 + * @param color - A CSS color string + */ + addColorStop(offset: number, color: string): void; +} + +/** + * CanvasPattern for creating pattern fills + */ +// eslint-disable-next-line @typescript-eslint/no-empty-interface +export interface CanvasPattern {} + +/** + * TextMetrics - measurement results from measureText() + */ +export interface TextMetrics { + width: number; +} + +/** + * Context - implements most of CanvasRenderingContext2D API but generates SVG + * + * This class provides a Canvas 2D-like API that generates SVG elements instead + * of drawing to a bitmap. Most standard Canvas 2D methods are supported. + */ +export class Context { + // Canvas properties + readonly canvas: Context; + width: number; + height: number; + + // Style properties + fillStyle: string | CanvasGradient | CanvasPattern; + strokeStyle: string | CanvasGradient | CanvasPattern; + lineWidth: number; + lineCap: CanvasLineCap; + lineJoin: CanvasLineJoin; + miterLimit: number; + globalAlpha: number; + font: string; + textAlign: CanvasTextAlign; + textBaseline: CanvasTextBaseline; + shadowColor: string; + shadowBlur: number; + shadowOffsetX: number; + shadowOffsetY: number; + lineDash: string | null; + + constructor(options?: C2SOptions); + constructor(width: number, height: number); + + // Drawing state + save(): void; + restore(): void; + + // Transformations + scale(x: number, y?: number): void; + rotate(angle: number): void; + translate(x: number, y: number): void; + transform(a: number, b: number, c: number, d: number, e: number, f: number): void; + setTransform(a: number, b: number, c: number, d: number, e: number, f: number): void; + setTransform(matrix: DOMMatrix): void; + getTransform(): DOMMatrix; + resetTransform(): void; + + // Path methods + beginPath(): void; + closePath(): void; + moveTo(x: number, y: number): void; + lineTo(x: number, y: number): void; + bezierCurveTo(cp1x: number, cp1y: number, cp2x: number, cp2y: number, x: number, y: number): void; + quadraticCurveTo(cpx: number, cpy: number, x: number, y: number): void; + arc(x: number, y: number, radius: number, startAngle: number, endAngle: number, counterClockwise?: boolean): void; + arcTo(x1: number, y1: number, x2: number, y2: number, radius: number): void; + ellipse( + x: number, + y: number, + radiusX: number, + radiusY: number, + rotation: number, + startAngle: number, + endAngle: number, + counterClockwise?: boolean, + ): void; + rect(x: number, y: number, width: number, height: number): void; + roundRect(x: number, y: number, w: number, h: number, radii: number | [number, number, number, number]): void; + + // Drawing methods + fill(): void; + stroke(): void; + clip(): void; + fillRect(x: number, y: number, width: number, height: number): void; + strokeRect(x: number, y: number, width: number, height: number): void; + clearRect(x: number, y: number, width: number, height: number): void; + + // Text methods + fillText(text: string, x: number, y: number): void; + strokeText(text: string, x: number, y: number): void; + measureText(text: string): TextMetrics; + + // Image methods - supports Context instances for nested SVG + drawImage( + image: HTMLImageElement | HTMLCanvasElement | HTMLVideoElement | ImageBitmap | Context, + dx: number, + dy: number, + ): void; + drawImage( + image: HTMLImageElement | HTMLCanvasElement | HTMLVideoElement | ImageBitmap | Context, + dx: number, + dy: number, + dWidth: number, + dHeight: number, + ): void; + drawImage( + image: HTMLImageElement | HTMLCanvasElement | HTMLVideoElement | ImageBitmap | Context, + sx: number, + sy: number, + sWidth: number, + sHeight: number, + dx: number, + dy: number, + dWidth: number, + dHeight: number, + ): void; + + // Gradient and pattern methods + createLinearGradient(x1: number, y1: number, x2: number, y2: number): CanvasGradient; + createRadialGradient(x0: number, y0: number, r0: number, x1: number, y1: number, r1: number): CanvasGradient; + createPattern( + image: HTMLImageElement | HTMLCanvasElement | HTMLVideoElement | ImageBitmap | Context, + repetition: "repeat" | "repeat-x" | "repeat-y" | "no-repeat", + ): CanvasPattern | null; + + // Line dash + setLineDash(dashArray: ReadonlyArray | null): void; + + // Image data methods (async versions) + getImageData( + sx: number, + sy: number, + sw: number, + sh: number, + options?: { async?: boolean }, + ): ImageData | Promise; + createImageData(): ImageData; + putImageData(): void; + + // SVG-specific methods + /** + * Returns the SVG as a serialized string + * @param fixNamedEntities - If true, fixes named entities to numbered entities + */ + getSerializedSvg(fixNamedEntities?: boolean): string; + + /** + * Returns the SVG root element + */ + getSvg(): SVGSVGElement; +} + +/** + * Element - A canvas-like element that uses SVG + * + * This class provides a wrapper that mimics HTMLCanvasElement behavior + * while using SVG as the underlying rendering technology. + */ +export class Element { + ctx: Context; + svg: SVGSVGElement; + wrapper: HTMLDivElement; + className: string; + readonly tagName: string; + width: number; + height: number; + style: CSSStyleDeclaration; + id: string; + + constructor(options?: C2SOptions); + + /** + * Get the 2D rendering context + */ + getContext(type: "2d"): Context; + + /** + * Returns an object URL for the SVG + * Remember to call URL.revokeObjectURL when done + */ + toObjectURL(): string; + + /** + * Returns a data URI containing a representation of the image + * @param type - Image format (image/svg+xml, image/jpeg, image/png) + * @param encoderOptions - Quality for lossy formats (0-1) + * @param options - If async is true, returns a Promise + */ + toDataURL(type?: string, encoderOptions?: number, options?: { async?: boolean }): string | Promise; + + addEventListener( + type: string, + listener: EventListenerOrEventListenerObject, + options?: boolean | AddEventListenerOptions, + ): void; + getElement(): HTMLDivElement; + getAttribute(prop: string): string | null; + setAttribute(prop: string, val: string): void; + getBoundingClientRect(): DOMRect; +} diff --git a/types/svgcanvas/package.json b/types/svgcanvas/package.json new file mode 100644 index 00000000000000..dce158cbfe4c03 --- /dev/null +++ b/types/svgcanvas/package.json @@ -0,0 +1,17 @@ +{ + "private": true, + "name": "@types/svgcanvas", + "version": "2.6.9999", + "projects": [ + "https://github.com/zenozeng/svgcanvas" + ], + "devDependencies": { + "@types/svgcanvas": "workspace:." + }, + "owners": [ + { + "name": "Au", + "githubUsername": "Aurouscia" + } + ] +} diff --git a/types/svgcanvas/svgcanvas-tests.ts b/types/svgcanvas/svgcanvas-tests.ts new file mode 100644 index 00000000000000..ee8adecb69f4ab --- /dev/null +++ b/types/svgcanvas/svgcanvas-tests.ts @@ -0,0 +1,133 @@ +import { C2SOptions, CanvasGradient, CanvasPattern, Context, Element } from "svgcanvas"; + +// Test Context construction +// $ExpectType Context +const ctx1 = new Context(); +// $ExpectType Context +const ctx2 = new Context({ width: 800, height: 600 }); +// $ExpectType Context +const ctx3 = new Context(500, 500); + +// Test drawing state +ctx1.save(); +ctx1.restore(); + +// Test transformations +ctx1.scale(2, 2); +ctx1.scale(2); // single argument +ctx1.rotate(Math.PI / 4); +ctx1.translate(10, 20); +ctx1.transform(1, 0, 0, 1, 0, 0); +ctx1.setTransform(1, 0, 0, 1, 0, 0); +ctx1.resetTransform(); +// $ExpectType DOMMatrix +const matrix = ctx1.getTransform(); +ctx1.setTransform(matrix); + +// Test style properties +ctx1.fillStyle = "red"; +ctx1.strokeStyle = "#00FF00"; +ctx1.lineWidth = 5; +ctx1.lineCap = "round"; +ctx1.lineJoin = "bevel"; +ctx1.miterLimit = 10; +ctx1.globalAlpha = 0.5; +ctx1.font = "16px Arial"; +ctx1.textAlign = "center"; +ctx1.textBaseline = "middle"; +ctx1.shadowColor = "black"; +ctx1.shadowBlur = 10; +ctx1.shadowOffsetX = 5; +ctx1.shadowOffsetY = 5; + +// Test path methods +ctx1.beginPath(); +ctx1.moveTo(0, 0); +ctx1.lineTo(100, 100); +ctx1.closePath(); +ctx1.bezierCurveTo(0, 0, 50, 50, 100, 100); +ctx1.quadraticCurveTo(50, 50, 100, 100); +ctx1.arc(50, 50, 25, 0, Math.PI * 2); +ctx1.arc(50, 50, 25, 0, Math.PI * 2, true); +ctx1.arcTo(0, 0, 50, 50, 25); +ctx1.ellipse(50, 50, 30, 20, 0, 0, Math.PI * 2); +ctx1.rect(10, 10, 80, 80); +ctx1.roundRect(10, 10, 80, 80, 5); +ctx1.roundRect(10, 10, 80, 80, [5, 10, 15, 20]); + +// Test drawing methods +ctx1.fill(); +ctx1.stroke(); +ctx1.clip(); +ctx1.fillRect(10, 10, 100, 100); +ctx1.strokeRect(10, 10, 100, 100); +ctx1.clearRect(10, 10, 100, 100); + +// Test text methods +ctx1.fillText("Hello", 50, 50); +ctx1.strokeText("World", 50, 100); +// $ExpectType TextMetrics +const metrics = ctx1.measureText("Test"); + +// Test gradients and patterns +// $ExpectType CanvasGradient +const linearGradient = ctx1.createLinearGradient(0, 0, 100, 100); +linearGradient.addColorStop(0, "red"); +linearGradient.addColorStop(1, "blue"); +ctx1.fillStyle = linearGradient; + +// $ExpectType CanvasGradient +const radialGradient = ctx1.createRadialGradient(50, 50, 0, 50, 50, 50); + +// Test line dash +ctx1.setLineDash([5, 10]); +ctx1.setLineDash(null); + +// Test SVG-specific methods +// $ExpectType SVGSVGElement +const svg = ctx1.getSvg(); +// $ExpectType string +const serialized = ctx1.getSerializedSvg(); +// $ExpectType string +const serializedFixed = ctx1.getSerializedSvg(true); + +// Test Element class +// $ExpectType Element +const elem1 = new Element(); +// $ExpectType Element +const elem2 = new Element({ width: 800, height: 600 }); + +// $ExpectType Context +const elemCtx = elem1.getContext("2d"); +elem1.width = 500; +elem1.height = 400; +elem1.className = "my-canvas"; +// $ExpectType string +const tagName: string = elem1.tagName; + +// $ExpectType string +const objectUrl = elem1.toObjectURL(); +// $ExpectType string | Promise +const dataUrl = elem1.toDataURL(); +// $ExpectType Promise +const dataUrlJpegAsync = elem1.toDataURL("image/jpeg", 0.8, { async: true }) as Promise; +// $ExpectType string | Promise +const dataUrlSvg = elem1.toDataURL("image/svg+xml"); + +// $ExpectType HTMLDivElement +const wrapper = elem1.getElement(); +// $ExpectType DOMRect +const rect = elem1.getBoundingClientRect(); + +elem1.addEventListener("click", () => console.log("clicked")); +elem1.setAttribute("data-test", "value"); +// $ExpectType string | null +const attr = elem1.getAttribute("data-test"); + +// Test drawImage with Context +const ctx4 = new Context({ width: 100, height: 100 }); +ctx1.drawImage(ctx4, 0, 0); + +// Test createPattern with Context +// $ExpectType CanvasPattern | null +const pattern = ctx1.createPattern(ctx4, "repeat"); diff --git a/types/svgcanvas/tsconfig.json b/types/svgcanvas/tsconfig.json new file mode 100644 index 00000000000000..ed4013da1a826a --- /dev/null +++ b/types/svgcanvas/tsconfig.json @@ -0,0 +1,20 @@ +{ + "compilerOptions": { + "module": "node16", + "lib": [ + "es6", + "dom" + ], + "noImplicitAny": true, + "noImplicitThis": true, + "strictFunctionTypes": true, + "strictNullChecks": true, + "types": [], + "noEmit": true, + "forceConsistentCasingInFileNames": true + }, + "files": [ + "index.d.ts", + "svgcanvas-tests.ts" + ] +}