npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@openmaic/importer

v0.1.0

Published

A javascript tool for parsing .pptx file

Readme

🎨 pptxtojson

⚠️ Browser-only. This package parses .pptx in the browser and depends on DOM APIs (XMLHttpRequest, DOMMatrix, Path2D, via a browser-targeted pdf.js build). It is built for browser / bundler (webpack, Vite, Next client) environments — importing it in a pure Node.js process throws at load. Use it from client code, not from a Node server runtime.

一个运行在浏览器中,可以将 .pptx 文件转为可读的 JSON 数据的 JavaScript 库。

实现说明:主入口为 TypeScript 实现(src/),构建产物为 dist/;输出 JSON 格式与文档及原示例一致。原 JavaScript 实现位于 src1/,仅作输出格式与逻辑参考,不参与构建。

OpenMAIC 扩展:在 parse()(PPTX → 中间 JSON)之上新增了完整的 import pipeline —— importPptx() 直接吃 .pptx 文件、吐 OpenMAIC 画布需要的 Slide[],并可选地把所有 base64 图片 / blob 媒体转交给你提供的 OSS 上传函数。详见下方「🚀 进阶用法」。

与其他的pptx文件解析工具的最大区别在于:

  1. 直接运行在浏览器端;
  2. 解析结果是可读的 JSON 数据,而不仅仅是把 XML 文件内容原样翻译成难以理解的 JSON。

在线DEMO:https://pipipi-pikachu.github.io/pptxtojson/

国内镜像(定期同步):GiteeGitCode

🎯 注意事项

⚒️ 使用场景

本仓库诞生于项目 PPTist ,希望为其“导入 .pptx 文件功能”提供一个参考示例。不过就目前来说,解析出来的PPT信息与源文件在样式上还是存在差异。

但如果你只是需要提取PPT文件的文本内容、媒体资源信息、结构信息等,或者对排版/样式精准度没有特别高的要求,那么 pptxtojson 可能会对你有帮助。

📏 长度值单位

输出的JSON中,所有数值长度值单位都为pt(point)

注意:在0.x版本中,所有输出的长度值单位都是px(像素)

🔨安装

npm install pptxtojson

💿用法

浏览器

<input type="file" accept="application/vnd.openxmlformats-officedocument.presentationml.presentation"/>
import { parse } from 'pptxtojson'

document.querySelector('input').addEventListener('change', evt => {
	const file = evt.target.files[0]
	
	const reader = new FileReader()
	reader.onload = async e => {
		const json = await parse(e.target.result)
		console.log(json)
	}
	reader.readAsArrayBuffer(file)
})

Node.js(实验性,1.5.0以上版本)

const pptxtojson = require('pptxtojson/dist/index.cjs')
const fs = require('fs')

async function func() {
  const buffer = fs.readFileSync('test.pptx')

  const json = await pptxtojson.parse(buffer.buffer)
  console.log(json)
}

func()

🚀 进阶用法:PPTX → OpenMAIC 画布 Slide[]

parse() 只完成「PPTX → 可读 JSON」这一步,元素的字段还是 PPT 语义(type: 'text' | 'shape' | 'image' …、单位 pt、媒体是 base64 / blob: URL)。

如果你需要的最终产物是 OpenMAIC 画布直接可渲染的 Slide[]PPTTextElement / PPTShapeElement / PPTImageElement 等、单位 px、媒体替换为 OSS URL),用 importPptx()

🔑 API 一览

| 导出 | 类型 | 用途 | |------|------|------| | importPptx(input, options?) | (File \| Blob \| ArrayBuffer, ImportPptxOptions?) => Promise<Slide[]> | 一站式:.pptxSlide[],等所有上传 settle 后再 resolve | | parsedToSlides(json, options?) | (Output, ImportPptxOptions?) => Promise<Slide[]> | 只做「中间 JSON → Slide[]」,给已经用 parse() 拿到 JSON 的场景 | | normalizeImportedSlides(slides) | (Slide[]) => Slide[] | DSL 合同边界:补默认值、丢弃无法修复的元素(console.warn 上报)。parsedToSlides / importPptx 已自动应用;直接调用 transformParsedToSlides 的消费方需要自己跑一遍以获得相同的输出契约 | | OssUpload | (blob: Blob, filename: string, dir?: string) => Promise<string> | 上传回调签名 | | ImportPptxOptions | { upload?: OssUpload } | 选项对象 | | CanvasSlide | OpenMAIC Slide 类型 | 用于消费方做类型注解 |

