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

@work-zhanguo/pptx-preview

v0.0.4

Published

Lightweight PPTX preview component for Vue 3, Vue 2 adapter, and standalone usage / 轻量级 PPTX 预览组件,支持 Vue3、Vue2、standalone 与 Odoo 等项目集成。

Downloads

542

Readme

项目简介

  • 当前版本:0.0.4
  • 项目定位:独立的 PPTX 预览组件,只处理 PPTX 在线预览
  • 适用场景:业务系统方案查看、汇报材料查看、页面内嵌预览、弹窗预览、老项目独立挂载
  • 集成形态:Vue3、Vue2、原生项目、Odoo等环境

当前能力:

  • 支持远程 URL、本地 FileBlob
  • 支持缩略图导航、上下页切换、缩放、自动播放、原文件下载
  • 支持页面内嵌预览和弹窗预览
  • 支持弹窗工具栏按钮按项配置,默认展示上一页、下一页、播放、缩小、缩放值、放大、下载、关闭
  • 支持集成方通过组件实例 ref 自己绘制外部工具栏

怎么实现的:

  • 第一步,集成方把 source 传进来,组件支持远程 URL、本地 FileBlob。输入层会先把这些来源统一成可读取的数据。
  • 第二步,加载层调用 pptxtojson 解析原始 pptx 文件,把它转成中间 JSON。这里会拿到页面尺寸、主题色、每页元素、备注和过渡信息。
  • 第三步,项目会把第三方解析结果再做一次标准化,整理成组件内部稳定的数据结构。这样做是为了降低第三方库输出波动对渲染层的影响。
  • 第四步,预览组件维护自己的运行状态,包括当前页、总页数、缩放比例、自动播放状态、弹窗显隐状态。工具栏操作、缩略图点击、外部 ref 调用,最后都会落到这层状态更新。
  • 第五步,渲染层按页渲染内容。右侧主区域只渲染当前页,左侧缩略图区渲染所有页面的小图导航。文本、图片、形状等元素会分配给对应的渲染逻辑处理。
  • 第六步,样式层统一收敛在 .ppx-* 命名空间下,避免把组件样式污染到宿主项目全局。
  • 第七步,输出层按不同集成场景提供不同入口。Vue3 直接用主入口,Vue2 通过适配层挂载隔离的 Vue3 实例,非 Vue 页面和 Odoo 走 standalone 入口。

一句话概括:

  • 先把 PPTX 解析成稳定数据
  • 再用组件状态驱动预览渲染
  • 最后按 Vue3 / Vue2 / standalone 三种方式提供给集成方使用

核心文件定位:

  • src/components/PptxPreview.vue:主预览组件,负责状态、工具栏、缩略图、弹窗逻辑
  • src/components/PptxSlideView.vue:单页视图渲染
  • src/components/PptxElementRenderer.vue:元素级渲染
  • src/utils/source.ts:输入源读取
  • src/utils/load.ts:解析与加载
  • src/utils/render.ts:渲染辅助逻辑
  • src/vue2.ts:Vue2 适配入口
  • src/standalone-api.ts:standalone 挂载 API

如果你要预览 PDF / DOCX / XLSX / 图片 / 文本 / 音视频 等其他文件,请使用:

效果预览

弹窗预览示例

PPTX 弹窗预览效果

样式隔离与集成安全

样式审计结论:

  • npm 主入口只引入 src/styles/component.css
  • 发布到包内的样式都挂在 .ppx-* 命名空间下
  • 不会主动改写 bodyhtmlbuttonimgtable 这类全局选择器
  • demo 页使用的页面级样式只在演示站里生效,不会通过组件库主入口带给集成方

集成建议:

  • Vue3 项目使用 @work-zhanguo/pptx-preview
  • Vue2 项目使用 @work-zhanguo/pptx-preview/vue2
  • 非 Vue 页面或老系统模板页使用 @work-zhanguo/pptx-preview/standalone
  • 样式只引入 @work-zhanguo/pptx-preview/style.css 或对应入口的 style.css

安装

npm install @work-zhanguo/pptx-preview

组件属性

