refactor: web-to-pixso → web-to-ppt 全面改名
- 目录 web-to-pixso/ → web-to-ppt/ - 所有代码引用:PIXSO → WEB_TO_PPT, webToPixso → webToPPT - 数据格式:pixso-design-capture → web-to-ppt-capture - CSS 选择器:__web_to_pixso_ → __web_to_ppt_ - README 重写,移除 Pixso 相关描述 - docs/web-to-pixso-mapping.md → docs/web-to-ppt-mapping.md
@@ -2,9 +2,9 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* convert-w2p.js — web-to-pixso JSON → html2pptx Schema JSON 转换器
|
||||
* convert-w2p.js — web-to-ppt JSON → html2pptx Schema JSON 转换器
|
||||
*
|
||||
* 将 web-to-pixso Chrome 扩展导出的 JSON 格式转换为 html2pptx 的
|
||||
* 将 web-to-ppt Chrome 扩展导出的 JSON 格式转换为 html2pptx 的
|
||||
* presentation Schema JSON(presentation.schema.json),使其可以通过
|
||||
* renderer/index.js 生成 PPTX 文件。
|
||||
*
|
||||
@@ -97,7 +97,7 @@ function pxToPt(px) {
|
||||
// ============================================================
|
||||
|
||||
/**
|
||||
* 将单个 web-to-pixso 节点转换为一个 html2pptx schema 对象。
|
||||
* 将单个 web-to-ppt 节点转换为一个 html2pptx schema 对象。
|
||||
*
|
||||
* 转换规则:
|
||||
* - type: "text" → { type: "text", text, options }
|
||||
@@ -256,9 +256,9 @@ function collectObjects(nodeId, ctx, processed) {
|
||||
// ============================================================
|
||||
|
||||
/**
|
||||
* 转换 web-to-pixso JSON 为 html2pptx Schema JSON。
|
||||
* 转换 web-to-ppt JSON 为 html2pptx Schema JSON。
|
||||
*
|
||||
* @param {Object} input web-to-pixso 格式的 JSON 对象
|
||||
* @param {Object} input web-to-ppt 格式的 JSON 对象
|
||||
* @returns {Object} html2pptx Schema JSON 对象
|
||||
*/
|
||||
async function convert(input) {
|
||||
|
||||
@@ -92,7 +92,7 @@
|
||||
### 2.1 自动识别 Slide 容器
|
||||
|
||||
```
|
||||
输入:web-to-pixso JSON 的 nodes 树
|
||||
输入:web-to-ppt JSON 的 nodes 树
|
||||
输出:slide 容器列表
|
||||
|
||||
策略:
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# web-to-pixso → PPT 映射分析
|
||||
# web-to-ppt → PPT 映射分析
|
||||
|
||||
## 1. JSON 结构总览
|
||||
|
||||
@@ -113,7 +113,7 @@ visualRole - layout-wrapper/text-node/raster-fallback
|
||||
## 4. 当前代码架构
|
||||
|
||||
```
|
||||
HTML → web-to-pixso 插件 → JSON
|
||||
HTML → web-to-ppt 插件 → JSON
|
||||
↓
|
||||
convert-w2p.js(提取+映射)
|
||||
↓
|
||||
@@ -143,7 +143,7 @@ HTML → web-to-pixso 插件 → JSON
|
||||
- [ ] 实现 P1:letterSpacing、textDecoration、display/visibility 过滤
|
||||
|
||||
### 中期
|
||||
- [ ] 建立 web-to-pixso JSON 的完整字段文档
|
||||
- [ ] 建立 web-to-ppt JSON 的完整字段文档
|
||||
- [ ] 验证不同 HTML 结构的 JSON 输出一致性
|
||||
- [ ] 处理 transform(旋转)
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
# Web to Pixso
|
||||
|
||||
一套对标 `figma-capture-extension` 使用体验的网页采集工具,包含 Chrome 扩展和 Pixso 导入插件。
|
||||
|
||||
## 目录
|
||||
|
||||
- `manifest.json`、`popup.*`、`background.js`、`capture.js`、`runner.js`:Chrome 扩展
|
||||
- `pixso-plugin/`:Pixso 插件,用于导入扩展导出的 JSON 文件
|
||||
- `logo/`:扩展与插件图标
|
||||
|
||||
## 使用
|
||||
|
||||
1. 打开 `chrome://extensions/`,开启开发者模式。
|
||||
2. 点击“加载已解压的扩展程序”,选择本目录 `web-to-pixso`。
|
||||
3. 打开要采集的网页,点击扩展图标,按需开启“跨域图片代理模式”,点击“开始采集”。
|
||||
4. 扩展会下载一个 `web-to-pixso/*.json` 文件。
|
||||
5. 在 Pixso 中导入 `pixso-plugin/manifest.json`,运行插件并选择上一步下载的 JSON 文件。若旧版导入器要求 `plugin.json`,目录内也保留了同内容兼容文件。
|
||||
|
||||
## 数据格式
|
||||
|
||||
扩展导出的文件格式为 `pixso-design-capture`,包含页面来源、画布尺寸、DOM 节点树、图片资源、字体和诊断信息。Pixso 插件会尽量还原:
|
||||
|
||||
- 文本图层
|
||||
- 图片和背景图片
|
||||
- 背景色、边框、圆角、透明度
|
||||
- DOM 层级和基础坐标
|
||||
|
||||
## 注意
|
||||
|
||||
网页到设计稿的转换无法做到 100% 语义等价,复杂 CSS、canvas、视频帧、伪元素和部分字体效果可能需要在 Pixso 中二次微调。
|
||||
@@ -0,0 +1,29 @@
|
||||
# Web to PPT
|
||||
|
||||
网页采集 → PPTX 导出工具,包含 Chrome 扩展和转化引擎。
|
||||
|
||||
## 组件
|
||||
|
||||
- `capture.js`:DOM 提取引擎(在页面上下文中运行)
|
||||
- `runner.js`:预处理(冻结动画、滚动加载、等待图片)
|
||||
- `background.js`:Service Worker,编排采集流程
|
||||
- `popup.html/js/css`:扩展弹出窗口 UI
|
||||
- `convert-browser.js`:浏览器版转化逻辑(JSON → PPTX Schema)
|
||||
- `lib-pptxgen.js`:pptxgenjs 浏览器 bundle
|
||||
|
||||
## 使用
|
||||
|
||||
1. 在 Chrome 中加载 `web-to-ppt/` 为未打包扩展
|
||||
2. 打开目标网页
|
||||
3. 点击扩展图标,设置采集宽度
|
||||
4. 点击"导出 PPTX"
|
||||
5. 自动下载生成的 PPTX 文件
|
||||
|
||||
## 文件格式
|
||||
|
||||
扩展导出的 JSON 文件包含:
|
||||
- `source`:页面 URL、标题、视口信息
|
||||
- `canvas`:画布尺寸和背景色
|
||||
- `nodes`:DOM 节点树(FRAME/TEXT/RECTANGLE 类型)
|
||||
- `assets`:图片资源(base64)
|
||||
- `fonts`:字体列表
|
||||
@@ -1,6 +1,6 @@
|
||||
const CAPTURE_FILE = "capture.js";
|
||||
const RUNNER_FILE = "runner.js";
|
||||
const SETTINGS_KEY = "webToPixsoSettings";
|
||||
const SETTINGS_KEY = "webToPPTSettings";
|
||||
const DEFAULT_SETTINGS = {
|
||||
useProxy: false,
|
||||
concurrency: "8",
|
||||
@@ -66,7 +66,7 @@ async function runCapture(tabId, options) {
|
||||
});
|
||||
const [{ result }] = await chrome.scripting.executeScript({
|
||||
target: { tabId },
|
||||
func: captureOptions => window.__webToPixsoRunCapture(captureOptions),
|
||||
func: captureOptions => window.__webToPPTRunCapture(captureOptions),
|
||||
args: [options]
|
||||
});
|
||||
if (!result) {
|
||||
@@ -221,7 +221,7 @@ function arrayBufferToBase64(buffer) {
|
||||
// 消息处理
|
||||
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
|
||||
// 采集并下载 JSON(兼容旧流程)
|
||||
if (message?.type === "PIXSO_CAPTURE_START") {
|
||||
if (message?.type === "WEB_TO_PPT_CAPTURE_START") {
|
||||
(async () => {
|
||||
const settings = normalizeSettings(message.options);
|
||||
await chrome.storage.local.set({ [SETTINGS_KEY]: settings });
|
||||
@@ -91,16 +91,16 @@
|
||||
|
||||
let nodeCounter = 0;
|
||||
let rasterCounter = 0;
|
||||
const CAPTURE_SCHEMA = "web-to-pixso-capture";
|
||||
const CAPTURE_SCHEMA = "web-to-ppt-capture";
|
||||
const CAPTURE_SCHEMA_VERSION = "1.1.1";
|
||||
|
||||
function isWebToPixsoElement(element) {
|
||||
function isWebToPPTElement(element) {
|
||||
if (!element?.closest) return false;
|
||||
return Boolean(element.closest([
|
||||
"#__web_to_pixso_panel_root__",
|
||||
"#__web_to_pixso_picker_root__",
|
||||
"#__web_to_pixso_picker_box__",
|
||||
"#__web_to_pixso_picker_label__"
|
||||
"#__web_to_ppt_panel_root__",
|
||||
"#__web_to_ppt_picker_root__",
|
||||
"#__web_to_ppt_picker_box__",
|
||||
"#__web_to_ppt_picker_label__"
|
||||
].join(",")));
|
||||
}
|
||||
|
||||
@@ -671,7 +671,7 @@
|
||||
}
|
||||
|
||||
function isUsefulHeaderElement(element, headerRect) {
|
||||
if (!element || isWebToPixsoElement(element)) return false;
|
||||
if (!element || isWebToPPTElement(element)) return false;
|
||||
if (/^(HTML|BODY|SCRIPT|STYLE|META|LINK)$/i.test(element.tagName || "")) return false;
|
||||
const rect = element.getBoundingClientRect();
|
||||
const style = window.getComputedStyle(element);
|
||||
@@ -770,7 +770,7 @@
|
||||
const escaped = window.CSS?.escape
|
||||
? CSS.escape(raw)
|
||||
: raw.replace(/["\\]/g, "\\$&");
|
||||
return document.querySelector(`[data-web-to-pixso-selection-id="${escaped}"]`);
|
||||
return document.querySelector(`[data-web-to-ppt-selection-id="${escaped}"]`);
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
@@ -910,7 +910,7 @@
|
||||
|
||||
function elementToCaptureNode(element, assetUrls, clipRect, diagnostics, context = {}) {
|
||||
if (!element || SKIP_TAGS.has(element.tagName)) return null;
|
||||
if (isWebToPixsoElement(element)) return null;
|
||||
if (isWebToPPTElement(element)) return null;
|
||||
if (isCarouselClone(element)) {
|
||||
if (diagnostics) diagnostics.skippedCarouselClones += 1;
|
||||
return null;
|
||||
@@ -1062,7 +1062,7 @@
|
||||
throw new Error("扩展代理不可用");
|
||||
}
|
||||
const response = await chrome.runtime.sendMessage({
|
||||
type: "PIXSO_CAPTURE_FETCH_ASSET",
|
||||
type: "WEB_TO_PPT_FETCH_ASSET",
|
||||
url
|
||||
});
|
||||
if (!response?.ok) {
|
||||
@@ -1082,14 +1082,14 @@
|
||||
let response = null;
|
||||
try {
|
||||
response = await chrome.runtime.sendMessage({
|
||||
type: "PIXSO_CAPTURE_VISIBLE_TAB"
|
||||
type: "WEB_TO_PPT_VISIBLE_TAB"
|
||||
});
|
||||
} catch (error) {
|
||||
console.warn("[Web to Pixso] Raster fallback message failed", error);
|
||||
console.warn("[Web to PPT] Raster fallback message failed", error);
|
||||
return null;
|
||||
}
|
||||
if (!response?.ok || !response.dataUrl) {
|
||||
console.warn("[Web to Pixso] Raster fallback skipped", response?.error || "标签页截图失败");
|
||||
console.warn("[Web to PPT] Raster fallback skipped", response?.error || "标签页截图失败");
|
||||
return null;
|
||||
}
|
||||
const image = new Image();
|
||||
@@ -1102,7 +1102,7 @@
|
||||
});
|
||||
return image;
|
||||
} catch (error) {
|
||||
console.warn("[Web to Pixso] Raster fallback image decode failed", error);
|
||||
console.warn("[Web to PPT] Raster fallback image decode failed", error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1129,7 +1129,7 @@
|
||||
function hideFixedTopOverlays() {
|
||||
const hidden = [];
|
||||
for (const element of Array.from(document.body?.querySelectorAll("*") || [])) {
|
||||
if (isWebToPixsoElement(element)) continue;
|
||||
if (isWebToPPTElement(element)) continue;
|
||||
const style = window.getComputedStyle(element);
|
||||
if (style.position !== "fixed" && style.position !== "sticky") continue;
|
||||
const rect = element.getBoundingClientRect();
|
||||
@@ -1166,13 +1166,13 @@
|
||||
};
|
||||
}
|
||||
|
||||
function hideWebToPixsoOverlays() {
|
||||
function hideWebToPPTOverlays() {
|
||||
const hidden = [];
|
||||
for (const selector of [
|
||||
"#__web_to_pixso_panel_root__",
|
||||
"#__web_to_pixso_picker_root__",
|
||||
"#__web_to_pixso_picker_box__",
|
||||
"#__web_to_pixso_picker_label__"
|
||||
"#__web_to_ppt_panel_root__",
|
||||
"#__web_to_ppt_picker_root__",
|
||||
"#__web_to_ppt_picker_box__",
|
||||
"#__web_to_ppt_picker_label__"
|
||||
]) {
|
||||
const element = document.querySelector(selector);
|
||||
if (!element) continue;
|
||||
@@ -1212,9 +1212,9 @@
|
||||
|
||||
function hideTextForBackgroundRaster(targetRect) {
|
||||
const style = document.createElement("style");
|
||||
style.setAttribute("data-web-to-pixso-background-raster", "true");
|
||||
style.setAttribute("data-web-to-ppt-background-raster", "true");
|
||||
style.textContent = `
|
||||
html body *:not(#__web_to_pixso_panel_root__):not(#__web_to_pixso_picker_root__) {
|
||||
html body *:not(#__web_to_ppt_panel_root__):not(#__web_to_ppt_picker_root__) {
|
||||
color: transparent !important;
|
||||
-webkit-text-fill-color: transparent !important;
|
||||
text-shadow: none !important;
|
||||
@@ -1239,7 +1239,7 @@
|
||||
const isTransparent = value => !value || /transparent|rgba\([^)]*,\s*0(?:\.0+)?\)/i.test(value);
|
||||
|
||||
for (const element of Array.from(document.body?.querySelectorAll("*") || [])) {
|
||||
if (isWebToPixsoElement(element)) continue;
|
||||
if (isWebToPPTElement(element)) continue;
|
||||
const style = window.getComputedStyle(element);
|
||||
const rect = element.getBoundingClientRect();
|
||||
if (!isVisible(element, rect, style)) continue;
|
||||
@@ -1615,7 +1615,7 @@
|
||||
const scrollY = Math.max(0, Math.min(target.rect.y, document.documentElement.scrollHeight - window.innerHeight));
|
||||
window.scrollTo(0, scrollY);
|
||||
await new Promise(resolve => setTimeout(resolve, 620));
|
||||
const restorePluginOverlays = hideWebToPixsoOverlays();
|
||||
const restorePluginOverlays = hideWebToPPTOverlays();
|
||||
const restoreText = target.mode === "visual"
|
||||
? () => {}
|
||||
: hideTextForBackgroundRaster(target.rect);
|
||||
@@ -1636,7 +1636,7 @@
|
||||
restorePluginOverlays();
|
||||
}
|
||||
if (!asset?.data) continue;
|
||||
const key = `web-to-pixso-raster://${++rasterCounter}`;
|
||||
const key = `web-to-ppt-raster://${++rasterCounter}`;
|
||||
assets[key] = {
|
||||
type: "image",
|
||||
mimeType: asset.mimeType || "image/png",
|
||||
@@ -1684,7 +1684,7 @@
|
||||
children: []
|
||||
});
|
||||
} catch (error) {
|
||||
console.warn("[Web to Pixso] Raster fallback failed", error);
|
||||
console.warn("[Web to PPT] Raster fallback failed", error);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
@@ -1722,7 +1722,7 @@
|
||||
const scrollY = Math.max(0, Math.min(y, document.documentElement.scrollHeight - window.innerHeight));
|
||||
window.scrollTo(0, scrollY);
|
||||
await new Promise(resolve => setTimeout(resolve, 420));
|
||||
const restorePluginOverlays = hideWebToPixsoOverlays();
|
||||
const restorePluginOverlays = hideWebToPPTOverlays();
|
||||
const restoreFixedOverlays = options.keepFixedOverlays === true
|
||||
? () => {}
|
||||
: hideFixedTopOverlays();
|
||||
@@ -1735,7 +1735,7 @@
|
||||
restorePluginOverlays();
|
||||
}
|
||||
if (asset?.data) {
|
||||
const key = `web-to-pixso-raster://${++rasterCounter}`;
|
||||
const key = `web-to-ppt-raster://${++rasterCounter}`;
|
||||
assets[key] = {
|
||||
type: "image",
|
||||
mimeType: asset.mimeType || "image/png",
|
||||
@@ -1784,7 +1784,7 @@
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn("[Web to Pixso] Comparison fallback failed", error);
|
||||
console.warn("[Web to PPT] Comparison fallback failed", error);
|
||||
}
|
||||
y += height;
|
||||
index += 1;
|
||||
@@ -1813,7 +1813,7 @@
|
||||
});
|
||||
}
|
||||
|
||||
async function normalizeAssetForPixso(asset) {
|
||||
async function normalizeAssetForPPT(asset) {
|
||||
if (!asset?.data) return asset;
|
||||
if (/^image\/(png|jpe?g|webp)$/i.test(asset.mimeType || "")) {
|
||||
return asset;
|
||||
@@ -1836,7 +1836,7 @@
|
||||
|
||||
return await canvasToPng(canvas) || asset;
|
||||
} catch (error) {
|
||||
console.warn("[Web to Pixso] Image normalization failed", error);
|
||||
console.warn("[Web to PPT] Image normalization failed", error);
|
||||
return asset;
|
||||
}
|
||||
}
|
||||
@@ -1849,7 +1849,7 @@
|
||||
try {
|
||||
return await proxyFetchAsset(url);
|
||||
} catch (proxyError) {
|
||||
console.warn("[Web to Pixso] Proxy image fetch failed, trying direct fetch", proxyError);
|
||||
console.warn("[Web to PPT] Proxy image fetch failed, trying direct fetch", proxyError);
|
||||
return directFetchAsset(url);
|
||||
}
|
||||
}
|
||||
@@ -1857,7 +1857,7 @@
|
||||
try {
|
||||
return await directFetchAsset(url);
|
||||
} catch (directError) {
|
||||
console.warn("[Web to Pixso] Direct image fetch failed, trying extension proxy", directError);
|
||||
console.warn("[Web to PPT] Direct image fetch failed, trying extension proxy", directError);
|
||||
return proxyFetchAsset(url);
|
||||
}
|
||||
}
|
||||
@@ -1875,7 +1875,7 @@
|
||||
while (cursor < queue.length) {
|
||||
const url = queue[cursor++];
|
||||
try {
|
||||
const result = await normalizeAssetForPixso(await fetchAsset(url, options.useProxy));
|
||||
const result = await normalizeAssetForPPT(await fetchAsset(url, options.useProxy));
|
||||
assets[url] = {
|
||||
type: "image",
|
||||
mimeType: result.mimeType,
|
||||
@@ -1924,7 +1924,7 @@
|
||||
return count;
|
||||
}
|
||||
|
||||
window.__webToPixsoCapture = async function capture(options = {}) {
|
||||
window.__webToPPTCapture = async function capture(options = {}) {
|
||||
nodeCounter = 0;
|
||||
rasterCounter = 0;
|
||||
const assetUrls = new Set();
|
||||
@@ -1940,7 +1940,7 @@
|
||||
try {
|
||||
comparisonFallbacks = await collectComparisonFallbacks(options);
|
||||
} catch (error) {
|
||||
console.warn("[Web to Pixso] Comparison fallback collection skipped", error);
|
||||
console.warn("[Web to PPT] Comparison fallback collection skipped", error);
|
||||
}
|
||||
}
|
||||
const documentRect = selectionRect || getDocumentRect();
|
||||
@@ -1951,7 +1951,7 @@
|
||||
try {
|
||||
rasterFallbacks = await collectRasterFallbacks(options);
|
||||
} catch (error) {
|
||||
console.warn("[Web to Pixso] Raster fallback collection skipped", error);
|
||||
console.warn("[Web to PPT] Raster fallback collection skipped", error);
|
||||
}
|
||||
}
|
||||
if (root?.children) {
|
||||
@@ -1970,7 +1970,7 @@
|
||||
return {
|
||||
schema: CAPTURE_SCHEMA,
|
||||
schemaVersion: CAPTURE_SCHEMA_VERSION,
|
||||
format: "pixso-design-capture",
|
||||
format: "web-to-ppt-capture",
|
||||
version: CAPTURE_SCHEMA_VERSION,
|
||||
generatedAt: new Date().toISOString(),
|
||||
source: {
|
||||
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 244 B After Width: | Height: | Size: 244 B |
|
Before Width: | Height: | Size: 245 B After Width: | Height: | Size: 245 B |
|
Before Width: | Height: | Size: 245 B After Width: | Height: | Size: 245 B |
|
Before Width: | Height: | Size: 112 KiB After Width: | Height: | Size: 112 KiB |
@@ -1,4 +1,4 @@
|
||||
const SETTINGS_KEY = 'webToPixsoSettings';
|
||||
const SETTINGS_KEY = 'webToPPTSettings';
|
||||
const DEFAULT_SETTINGS = { useProxy: false, concurrency: '8', captureMode: 'mixed', captureWidth: null };
|
||||
const MIN_CAPTURE_WIDTH = 320;
|
||||
const MAX_CAPTURE_WIDTH = 3840;
|
||||
@@ -71,7 +71,7 @@ async function exportPptx() {
|
||||
// 1. 抓取 DOM
|
||||
setProgress(15, '正在采集页面...');
|
||||
const response = await chrome.runtime.sendMessage({
|
||||
type: 'PIXSO_CAPTURE_START',
|
||||
type: 'WEB_TO_PPT_CAPTURE_START',
|
||||
options: settings
|
||||
});
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
function freezeAnimations() {
|
||||
const style = document.createElement("style");
|
||||
style.id = "__web-to-pixso-freeze";
|
||||
style.id = "__web-to-ppt-freeze";
|
||||
style.textContent = `
|
||||
*, *::before, *::after {
|
||||
animation-play-state: paused !important;
|
||||
@@ -134,8 +134,8 @@
|
||||
await Promise.race([document.fonts.ready, delay(timeout)]);
|
||||
}
|
||||
|
||||
window.__webToPixsoRunCapture = async function runCapture(options = {}) {
|
||||
if (!window.__webToPixsoCapture) {
|
||||
window.__webToPPTRunCapture = async function runCapture(options = {}) {
|
||||
if (!window.__webToPPTCapture) {
|
||||
throw new Error("采集引擎未加载");
|
||||
}
|
||||
|
||||
@@ -150,7 +150,7 @@
|
||||
stabilizeCarousels();
|
||||
await delay(200);
|
||||
|
||||
return window.__webToPixsoCapture({
|
||||
return window.__webToPPTCapture({
|
||||
useProxy: Boolean(options.useProxy),
|
||||
concurrency: options.concurrency || "8",
|
||||
captureMode: options.captureMode === "editable" ? "editable" : "mixed",
|
||||
@@ -1,10 +1,10 @@
|
||||
const path = require('path');
|
||||
|
||||
module.exports = {
|
||||
entry: './web-to-pixso/convert-browser.js',
|
||||
entry: './web-to-ppt/convert-browser.js',
|
||||
output: {
|
||||
filename: 'convert-bundle.js',
|
||||
path: path.resolve(__dirname, 'web-to-pixso'),
|
||||
path: path.resolve(__dirname, 'web-to-ppt'),
|
||||
library: { type: 'module' },
|
||||
module: true
|
||||
},
|
||||
|
||||