importPptx 内部就是 parse(buffer, { mediaMode: 'base64' }) + parsedToSlides(...),两者任选其一即可。

🧩 完整签名

import {
  importPptx,
  parsedToSlides,
  normalizeImportedSlides,
  type OssUpload,
  type ImportPptxOptions,
  type CanvasSlide,
} from '@openmaic/importer';

export type OssUpload = (
  blob: Blob,
  filename: string,
  dir?: string,
) => Promise<string>;

export interface ImportPptxOptions {
  /**
   * 上传媒体(图片 / 音频 / 视频)到远程存储并返回公网 URL。
   * - 提供:所有 base64 图片会先转成 Blob,再调用此函数,URL 写回 slide。
   * - 不提供:图片保留 base64 data URL;音视频保留临时 `blob:` URL(仅当前 tab 有效)。
   */
  upload?: OssUpload;
}

export function importPptx(
  input: File | Blob | ArrayBuffer,
  options?: ImportPptxOptions,
): Promise<CanvasSlide[]>;

export function parsedToSlides(
  json: Output,
  options?: ImportPptxOptions,
): Promise<CanvasSlide[]>;

export function normalizeImportedSlides(slides: CanvasSlide[]): CanvasSlide[];

📦 用法

1. 不传 upload —— 本地预览 / 调试

媒体留在内存,slide 可以直接在当前 tab 里渲染,但刷新就失效(音视频)/ JSON 体积大(图片)。

import { importPptx } from '@openmaic/importer';

const slides = await importPptx(file);
// slides[*].elements 里的 image.src 还是 data:image/png;base64,…
// audio/video.src 是 blob:http://… URL

2. 传 upload —— 生产场景

把媒体上传到你自己的 OSS / classroom-media / S3 / 任意存储,slide 里只剩 URL:

import { importPptx, type OssUpload } from '@openmaic/importer';

const upload: OssUpload = async (blob, filename, dir) => {
  const form = new FormData();
  form.append('file', blob, filename);
  form.append('dir', dir ?? 'pptx-import');

  const res = await fetch('/api/upload', { method: 'POST', body: form });
  if (!res.ok) throw new Error(`upload failed: ${res.status}`);
  const { url } = await res.json();
  return url; // ← 必须返回最终可访问 URL
};

const slides = await importPptx(file, { upload });
// 此时 slides[*].elements 里的 src 全是 OSS URL

3. 已经用 parse() 拿到 JSON 时

import { parse, parsedToSlides } from '@openmaic/importer';

const json = await parse(buffer, { mediaMode: 'base64' });
const slides = await parsedToSlides(json, { upload });

⚠️ 必须用 mediaMode: 'base64'blob 模式产出的 URL 只在当前 tab 有效,无法上传后跨页面使用。

📞 upload 回调被调用的时机

| 元素类型 | 源数据 | filename 示例 | dir | |---------|--------|---------------|-----| | 背景图片 | base64 → Blob | background_<timestamp>.png | a2m | | 图片元素 | base64 → Blob | image_<timestamp>.png | a2m | | 数学公式渲染图 | base64 → Blob | math_<timestamp>.png | a2m | | 形状的图案填充 | base64 → Blob | pattern_<timestamp>.png | a2m | | 音频 | 直接是 Blob | audio_<timestamp>.mp3 | a2m/audio | | 视频 | 直接是 Blob | video_<timestamp>.mp4 | a2m/video |

并发:内部用 6 路并发上传图片,避免一次性打满网络。

💥 错误处理

  • 单个媒体上传失败 → transform 内部 .catch 吞掉错误(控制台 console.error),该元素的 src 仍是原始 base64 / 空字符串。整体 import 不会失败
  • parse() 解析失败(坏文件等)→ importPptx 直接 throw,调用方自己 try/catch
  • 内部用 Promise.allSettled 等所有上传 settle 后才 resolve,调用方拿到的 Slide[] 不需要再 await 任何东西。

⚠️ 当前限制

| 模块 | 状态 | 影响 | |------|------|------| | 字体白名单(resolveFont) | stub,透传 | 中文字体保留原名,浏览器找不到字体时会回退到默认。后续可移植 PPTist 字体替换逻辑。 | | 视频编码检测(videoCodec) | stub,永远视为支持 | HEVC 等浏览器不支持的编码会变成坏的 <video>,而不是降级到占位图标。 | | SVG path bbox(svgPathParser) | 自实现 tokenizer | 标准命令(M L H V C S Q T A Z 大小写)都覆盖;弧线 bbox 用端点近似,可能略小。 |