| 属性 | 类型 | 默认值 | 说明 | | --- | --- | --- | --- | | source | string \| File \| Blob | - | 必填。支持远程 URL、本地 FileBlob。 | | fileName | string | - | 自定义文件名,远程地址没有扩展名时建议传。 | | mode | 'inline' \| 'dialog' | 'inline' | 页面内嵌预览或弹窗预览。 | | visible | boolean | true | 弹窗模式下控制显示状态,可配合 v-model:visible。 | | loadingText | string | 'PPTX 加载中...' | 加载提示文案。 | | dialogTitle | string | 'PPTX 预览' | 标题兜底文案。 | | showToolbar | boolean | true | 是否显示顶部工具栏。 | | showThumbnails | boolean | true | 是否显示左侧缩略图列表。 | | autoPlay | boolean | false | 是否默认自动播放。 | | playInterval | number | 3000 | 自动播放间隔,单位毫秒。 | | loopPlayback | boolean | true | 播放到最后一页后是否循环。 | | initialSlide | number | 0 | 初始页索引,从 0 开始。 | | toolbarActions | Partial<PptxPreviewToolbarActions> | 全部 true | 工具栏按钮显示配置,可按项关闭。 |

toolbarActions 可配置项

| 字段 | 默认值 | 说明 | | --- | --- | --- | | prev | true | 上一页 | | next | true | 下一页 | | play | true | 播放 / 停止 | | zoomOut | true | 缩小按钮 | | zoomReset | true | 中间缩放值按钮 | | zoomIn | true | 放大按钮 | | download | true | 下载原文件 | | close | true | 弹窗关闭按钮,仅弹窗模式生效 |

组件事件:

  • loaded:解析完成后返回标准化演示文稿对象
  • error:解析失败时返回错误对象
  • slide-change:当前页变更时返回页索引
  • update:visible:弹窗关闭时回传状态

弹窗预览配置示例

默认情况下,弹窗预览会显示:

  • 上一页
  • 下一页
  • 播放
  • 缩小
  • 缩放值
  • 放大
  • 下载原文件
  • 关闭

如果你想去掉其中一部分按钮:

<template>
  <button @click="show = true">打开弹窗预览</button>

  <PptxPreview
    v-model:visible="show"
    source="/files/demo.pptx"
    mode="dialog"
    :toolbar-actions="{
      play: false,
      download: false,
      close: true
    }"
  />
</template>

<script setup lang="ts">
import { ref } from 'vue';

const show = ref(false);
</script>

Vue 3 集成

import { createApp } from 'vue';
import App from './App.vue';
import PptxPreviewPlugin from '@work-zhanguo/pptx-preview';
import '@work-zhanguo/pptx-preview/style.css';

createApp(App).use(PptxPreviewPlugin).mount('#app');
<template>
  <PptxPreview
    source="/files/demo.pptx"
    :show-toolbar="true"
    :show-thumbnails="true"
  />
</template>

Vue 3 自定义外部工具栏

如果你不想用组件自带工具栏,可以隐藏它,然后通过实例方法自己接按钮:

<template>
  <div class="toolbar">
    <button @click="previewRef?.prevSlide()">上一页</button>
    <button @click="previewRef?.nextSlide()">下一页</button>
    <button @click="previewRef?.zoomOut()">缩小</button>
    <button @click="previewRef?.zoomIn()">放大</button>
    <button @click="previewRef?.togglePlayback()">播放 / 停止</button>
  </div>

  <PptxPreview
    ref="previewRef"
    :source="source"
    :show-toolbar="false"
    :show-thumbnails="true"
  />
</template>

<script setup lang="ts">
import { ref } from 'vue';
import { PptxPreview } from '@work-zhanguo/pptx-preview';
import type { PptxPreviewInstance } from '@work-zhanguo/pptx-preview';

const source = '/files/demo.pptx';
const previewRef = ref<PptxPreviewInstance | null>(null);
</script>

Vue 2 集成

Vue2 入口不是直接把宿主 Vue2 runtime 和本组件的 Vue3 runtime 混在一起,而是通过适配层挂载隔离的 Vue3 预览实例。

import Vue from 'vue';
import PptxPreview from '@work-zhanguo/pptx-preview/vue2';
import '@work-zhanguo/pptx-preview/vue2/style.css';

Vue.use(PptxPreview);
<template>
  <PptxPreview
    :source="fileUrl"
    :show-toolbar="true"
    :toolbar-actions="{ download: false }"
  />
</template>

Standalone 集成

