{"version":3,"file":"drawing-BxzLuryn.mjs","names":[],"sources":["../src/drawing/image.ts","../src/drawing/anchor.ts","../src/drawing/drawing.ts"],"sourcesContent":["// Image embedding.\n//\n// `XlsxImage` is the workbook-level handle for any image referenced from a\n// worksheet drawing (or chart `<a:blipFill>`). Bytes are kept verbatim so\n// re-saving never re-encodes; format / width / height are detected from the\n// file header so callers don't have to specify them.\n\nimport { OpenXmlIoError } from '../utils/exceptions';\n\nexport type XlsxImageFormat = 'png' | 'jpeg' | 'gif' | 'bmp' | 'webp' | 'tiff' | 'svg' | 'emf' | 'wmf';\n\n/**\n * Map from image format to the Content-Types Default extension that Excel uses\n * in `[Content_Types].xml`. SVG / EMF / WMF use the same extension as the\n * format string; PNG/JPEG/GIF/BMP do too. WebP and TIFF use their canonical\n * short names.\n */\nexport const IMAGE_FORMAT_EXTENSION: Readonly<Record<XlsxImageFormat, string>> = {\n  png: 'png',\n  jpeg: 'jpeg',\n  gif: 'gif',\n  bmp: 'bmp',\n  webp: 'webp',\n  tiff: 'tiff',\n  svg: 'svg',\n  emf: 'emf',\n  wmf: 'wmf',\n};\n\n/** Map from image format to its IANA `image/*` MIME type. */\nexport const IMAGE_FORMAT_MIME: Readonly<Record<XlsxImageFormat, string>> = {\n  png: 'image/png',\n  jpeg: 'image/jpeg',\n  gif: 'image/gif',\n  bmp: 'image/bmp',\n  webp: 'image/webp',\n  tiff: 'image/tiff',\n  svg: 'image/svg+xml',\n  emf: 'image/x-emf',\n  wmf: 'image/x-wmf',\n};\n\nexport interface XlsxImage {\n  bytes: Uint8Array;\n  format: XlsxImageFormat;\n  /** Pixel width. Zero when dimensions can't be determined for the format. */\n  width: number;\n  /** Pixel height. Zero when dimensions can't be determined for the format. */\n  height: number;\n  /** ZIP archive path, e.g. `xl/media/image3.png`. Set by the writer. */\n  path?: string;\n  /** rels-resolved id used by `<a:blip r:embed=\"...\">`. Set by the loader. */\n  rId?: string;\n}\n\n// ---- Magic-byte format detection ------------------------------------------\n\nconst startsWith = (bytes: Uint8Array, sig: ReadonlyArray<number>, offset = 0): boolean => {\n  if (bytes.length < offset + sig.length) return false;\n  for (let i = 0; i < sig.length; i++) {\n    if (bytes[offset + i] !== sig[i]) return false;\n  }\n  return true;\n};\n\nconst PNG_SIG = [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a];\nconst JPEG_SIG = [0xff, 0xd8, 0xff];\nconst GIF87 = [0x47, 0x49, 0x46, 0x38, 0x37, 0x61];\nconst GIF89 = [0x47, 0x49, 0x46, 0x38, 0x39, 0x61];\nconst BMP_SIG = [0x42, 0x4d];\nconst RIFF_SIG = [0x52, 0x49, 0x46, 0x46];\nconst WEBP_TAG = [0x57, 0x45, 0x42, 0x50];\nconst TIFF_LE = [0x49, 0x49, 0x2a, 0x00];\nconst TIFF_BE = [0x4d, 0x4d, 0x00, 0x2a];\nconst EMF_SIG = [0x01, 0x00, 0x00, 0x00];\nconst EMF_TAG = [0x20, 0x45, 0x4d, 0x46]; // ' EMF' at offset 40\nconst WMF_SIG_PLACEABLE = [0xd7, 0xcd, 0xc6, 0x9a];\nconst WMF_SIG_BARE = [0x01, 0x00, 0x09, 0x00];\n\nconst isSvg = (bytes: Uint8Array): boolean => {\n  // Inspect the first ~512 bytes for an `<svg` tag (with optional XML / DOCTYPE\n  // preamble).\n  const head = new TextDecoder('utf-8', { fatal: false }).decode(bytes.subarray(0, Math.min(bytes.length, 512)));\n  return /<svg\\b/i.test(head);\n};\n\nexport function detectImageFormat(bytes: Uint8Array): XlsxImageFormat | undefined {\n  if (startsWith(bytes, PNG_SIG)) return 'png';\n  if (startsWith(bytes, JPEG_SIG)) return 'jpeg';\n  if (startsWith(bytes, GIF87) || startsWith(bytes, GIF89)) return 'gif';\n  if (startsWith(bytes, BMP_SIG)) return 'bmp';\n  if (startsWith(bytes, RIFF_SIG) && startsWith(bytes, WEBP_TAG, 8)) return 'webp';\n  if (startsWith(bytes, TIFF_LE) || startsWith(bytes, TIFF_BE)) return 'tiff';\n  if (startsWith(bytes, EMF_SIG) && startsWith(bytes, EMF_TAG, 40)) return 'emf';\n  if (startsWith(bytes, WMF_SIG_PLACEABLE) || startsWith(bytes, WMF_SIG_BARE)) return 'wmf';\n  if (isSvg(bytes)) return 'svg';\n  return undefined;\n}\n\n// ---- Per-format dimension extraction --------------------------------------\n\nconst readU32BE = (bytes: Uint8Array, offset: number): number =>\n  ((bytes[offset] ?? 0) << 24) |\n  ((bytes[offset + 1] ?? 0) << 16) |\n  ((bytes[offset + 2] ?? 0) << 8) |\n  (bytes[offset + 3] ?? 0);\n\nconst readU16LE = (bytes: Uint8Array, offset: number): number => (bytes[offset] ?? 0) | ((bytes[offset + 1] ?? 0) << 8);\n\nconst readU16BE = (bytes: Uint8Array, offset: number): number => ((bytes[offset] ?? 0) << 8) | (bytes[offset + 1] ?? 0);\n\ninterface Dimensions {\n  width: number;\n  height: number;\n}\n\nconst pngDimensions = (bytes: Uint8Array): Dimensions | undefined => {\n  // PNG: 8-byte signature, 4-byte chunk-length, 4-byte type (\"IHDR\"), then\n  // 4-byte width, 4-byte height (both big-endian).\n  if (bytes.length < 24) return undefined;\n  if (bytes[12] !== 0x49 || bytes[13] !== 0x48 || bytes[14] !== 0x44 || bytes[15] !== 0x52) {\n    return undefined;\n  }\n  return { width: readU32BE(bytes, 16), height: readU32BE(bytes, 20) };\n};\n\nconst gifDimensions = (bytes: Uint8Array): Dimensions | undefined => {\n  if (bytes.length < 10) return undefined;\n  return { width: readU16LE(bytes, 6), height: readU16LE(bytes, 8) };\n};\n\nconst bmpDimensions = (bytes: Uint8Array): Dimensions | undefined => {\n  if (bytes.length < 26) return undefined;\n  // BITMAPINFOHEADER: width (LE int32) at offset 18, height at offset 22.\n  // Height can be negative for top-down bitmaps; we report absolute pixels.\n  const w = (bytes[18] ?? 0) | ((bytes[19] ?? 0) << 8) | ((bytes[20] ?? 0) << 16) | ((bytes[21] ?? 0) << 24);\n  const hRaw = (bytes[22] ?? 0) | ((bytes[23] ?? 0) << 8) | ((bytes[24] ?? 0) << 16) | ((bytes[25] ?? 0) << 24);\n  // Treat width as signed; for height take absolute value (top-down bitmaps\n  // store negative).\n  const wSigned = (w | 0) >>> 0 > 0x7fffffff ? (w | 0) - 0x100000000 : w;\n  const hSigned = (hRaw | 0) >>> 0 > 0x7fffffff ? (hRaw | 0) - 0x100000000 : hRaw;\n  return { width: wSigned, height: Math.abs(hSigned) };\n};\n\nconst jpegDimensions = (bytes: Uint8Array): Dimensions | undefined => {\n  // Walk the marker stream until an SOFn (FFC0..FFCF, excluding FFC4/C8/CC).\n  let i = 2; // skip SOI (FFD8)\n  while (i + 9 < bytes.length) {\n    if (bytes[i] !== 0xff) return undefined;\n    let marker = bytes[i + 1] ?? 0;\n    while (marker === 0xff) {\n      // Padding bytes. Advance to the next non-FF.\n      i += 1;\n      marker = bytes[i + 1] ?? 0;\n    }\n    i += 2;\n    const isSof = marker >= 0xc0 && marker <= 0xcf && marker !== 0xc4 && marker !== 0xc8 && marker !== 0xcc;\n    const len = readU16BE(bytes, i);\n    if (isSof) {\n      // SOF segment: 2 bytes length, 1 byte precision, 2 bytes height, 2 bytes\n      // width.\n      if (i + 7 > bytes.length) return undefined;\n      const height = readU16BE(bytes, i + 3);\n      const width = readU16BE(bytes, i + 5);\n      return { width, height };\n    }\n    i += len;\n  }\n  return undefined;\n};\n\nconst webpDimensions = (bytes: Uint8Array): Dimensions | undefined => {\n  // RIFF header is 12 bytes; chunk type is at offset 12.\n  if (bytes.length < 30) return undefined;\n  // VP8 (lossy): \"VP8 \" chunk; width / height at offset 26 / 28 (LE 14-bit each\n  // + 2 unused bits).\n  if (\n    bytes[12] === 0x56 && // V\n    bytes[13] === 0x50 && // P\n    bytes[14] === 0x38 && // 8\n    bytes[15] === 0x20 // space\n  ) {\n    const w = readU16LE(bytes, 26) & 0x3fff;\n    const h = readU16LE(bytes, 28) & 0x3fff;\n    return { width: w, height: h };\n  }\n  // VP8L (lossless): 14-bit width-1 / height-1 packed little-endian starting at\n  // offset 21.\n  if (\n    bytes[12] === 0x56 &&\n    bytes[13] === 0x50 &&\n    bytes[14] === 0x38 &&\n    bytes[15] === 0x4c // L\n  ) {\n    if (bytes.length < 25) return undefined;\n    const b0 = bytes[21] ?? 0;\n    const b1 = bytes[22] ?? 0;\n    const b2 = bytes[23] ?? 0;\n    const b3 = bytes[24] ?? 0;\n    const w = (b0 | (b1 << 8)) & 0x3fff;\n    const h = ((b1 >> 6) | (b2 << 2) | ((b3 & 0x0f) << 10)) & 0x3fff;\n    return { width: w + 1, height: h + 1 };\n  }\n  // VP8X (extended): width-1 (24 bits) / height-1 (24 bits) at offset 24 / 27.\n  if (\n    bytes[12] === 0x56 &&\n    bytes[13] === 0x50 &&\n    bytes[14] === 0x38 &&\n    bytes[15] === 0x58 // X\n  ) {\n    if (bytes.length < 30) return undefined;\n    const w = (bytes[24] ?? 0) | ((bytes[25] ?? 0) << 8) | ((bytes[26] ?? 0) << 16);\n    const h = (bytes[27] ?? 0) | ((bytes[28] ?? 0) << 8) | ((bytes[29] ?? 0) << 16);\n    return { width: w + 1, height: h + 1 };\n  }\n  return undefined;\n};\n\nexport function detectImageDimensions(bytes: Uint8Array, format: XlsxImageFormat): Dimensions {\n  let dims: Dimensions | undefined;\n  switch (format) {\n    case 'png':\n      dims = pngDimensions(bytes);\n      break;\n    case 'jpeg':\n      dims = jpegDimensions(bytes);\n      break;\n    case 'gif':\n      dims = gifDimensions(bytes);\n      break;\n    case 'bmp':\n      dims = bmpDimensions(bytes);\n      break;\n    case 'webp':\n      dims = webpDimensions(bytes);\n      break;\n    default:\n      // tiff / svg / emf / wmf — readers can fall back to 0 and Excel will\n      // assign defaults.\n      dims = undefined;\n  }\n  return dims ?? { width: 0, height: 0 };\n}\n\n// ---- Public factory --------------------------------------------------------\n\n/**\n * Build an `XlsxImage` from raw bytes. Detects the format and dimensions\n * automatically. Caller may pass an explicit `format` to override detection\n * (e.g. when bytes were read from a `data:` URL with a known MIME type) or\n * `width`/`height` to skip the parser.\n */\nexport function loadImage(\n  bytes: Uint8Array,\n  opts: { format?: XlsxImageFormat; width?: number; height?: number } = {},\n): XlsxImage {\n  const format = opts.format ?? detectImageFormat(bytes);\n  if (!format) {\n    throw new OpenXmlIoError('loadImage: could not determine image format from bytes');\n  }\n  const dims =\n    opts.width !== undefined && opts.height !== undefined\n      ? { width: opts.width, height: opts.height }\n      : detectImageDimensions(bytes, format);\n  return { bytes, format, width: dims.width, height: dims.height };\n}\n","// DrawingML anchors.\n//\n// An anchor positions a drawing (chart / image / shape) inside a worksheet.\n// ECMA-376 §20.5.2 defines three kinds:\n//\n// absolute — fixed (x, y) and (cx, cy) in EMU; ignores cell layout. oneCell —\n// pinned at `from` cell, fixed extent. Resizes with the\n//               cell only on its top-left corner.\n// twoCell — anchored to `from` and `to` cells. Resizes / moves with\n//               both corners depending on `editAs`.\n//\n// Coordinates are EMU (English Metric Units). 1 inch = 914400 EMU, 1 cm =\n// 360000 EMU, 1 px = 9525 EMU at 96 dpi.\n\nimport { columnIndexFromLetter } from '../utils/coordinate';\nimport { OpenXmlSchemaError } from '../utils/exceptions';\nimport { emuFromPx } from '../utils/units';\n\n/** EMU = English Metric Units. Drawing coordinates are stored in EMU on the wire. */\nexport interface Point2D {\n  /** Horizontal offset in EMU. */\n  x: number;\n  /** Vertical offset in EMU. */\n  y: number;\n}\n\nexport interface PositiveSize2D {\n  cx: number;\n  cy: number;\n}\n\n/**\n * `from` / `to` corners reference a cell by 0-based column + row index plus an\n * EMU offset within the cell. Excel's wire format is 0-based here even though\n * cell references in formulas / sheetData are 1-based.\n */\nexport interface AnchorMarker {\n  col: number;\n  colOff: number;\n  row: number;\n  rowOff: number;\n}\n\nexport type DrawingAnchor =\n  | { kind: 'absolute'; pos: Point2D; ext: PositiveSize2D }\n  | { kind: 'oneCell'; from: AnchorMarker; ext: PositiveSize2D }\n  | { kind: 'twoCell'; from: AnchorMarker; to: AnchorMarker; editAs?: 'twoCell' | 'oneCell' | 'absolute' };\n\nconst A1_RE = /^([A-Za-z]{1,3})([1-9][0-9]*)$/;\n\n/**\n * Convert a cell ref (\"A1\", \"C5\") to a 0-based AnchorMarker with `colOff =\n * rowOff = 0`. Throws on malformed refs.\n */\nexport function anchorMarkerFromCellRef(ref: string): AnchorMarker {\n  const m = A1_RE.exec(ref);\n  if (!m || m[1] === undefined || m[2] === undefined) {\n    throw new OpenXmlSchemaError(`anchorMarkerFromCellRef: invalid coordinate \"${ref}\"`);\n  }\n  const col = columnIndexFromLetter(m[1]) - 1; // 0-based\n  const row = Number.parseInt(m[2], 10) - 1; // 0-based\n  return { col, colOff: 0, row, rowOff: 0 };\n}\n\n/** Build an absolute anchor from an (x, y, cx, cy) EMU bundle. */\nexport function makeAbsoluteAnchor(opts: { x: number; y: number; cx: number; cy: number }): DrawingAnchor {\n  return { kind: 'absolute', pos: { x: opts.x, y: opts.y }, ext: { cx: opts.cx, cy: opts.cy } };\n}\n\n/** Build a one-cell anchor pinned at `from` with an explicit pixel extent. */\nexport function makeOneCellAnchor(opts: {\n  from: string | AnchorMarker;\n  widthPx: number;\n  heightPx: number;\n}): DrawingAnchor {\n  const from = typeof opts.from === 'string' ? anchorMarkerFromCellRef(opts.from) : opts.from;\n  return {\n    kind: 'oneCell',\n    from,\n    ext: { cx: emuFromPx(opts.widthPx), cy: emuFromPx(opts.heightPx) },\n  };\n}\n\n/**\n * Build a two-cell anchor from cell-ref pairs (or pre-built markers). Defaults\n * to `editAs='twoCell'` — drag both corners with the cells.\n */\nexport function makeTwoCellAnchor(opts: {\n  from: string | AnchorMarker;\n  to: string | AnchorMarker;\n  editAs?: 'twoCell' | 'oneCell' | 'absolute';\n}): DrawingAnchor {\n  const from = typeof opts.from === 'string' ? anchorMarkerFromCellRef(opts.from) : opts.from;\n  const to = typeof opts.to === 'string' ? anchorMarkerFromCellRef(opts.to) : opts.to;\n  return {\n    kind: 'twoCell',\n    from,\n    to,\n    ...(opts.editAs !== undefined ? { editAs: opts.editAs } : {}),\n  };\n}\n","// Spreadsheet drawing data model.\n//\n// A `Drawing` is the per-worksheet `xl/drawings/drawingN.xml` part — a list of\n// anchor entries, each carrying a content variant (chart, picture, shape,\n// connector, group). Stage-1 implements the chart variant as a \"rels-only\"\n// reference (the full ChartML model lands in later iterations); picture / shape\n// / connector / group are reserved for later.\n\nimport type { ChartSpace } from '../chart/chart';\nimport type { CxChartSpace } from '../chart/cx/chartex';\nimport type { DrawingAnchor } from './anchor';\nimport type { ShapeProperties } from './dml/shape-properties';\nimport type { XlsxImage } from './image';\n\n/** Reference to a chart part — the chart's drawing-rels rId resolves to xl/charts/chartN.xml. */\nexport interface ChartReference {\n  /** Drawing-rels rId pointing at the chart part. Populated on read; the writer assigns its own. */\n  rId?: string;\n  /**\n   * Legacy ECMA-376 chart payload (`c:chartSpace`). Stage-1 supports BarChart\n   * end-to-end; other chart kinds populate this field as their parsers /\n   * writers land.\n   */\n  space?: ChartSpace;\n  /**\n   * Excel-2016 chartex payload (`cx:chartSpace`). Mutually exclusive with\n   * {@link space} for any given drawing item; the parser sniffs the root\n   * element and populates whichever is appropriate.\n   */\n  cxSpace?: CxChartSpace;\n  /**\n   * `true` when the resolved chart part is a chartex (`cx:`) chart. Set by the\n   * package writer so the drawing emitter knows to use the chartex\n   * `<a:graphicData uri>` instead of the legacy chart URI — Excel rejects the\n   * workbook when the URI doesn't match the chart's actual root namespace.\n   */\n  isCx?: boolean;\n}\n\n/** Reference to an embedded picture inside a worksheet drawing. */\nexport interface PictureReference {\n  /** Drawing-rels rId pointing at the embedded image. Populated on read; the writer assigns its own. */\n  rId?: string;\n  /** Resolved image bytes + metadata. Populated on read; the writer reads it back. */\n  image?: XlsxImage;\n  /** Picture display name (`<xdr:cNvPr name=\"...\">`). */\n  name?: string;\n  /** Optional alt-text description. */\n  descr?: string;\n  /** Hidden flag (`<xdr:cNvPr hidden=\"1\"/>`). */\n  hidden?: boolean;\n  /** Per-picture shape properties (extra fill / line / rotation). */\n  spPr?: ShapeProperties;\n}\n\nexport interface DrawingItem {\n  anchor: DrawingAnchor;\n  content:\n    | { kind: 'chart'; chart: ChartReference }\n    | { kind: 'picture'; picture: PictureReference }\n    | { kind: 'unsupported'; rawTag: string };\n}\n\nexport interface Drawing {\n  items: DrawingItem[];\n}\n\nexport function makeDrawing(items: DrawingItem[] = []): Drawing {\n  return { items };\n}\n\nexport function makeChartDrawingItem(anchor: DrawingAnchor, chart: ChartReference = {}): DrawingItem {\n  return { anchor, content: { kind: 'chart', chart } };\n}\n\nexport function makePictureDrawingItem(anchor: DrawingAnchor, picture: PictureReference | XlsxImage): DrawingItem {\n  // Distinguish raw image bytes from a full PictureReference by checking the\n  // discriminator: XlsxImage carries `format`, PictureReference doesn't.\n  const ref: PictureReference = 'format' in picture ? { image: picture as XlsxImage } : (picture as PictureReference);\n  return { anchor, content: { kind: 'picture', picture: ref } };\n}\n\n// ---- Worksheet ergonomic helpers ----------------------------------------\n\nimport { loadImage } from './image';\nimport { makeOneCellAnchor } from './anchor';\nimport type { Worksheet } from '../worksheet/worksheet';\n\n/**\n * Drop an image onto a worksheet at a single-cell anchor. Lazy-allocates\n * `ws.drawing` (as `makeDrawing([])`) on first call and appends a picture\n * DrawingItem.\n *\n * `image` accepts either an `XlsxImage` (already loaded via `loadImage`) or raw\n * image bytes — in the bytes case, this helper sniffs the format with\n * `loadImage` itself.\n *\n * `at` is a cell ref like `\"C3\"`. Override `widthPx` / `heightPx` to scale;\n * otherwise the helper uses 96×96 defaults that look fine for typical icons.\n */\nexport const addImageAt = (\n  ws: Worksheet,\n  at: string,\n  image: XlsxImage | Uint8Array,\n  opts: { widthPx?: number; heightPx?: number } = {},\n): DrawingItem => {\n  const xlsxImage: XlsxImage = image instanceof Uint8Array ? loadImage(image) : image;\n  const anchor = makeOneCellAnchor({\n    from: at,\n    widthPx: opts.widthPx ?? 96,\n    heightPx: opts.heightPx ?? 96,\n  });\n  const item = makePictureDrawingItem(anchor, xlsxImage);\n  if (!ws.drawing) ws.drawing = makeDrawing([]);\n  ws.drawing.items.push(item);\n  return item;\n};\n\n/**\n * Anchor a chart to a worksheet at a single-cell ref. Lazy-allocates\n * `ws.drawing`. `chart` is the same `ChartReference` shape `makeChart\n * DrawingItem` accepts (`{ space }` for legacy chart, `{ cxSpace }` for\n * chartex).\n */\nexport const addChartAt = (\n  ws: Worksheet,\n  at: string,\n  chart: ChartReference,\n  opts: { widthPx?: number; heightPx?: number } = {},\n): DrawingItem => {\n  const anchor = makeOneCellAnchor({\n    from: at,\n    widthPx: opts.widthPx ?? 480,\n    heightPx: opts.heightPx ?? 320,\n  });\n  const item = makeChartDrawingItem(anchor, chart);\n  if (!ws.drawing) ws.drawing = makeDrawing([]);\n  ws.drawing.items.push(item);\n  return item;\n};\n\n/**\n * Read-only snapshot of every picture DrawingItem on the sheet. Returns the\n * matching items (each with its anchor + picture reference). Empty array when\n * the sheet has no drawing or only non-picture items.\n */\nexport const listImagesOnSheet = (ws: Worksheet): ReadonlyArray<DrawingItem> => {\n  if (!ws.drawing) return [];\n  return ws.drawing.items.filter((it) => it.content.kind === 'picture');\n};\n\n/**\n * Read-only snapshot of every chart DrawingItem on the sheet. Each item has its\n * anchor + chart reference.\n */\nexport const listChartsOnSheet = (ws: Worksheet): ReadonlyArray<DrawingItem> => {\n  if (!ws.drawing) return [];\n  return ws.drawing.items.filter((it) => it.content.kind === 'chart');\n};\n\n/**\n * Drop every DrawingItem from the worksheet. Returns the count removed. The\n * `ws.drawing` field itself is left in place (empty) so subsequent `addImageAt`\n * / `addChartAt` calls don't have to re-allocate.\n */\nexport const removeAllDrawingItems = (ws: Worksheet): number => {\n  if (!ws.drawing) return 0;\n  const n = ws.drawing.items.length;\n  ws.drawing.items = [];\n  return n;\n};\n\n/**\n * Drop every picture DrawingItem from the worksheet, leaving charts and any\n * other content kinds untouched. Returns the count removed.\n */\nexport const removeAllImages = (ws: Worksheet): number => {\n  if (!ws.drawing) return 0;\n  const before = ws.drawing.items.length;\n  ws.drawing.items = ws.drawing.items.filter((it) => it.content.kind !== 'picture');\n  return before - ws.drawing.items.length;\n};\n\n/**\n * Drop every chart DrawingItem from the worksheet, leaving pictures and any\n * other content kinds untouched. Returns the count removed.\n */\nexport const removeAllCharts = (ws: Worksheet): number => {\n  if (!ws.drawing) return 0;\n  const before = ws.drawing.items.length;\n  ws.drawing.items = ws.drawing.items.filter((it) => it.content.kind !== 'chart');\n  return before - ws.drawing.items.length;\n};\n"],"mappings":"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"}