🧪 在 Next.js (Turbopack) 里用

maic-importer 源码依赖 pdfjs-dist,其动态 require() 模式会被 Turbopack 拒绝。OpenMAIC 的做法:

  1. pnpm run build 把整个包(含 importPptx)打成 dist/
  2. scripts/sync-maic-importer.mjsdist/ 复制到 public/vendor/maic-importer/
  3. 在客户端组件里用静态 URL 动态 import,bundler 完全看不到:
import type * as PptxtojsonPro from '@openmaic/importer';

const mod = (await import(
  /* webpackIgnore: true */
  /* turbopackIgnore: true */
  /* @vite-ignore */
  '/vendor/maic-importer/index.js'
)) as typeof PptxtojsonPro;

const slides = await mod.importPptx(file, { upload });

类型仍走 workspace 包,IntelliSense 不丢。

参考:lib/import/use-import-pptx.ts

⚠️ 部署依赖(必读)

public/vendor/maic-importer/gitignored 的构建产物,不进仓库,由 postinstall 现生成(pnpm --filter @openmaic/importer build + node scripts/sync-maic-importer.mjs)。 因此部署流水线必须执行 postinstall(或显式跑这两步),否则运行时 /vendor/maic-importer/index.js 会 404,PPTX 导入功能失效。

两道防护已就位:

  • 构建期断言:根 build 脚本前置 node scripts/assert-vendor-maic-importer.mjs, 若 vendor 产物缺失则构建直接失败并给出修复提示,避免把必崩版本部署上线。
  • 运行期守卫use-import-pptx.ts 在动态 import 前先 HEAD 预检该 URL, 404 时抛出明确错误并提示 import.error.parserUnavailable,而不是把 404 HTML 当 JS 解析出诡异的 SyntaxError

另注:git pull 后若未重新 pnpm install,workspace 类型会更新但 URL 加载的 仍是旧 dist,二者可能静默漂移——拉取后请重新安装。


输出示例(parse(),未走 import pipeline)

{
	"slides": [
		{
			"fill": {
				"type": "color",
				"value": "#FF0000"
			},
			"elements": [
				{
					"left":	0,
					"top": 0,
					"width": 72,
					"height":	72,
					"borderColor": "#1F4E79",
					"borderWidth": 1,
					"borderType": "solid",
					"borderStrokeDasharray": 0,
					"fill": {
						"type": "color",
						"value": "#FF0000"
					},
					"content": "<p style=\"text-align: center;\"><span style=\"font-size: 18pt;font-family: Calibri;\">TEST</span></p>",
					"isFlipV": false,
					"isFlipH": false,
					"rotate": 0,
					"vAlign": "mid",
					"name": "矩形 1",
					"type": "shape",
					"shapType": "rect"
				},
				// more...
			],
			"layoutElements": [
				// more...
			],
			"note": "演讲者备注内容..."
		},
		// more...
	],
	"themeColors": ['#4472C4', '#ED7D31', '#A5A5A5', '#FFC000', '#5B9BD5', '#70AD47'],
	"size": {
		"width": 960,
		"height": 540
	}
}