如果目标项目不是 Vue,或者现有构建链路不适合直接引入 Vue 组件入口,可以使用 standalone。

1. 通过 bundler 导入 ESM

import PptxPreviewStandalone from '@work-zhanguo/pptx-preview/standalone';
import '@work-zhanguo/pptx-preview/standalone/style.css';

PptxPreviewStandalone.mount('#pptx-root', {
  source: '/files/demo.pptx',
  showToolbar: true,
  toolbarActions: {
    download: true
  }
});

2. 通过脚本标签挂载 IIFE

<link rel="stylesheet" href="/vendor/pptx-preview/style.css" />
<div id="pptx-root"></div>
<script src="/vendor/pptx-preview/pptx-preview.iife.js"></script>
<script>
  window.PptxPreview.mount('#pptx-root', {
    source: '/files/demo.pptx',
    showToolbar: true
  });
</script>

Odoo 集成

Odoo 推荐走 standalone 产物,不要把整个 Vue 工程直接塞进现有页面。

/** @odoo-module **/

import { Component, onMounted, useRef } from '@odoo/owl';
import PptxPreviewStandalone from '@work-zhanguo/pptx-preview/standalone';
import '@work-zhanguo/pptx-preview/standalone/style.css';

export class PptxPreviewBlock extends Component {
  setup() {
    this.rootRef = useRef('root');

    onMounted(() => {
      PptxPreviewStandalone.mount(this.rootRef.el, {
        source: this.props.source,
        fileName: this.props.fileName || 'demo.pptx',
        showToolbar: true
      });
    });
  }
}

打包冲突说明

为降低集成到其他项目后的冲突风险,当前包按下面的方式分流:

  • 主入口 @work-zhanguo/pptx-previewvue 作为 peer dependency,给 Vue3 项目复用宿主自己的 Vue3
  • Vue2 入口 @work-zhanguo/pptx-preview/vue2:通过适配层挂载隔离的 Vue3 预览实例,不直接和宿主 Vue2 runtime 混编
  • Standalone 入口 @work-zhanguo/pptx-preview/standalone:适合非 Vue 项目、老模板页、Odoo、脚本注入页面
  • IIFE 入口 @work-zhanguo/pptx-preview/standalone/iife:适合 <script> 标签直出场景

推荐做法:

  • Vue3 项目只用主入口
  • Vue2 项目只用 ./vue2
  • 非 Vue 页面只用 standalone
  • 不要在一个页面里同时混用主入口和 standalone

如果想预览其他文件

本项目只负责 PPTX

如果你还要同时预览这些文件:

  • PDF
  • DOCX
  • XLSX
  • 图片
  • 文本
  • 音视频

请使用:

构建与调试

npm install
npm run generate:demo
npm run dev

组件库打包:

npm run build

产物目录:

  • dist/
  • dist/vue2/
  • dist/standalone/
  • dist-site/

Overview

  • Current version: 0.0.4
  • Project scope: a dedicated PPTX preview component that only handles online PPTX preview
  • Use cases: proposal decks, business reports, inline preview, dialog preview, and legacy-page embedding
  • Integration targets: Vue3, Vue2, native web pages, and Odoo-like environments

Current capabilities:

  • Supports remote URL, local File, and Blob
  • Supports thumbnails, paging, zoom, autoplay, and original-file download
  • Supports inline preview and dialog preview
  • Supports per-action dialog toolbar configuration
  • Supports external host-side toolbar control through instance methods

How it works:

  • First, the host passes source, which can be a remote URL, local File, or Blob. The input layer normalizes all of them into a readable source.
  • Second, the loading layer calls pptxtojson to parse the original pptx file into an intermediate JSON structure. That structure includes slide size, theme colors, slide elements, notes, and transitions.
  • Third, the project normalizes that parser output into a stable internal data shape so the rendering layer does not depend directly on third-party output quirks.
  • Fourth, the preview component manages runtime state such as current slide, slide count, zoom level, autoplay state, and dialog visibility. Toolbar actions, thumbnail clicks, and external ref calls all update this state.
  • Fifth, the rendering layer paints the preview. The main stage renders the active slide, while the thumbnail rail renders the full slide list for navigation. Text, image, and shape elements are handled by their corresponding render logic.
  • Sixth, styles stay under the .ppx-* namespace to avoid leaking into the host project's global styles.
  • Seventh, the package exposes different integration entries for different hosts. Vue3 uses the main entry, Vue2 uses an adapter that mounts an isolated Vue3 instance, and non-Vue or Odoo-like pages use the standalone entry.

