From 5bb7aab7a8bf05ca529679f6cf8f2c83f896e232 Mon Sep 17 00:00:00 2001 From: miyanokomiya Date: Fri, 9 Feb 2024 13:21:39 +0900 Subject: [PATCH] feat: Avoid rendering or exporting empty text content --- src/composables/shapeRenderer.ts | 4 ++-- src/composables/shapeSVGRenderer.ts | 4 ++-- src/utils/textEditor.spec.ts | 12 ++++++++++++ src/utils/textEditor.ts | 9 +++++++++ 4 files changed, 25 insertions(+), 4 deletions(-) diff --git a/src/composables/shapeRenderer.ts b/src/composables/shapeRenderer.ts index d2dfede7..ae1ddf2b 100644 --- a/src/composables/shapeRenderer.ts +++ b/src/composables/shapeRenderer.ts @@ -1,6 +1,6 @@ import { DocOutput } from "../models/document"; import { getShapeTextBounds } from "../shapes"; -import { getDocCompositionInfo, renderDocByComposition } from "../utils/textEditor"; +import { getDocCompositionInfo, hasDocNoContent, renderDocByComposition } from "../utils/textEditor"; import { walkTree } from "../utils/tree"; import { ImageStore } from "./imageStore"; import { ShapeComposite } from "./shapeComposite"; @@ -23,7 +23,7 @@ export function newShapeRenderer(option: Option) { option.shapeComposite.render(ctx, shape, option.imageStore); const doc = docMap[shape.id]; - if (doc && !ignoreDocIdSet.has(shape.id)) { + if (doc && !ignoreDocIdSet.has(shape.id) && !hasDocNoContent(doc)) { ctx.save(); const bounds = getShapeTextBounds(option.shapeComposite.getShapeStruct, shape); ctx.transform(...bounds.affine); diff --git a/src/composables/shapeSVGRenderer.ts b/src/composables/shapeSVGRenderer.ts index 87b4c5f8..af42a214 100644 --- a/src/composables/shapeSVGRenderer.ts +++ b/src/composables/shapeSVGRenderer.ts @@ -1,7 +1,7 @@ import { DocOutput } from "../models/document"; import { getShapeTextBounds } from "../shapes"; import { createSVGElement, createSVGSVGElement, renderTransform } from "../utils/svgElements"; -import { getDocCompositionInfo, renderSVGDocByComposition } from "../utils/textEditor"; +import { getDocCompositionInfo, hasDocNoContent, renderSVGDocByComposition } from "../utils/textEditor"; import { walkTree } from "../utils/tree"; import { ImageStore } from "./imageStore"; import { ShapeComposite } from "./shapeComposite"; @@ -25,7 +25,7 @@ export function newShapeSVGRenderer(option: Option) { if (!shapeElmInfo) return; const doc = docMap[shape.id]; - if (!doc) { + if (!doc || hasDocNoContent(doc)) { const shapeElm = createSVGElement(shapeElmInfo.tag, shapeElmInfo.attributes, shapeElmInfo.children); root.appendChild(shapeElm); return; diff --git a/src/utils/textEditor.spec.ts b/src/utils/textEditor.spec.ts index cd84c0ab..143e5330 100644 --- a/src/utils/textEditor.spec.ts +++ b/src/utils/textEditor.spec.ts @@ -22,6 +22,7 @@ import { getOutputSelection, getRawCursor, getWordRangeAtCursor, + hasDocNoContent, isCursorInDoc, isLinebreak, isUrlText, @@ -89,6 +90,17 @@ describe("getDocLength", () => { }); }); +describe("hasDocNoContent", () => { + test("should return true when doc has no content", () => { + expect(hasDocNoContent([])).toBe(true); + expect(hasDocNoContent([{ insert: "\n" }])).toBe(true); + expect(hasDocNoContent([{ insert: " " }])).toBe(false); + expect(hasDocNoContent([{ insert: "a" }])).toBe(false); + expect(hasDocNoContent([{ insert: "a" }, { insert: "b" }])).toBe(false); + expect(hasDocNoContent([{ insert: "\n" }, { insert: "\n" }])).toBe(false); + }); +}); + describe("getDocRawLength", () => { test("should return doc length based on doc delta", () => { expect(getDocRawLength([{ insert: "a" }, { insert: "b" }, { insert: "c" }])).toBe(3); diff --git a/src/utils/textEditor.ts b/src/utils/textEditor.ts index 687de3e3..8d457904 100644 --- a/src/utils/textEditor.ts +++ b/src/utils/textEditor.ts @@ -88,6 +88,15 @@ export function getDocLength(doc: DocOutput): number { return doc.map((d) => splitToSegments(d.insert)).reduce((p, v) => p + v.length, 0); } +/** + * Returns true when doc has no content. + * i.e. There's no items or only one line break. + */ +export function hasDocNoContent(doc: DocOutput): boolean { + if (doc.length === 0) return true; + return doc.length === 1 && doc[0].insert.length === 1 && isLinebreak(doc[0].insert); +} + /** * Returns doc length based on doc delta */