📕 完整功能支持

  • 幻灯片主题色 themeColors

  • 幻灯片尺寸 size

    • 宽度 width
    • 高度 height
  • 幻灯片页面 slides

    • 页面备注 note

    • 页面背景填充(颜色、图片、渐变、图案) fill

      • 纯色填充 type='color'
      • 图片填充 type='image'
      • 渐变填充 type='gradient'
      • 图案填充 type='pattern'
    • 页面切换动画 transition

      • 类型 type
      • 持续时间 duration
      • 方向 direction
    • 页面内元素 elements / 母版元素 layoutElements

      • 文字

        • 类型 type='text'
        • 水平坐标 left
        • 垂直坐标 top
        • 宽度 width
        • 高度 height
        • 边框颜色 borderColor
        • 边框宽度 borderWidth
        • 边框类型(实线、点线、虚线) borderType
        • 非实线边框样式 borderStrokeDasharray
        • 阴影 shadow
        • 填充(颜色、图片、渐变、图案) fill
        • 内容文字(HTML富文本:字体、字号、颜色、渐变、下划线、删除线、斜体、加粗、阴影、角标、超链接) content
        • 垂直翻转 isFlipV
        • 水平翻转 isFlipH
        • 旋转角度 rotate
        • 垂直对齐方向 vAlign
        • 是否为竖向文本 isVertical
        • 元素名 name
        • 自动调整大小 autoFit
          • 类型 type
            • shape:文本框高度会根据文本内容自动调整
            • text:文本框大小固定,字号会自动缩放以适应文本框(注:autoFit不存在时,也会固定文本框大小,但字号不会缩放)
          • 字体缩放比例(type='text'专有,默认为1) fontScale
        • 超链接 link
      • 图片

        • 类型 type='image'
        • 水平坐标 left
        • 垂直坐标 top
        • 宽度 width
        • 高度 height
        • 边框颜色 borderColor
        • 边框宽度 borderWidth
        • 边框类型(实线、点线、虚线) borderType
        • 非实线边框样式 borderStrokeDasharray
        • 裁剪形状 geom
        • 裁剪范围 rect
        • 图片地址(base64) src
        • 旋转角度 rotate
        • 滤镜 filters
        • 超链接 link
      • 形状

        • 类型 type='shape'
        • 水平坐标 left
        • 垂直坐标 top
        • 宽度 width
        • 高度 height
        • 边框颜色 borderColor
        • 边框宽度 borderWidth
        • 边框类型(实线、点线、虚线) borderType
        • 非实线边框样式 borderStrokeDasharray
        • 阴影 shadow
        • 填充(颜色、图片、渐变、图案) fill
        • 内容文字(HTML富文本,与文字元素一致) content
        • 垂直翻转 isFlipV
        • 水平翻转 isFlipH
        • 旋转角度 rotate
        • 形状类型 shapType
        • 垂直对齐方向 vAlign
        • 形状路径 path
        • 形状调整参数 keypoints
        • 元素名 name
        • 自动调整大小 autoFit
        • 超链接 link
      • 表格

        • 类型 type='table'
        • 水平坐标 left
        • 垂直坐标 top
        • 宽度 width
        • 高度 height
        • 边框(4边) borders
        • 表格数据 data
        • 行高 rowHeights
        • 列宽 colWidths
      • 图表

        • 类型 type='chart'
        • 水平坐标 left
        • 垂直坐标 top
        • 宽度 width
        • 高度 height
        • 图表数据 data
        • 图表主题色 colors
        • 图表类型 chartType
        • 柱状图方向 barDir
        • 是否带数据标记 marker
        • 环形图尺寸 holeSize
        • 分组模式 grouping
        • 图表样式 style
      • 视频

        • 类型 type='video'
        • 水平坐标 left
        • 垂直坐标 top
        • 宽度 width
        • 高度 height
        • 视频blob blob
        • 视频src src
      • 音频

        • 类型 type='audio'
        • 水平坐标 left
        • 垂直坐标 top
        • 宽度 width
        • 高度 height
        • 音频blob blob
      • 公式

        • 类型 type='math'
        • 水平坐标 left
        • 垂直坐标 top
        • 宽度 width
        • 高度 height
        • 公式图片 picBase64
        • LaTeX表达式(仅支持常见结构) latex
        • 文本(文本和公式混排时存在) text
      • Smart图

        • 类型 type='diagram'
        • 水平坐标 left
        • 垂直坐标 top
        • 宽度 width
        • 高度 height
        • 子元素集合 elements
        • 文本列表(Smart图中的文字内容清单,仅在elements无法解析时存在) textList
      • 多元素组合

        • 类型 type='group'
        • 水平坐标 left
        • 垂直坐标 top
        • 宽度 width
        • 高度 height
        • 子元素集合 elements

更多类型请参考 👇

https://github.com/pipipi-pikachu/pptxtojson/blob/master/dist/index.d.ts

🙏 感谢

本仓库大量参考了 PPTX2HTMLPPTXjs 的实现。

与它们不同的是:PPTX2HTML 和 PPTXjs 是将PPT文件转换为能够运行的 HTML 页面,而 pptxtojson 做的是将PPT文件转换为干净的 JSON 数据,且在原有基础上进行了大量优化补充(包括代码质量和提取信息的完整度和准确度)。

📄 开源协议

MIT License | Copyright © 2020-PRESENT pipipi-pikachu