Short version:

  • parse PPTX into stable internal data
  • use component state to drive preview rendering
  • expose the result through Vue3 / Vue2 / standalone

Core file map:

  • src/components/PptxPreview.vue: main preview component, state, toolbar, thumbnail rail, dialog behavior
  • src/components/PptxSlideView.vue: single-slide rendering
  • src/components/PptxElementRenderer.vue: element-level rendering
  • src/utils/source.ts: source loading
  • src/utils/load.ts: parsing and loading
  • src/utils/render.ts: render helpers
  • src/vue2.ts: Vue2 adapter entry
  • src/standalone-api.ts: standalone mount API

If you want to preview other file types such as PDF / DOCX / XLSX / image / text / audio / video, use:

Preview Screenshot

Dialog Preview Example

PPTX dialog preview

Style Isolation and Integration Safety

Style audit result:

  • The npm main entry only imports src/styles/component.css
  • Published styles are scoped under the .ppx-* namespace
  • The package does not rewrite generic global selectors such as body, html, button, img, or table
  • Demo-page styles are not shipped through the library entry

Recommended integration paths:

  • Vue3 projects should use @work-zhanguo/pptx-preview
  • Vue2 projects should use @work-zhanguo/pptx-preview/vue2
  • Non-Vue or legacy pages should use @work-zhanguo/pptx-preview/standalone
  • Only import @work-zhanguo/pptx-preview/style.css or the style.css file that belongs to the entry you are using

Installation

npm install @work-zhanguo/pptx-preview

For Vue2 projects, keep the same package name but import from @work-zhanguo/pptx-preview/vue2.

Component Props

| Prop | Type | Default | Description | | --- | --- | --- | --- | | source | string \| File \| Blob | - | Required. Supports remote URLs, local File, and Blob. | | fileName | string | - | Optional file name. Recommended when the URL has no extension. | | mode | 'inline' \| 'dialog' | 'inline' | Inline preview or dialog preview. | | visible | boolean | true | Controls dialog visibility and works with v-model:visible. | | loadingText | string | 'PPTX 加载中...' | Loading text shown during parsing. | | dialogTitle | string | 'PPTX 预览' | Fallback title. | | showToolbar | boolean | true | Whether to render the toolbar. | | showThumbnails | boolean | true | Whether to render the thumbnail rail. | | autoPlay | boolean | false | Whether playback starts automatically. | | playInterval | number | 3000 | Autoplay interval in milliseconds. | | loopPlayback | boolean | true | Whether playback loops after the last slide. | | initialSlide | number | 0 | Initial slide index. | | toolbarActions | Partial<PptxPreviewToolbarActions> | all true | Per-button toolbar visibility config. |

toolbarActions Fields

| Field | Default | Description | | --- | --- | --- | | prev | true | Previous slide | | next | true | Next slide | | play | true | Play / Stop | | zoomOut | true | Zoom out button | | zoomReset | true | Zoom status button | | zoomIn | true | Zoom in button | | download | true | Download original file | | close | true | Close button, dialog mode only |

Events:

  • loaded: returns the normalized presentation object after parsing
  • error: returns the error object when parsing fails
  • slide-change: returns the current slide index when the active slide changes
  • update:visible: returns dialog visibility changes when the dialog closes

Dialog Toolbar Config Example

Dialog preview shows these buttons by default:

  • Previous
  • Next
  • Play
  • Zoom Out
  • Zoom Value
  • Zoom In
  • Download
  • Close

To remove some of them:

<template>
  <button @click="show = true">Open dialog preview</button>

  <PptxPreview
    v-model:visible="show"
    source="/files/demo.pptx"
    mode="dialog"
    :toolbar-actions="{
      play: false,
      download: false,
      close: true
    }"
  />
</template>

<script setup lang="ts">
import { ref } from 'vue';

const show = ref(false);
</script>

Vue 3 Integration

import { createApp } from 'vue';
import App from './App.vue';
import PptxPreviewPlugin from '@work-zhanguo/pptx-preview';
import '@work-zhanguo/pptx-preview/style.css';

createApp(App).use(PptxPreviewPlugin).mount('#app');
<template>
  <PptxPreview
    source="/files/demo.pptx"
    :show-toolbar="true"
    :show-thumbnails="true"
  />
</template>

Vue 3 Custom Toolbar

If you do not want to use the built-in toolbar, hide it and connect your own buttons through the component instance methods:

<template>
  <div class="toolbar">
    <button @click="previewRef?.prevSlide()">Prev</button>
    <button @click="previewRef?.nextSlide()">Next</button>
    <button @click="previewRef?.zoomOut()">Zoom Out</button>
    <button @click="previewRef?.zoomIn()">Zoom In</button>
    <button @click="previewRef?.togglePlayback()">Play / Stop</button>
  </div>

  <PptxPreview
    ref="previewRef"
    :source="source"
    :show-toolbar="false"
    :show-thumbnails="true"
  />
</template>

<script setup lang="ts">
import { ref } from 'vue';
import { PptxPreview } from '@work-zhanguo/pptx-preview';
import type { PptxPreviewInstance } from '@work-zhanguo/pptx-preview';

const source = '/files/demo.pptx';
const previewRef = ref<PptxPreviewInstance | null>(null);
</script>

Vue 2 Integration

The Vue2 entry does not mix the host Vue2 runtime with the component's Vue3 runtime directly. It mounts an isolated Vue3 preview instance through an adapter layer.

import Vue from 'vue';
import PptxPreview from '@work-zhanguo/pptx-preview/vue2';
import '@work-zhanguo/pptx-preview/vue2/style.css';

Vue.use(PptxPreview);
<template>
  <PptxPreview :source="fileUrl" :toolbar-actions="{ download: false }" />
</template>

Standalone Integration

If the target project is not Vue, or the existing build chain is not suitable for importing the Vue component entry directly, use the standalone entry instead.

1. ESM for bundlers

import PptxPreviewStandalone from '@work-zhanguo/pptx-preview/standalone';
import '@work-zhanguo/pptx-preview/standalone/style.css';

PptxPreviewStandalone.mount('#pptx-root', {
  source: '/files/demo.pptx',
  showToolbar: true,
  toolbarActions: {
    download: true
  }
});

2. IIFE for script-tag pages

<link rel="stylesheet" href="/vendor/pptx-preview/style.css" />
<div id="pptx-root"></div>
<script src="/vendor/pptx-preview/pptx-preview.iife.js"></script>
<script>
  window.PptxPreview.mount('#pptx-root', {
    source: '/files/demo.pptx',
    showToolbar: true
  });
</script>

Odoo Integration

For Odoo, prefer the standalone bundle instead of forcing the full Vue component entry into the host page.

/** @odoo-module **/

import { Component, onMounted, useRef } from '@odoo/owl';
import PptxPreviewStandalone from '@work-zhanguo/pptx-preview/standalone';
import '@work-zhanguo/pptx-preview/standalone/style.css';

export class PptxPreviewBlock extends Component {
  setup() {
    this.rootRef = useRef('root');

    onMounted(() => {
      PptxPreviewStandalone.mount(this.rootRef.el, {
        source: this.props.source,
        fileName: this.props.fileName || 'demo.pptx',
        showToolbar: true
      });
    });
  }
}

Bundling Conflict Notes

To reduce integration conflicts:

  • Main entry @work-zhanguo/pptx-preview is for Vue3 hosts and uses vue as a peer dependency
  • Vue2 entry @work-zhanguo/pptx-preview/vue2 mounts an isolated Vue3 preview instance through an adapter
  • Standalone entry @work-zhanguo/pptx-preview/standalone is intended for non-Vue pages and embedded environments
  • IIFE entry @work-zhanguo/pptx-preview/standalone/iife is intended for direct <script> usage

Recommended usage:

  • Vue3 projects: main entry only
  • Vue2 projects: ./vue2 only
  • Non-Vue pages: standalone only
  • Do not mix the main entry and the standalone entry on the same page

If You Need Other File Types

This project only handles PPTX.

If you also need to preview:

  • PDF
  • DOCX
  • XLSX
  • images
  • text
  • audio or video

use:

Build

npm install
npm run generate:demo
npm run dev

Build the component library:

npm run build

Build outputs:

  • dist/
  • dist/vue2/
  • dist/standalone/
  • dist-site/