mcpField
S
sharepoint-html

sharepoint-html

github.com/sharepoint文档处理1359 次安装13 周前更新
代码仓库

关于 sharepoint-html

sharepoint-html 是用于制作并发布自包含 HTML 文件的技能,使其可在 SharePoint 的 OneUp 查看器中呈现。内容涵盖查看器限制、实时 SharePoint 数据,以及通过 Microsoft Graph 或 SharePoint Vroom API 发布。

主要功能

  1. 01编写适用于 OneUp 沙盒的 HTML
  2. 02通过 LiveData 清单读取 SharePoint 内容
  3. 03使用内置仪表板模板
  4. 04预检 HTML 并检查目标文件冲突
  5. 05通过 Microsoft Graph 或 SharePoint Vroom 发布

适用场景

  1. 01发布自包含的状态仪表板
  2. 02展示实时 SharePoint 文件或列表数据
  3. 03从 OneDrive 或 SharePoint 打开呈现后的 HTML 页面

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/sharepoint/sharepoint-html --skill sharepoint-html

安装后在 Claude Code 中输入/sharepoint-html确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

LICENSE
.gitignore
README.md
install.sh
assets/templates/
README.md
dashboard.html
livedata-list-dashboard.html
livedata-dashboard.html
references/
contract.md
api.md
live-data.md
scripts/
preflight.sh
publish-to-folder.sh
publish-graph.sh

详细介绍

向 SharePoint 发布 HTML(OneUp HTML 查看器)

SharePoint 已支持托管 HTML:将 .html 文件保存到 OneDrive 或 SharePoint 并打开,即可在 OneUp HTML 查看器中呈现——该查看器使用受严格 Content-Security-Policy 约束的沙盒 <iframe>。无需配置单独的托管服务;发布只需以已登录用户的身份将 .html 文件写入其云盘,然后打开该文件的 webUrl。

本技能教会 Agent 两件事:

  1. 编写能正常呈现的 HTML——OneUp 的 CSP 和沙盒会静默失败,因此不符合要求的 HTML 会显示为空白或部分损坏,且不会报错。遵循以下规范即可正常运行。
  2. 发布 HTML——使用 Microsoft Graph(首选)或 SharePoint Vroom API(_api/v2.0,适用于已持有 SharePoint 令牌的 Agent)上传文件,然后将返回的 webUrl 提供给用户。

规范的、始终保持最新的编写要求位于租户的发现端点:https://<your-sharepoint-host>/_html(人类可读页面)、/_html/llms.txt(Agent 文本)和 /_html/help.json(结构化信息)。如有疑问,请获取 /_html/llms.txt——它由当前的查看器源代码生成。


⚠️ 发布前须知:你正在写入用户的真实云盘

使用此技能发布会以用户身份进行身份验证,并在其自己的 OneDrive / SharePoint 中创建或覆盖文件。这不是临时沙盒。

  • 文件不会自动公开。 文件对用户保持私有,除非用户明确共享。但它确实是其云盘中的真实文档。
  • 每次上传和每次覆盖之前,都必须征得用户的明确确认。 告知用户确切的目标位置(云盘、文件夹、文件名),以及此操作是创建新文件还是替换现有文件,然后等待用户确认。请参阅写入前确认。
  • 覆盖操作具有破坏性。 对现有路径执行 PUT .../content 会替换文件内容。请确认路径,并确认用户确实希望覆盖。

编写规范(让 HTML 在 OneUp 中正常渲染)

你的 HTML 会在 <iframe sandbox="allow-scripts"> 中运行,并受严格的 CSP 限制;违反规则时不会显示错误。请遵守以下规则,否则页面会空白或只显示部分内容,且不会报错。

应用于你的 HTML 的内容安全策略:

default-src 'none';
script-src 'unsafe-inline' 'unsafe-eval';
style-src 'unsafe-inline';
img-src data: blob:;
font-src data: blob:;
connect-src 'none';
worker-src 'none';
object-src 'none';
base-uri 'none';
form-action 'none';

外层 iframe 还会额外应用 frame-src 'none'。

不可妥协的规则:

  1. 禁止使用外部资源。 不得使用 <script src>、<link href>、<img src=https://…>、 @import、url(https://…)、远程字体或 CDN。所有内容均须内嵌,或使用 data: / blob: URI。
  2. 所有脚本都必须内嵌在 <script> 块中。不得导入模块,不得使用 import(),也不得使用 <script src>。
  3. 所有样式都必须内嵌在 <style> 或 style="…" 中。不得使用 <link rel="stylesheet">。
  4. 运行时禁止联网——fetch、XMLHttpRequest、WebSocket、sendBeacon、 EventSource 均会被阻止(connect-src 'none')。如需在查看时读取 SharePoint 文件数据,请使用 LiveData 清单(见下文)——这是唯一获准的数据路径。
  5. 禁止使用存储机制——localStorage、sessionStorage、indexedDB、 document.cookie(不透明源沙箱)。如需跨重新加载保留状态,请直接设置 location.hash (例如 location.hash = '#slide=3')。不得使用 history.pushState/ replaceState——沙箱化文档的基础 URL 继承自包装器的 blob: 源,因此任何 url 参数(即使只是 #hash)都会抛出 SecurityError。
  6. 禁止顶层导航、弹出窗口、表单提交、工作线程或插件。 alert / confirm / prompt 均为空操作。
  7. 内嵌的 on*= 处理程序可以正常工作(它们会被改写为带 nonce 的脚本),但如果将不可信数据模板化到其中,就会造成 XSS 漏洞——处理计算得出或来自用户/获取的数据时,优先使用 addEventListener。
  8. 保存为 UTF-8(以下文件创建 API 会以 UTF-8 写入;如果手动编写且非 ASCII 内容显示异常,请添加 BOM)。

链接:<a href> 仅会打开同一租户的 SharePoint 主机或外部允许列表中的地址;javascript: / vbscript: / data: href 会被拒绝。

实时 SharePoint 数据(唯一的运行时数据源)

运行时 fetch 会被阻止。要显示实时 SharePoint 文件内容,请嵌入 LiveData 清单——主机使用查看者的凭据在服务器端预取每个项目,并在脚本运行前注入结果:

<script type="application/json" class="ka-livedata-manifest">
[{ "spItemUrl": "https://contoso.sharepoint.com/_api/v2.0/drives/{driveId}/items/{itemId}", "fileName": "data.csv" }]
</script>

在脚本运行前,主机会设置 window.__LD_RESULTS__,并以准确的 spItemUrl 为键。每个值的格式为 { format, content, error?, metadata }——读取 content(字符串),并检查 error。

需要特别注意但至关重要的事项:

  • 每个项目都必须包含 fileName(含扩展名)——主机会据此选择 csv / xlsx-sheets / text 解码器。若缺少该字段,.xlsx 文件将无法读取,.csv 文件也不会按 csv 解析。
  • spItemUrl 必须包含 /drives/{driveId}/items/{itemId}(来源站点会被忽略,并根据查看者会话重新构建)。解析文件以获取这些 ID:GET /shares/{u!token}/driveItem → parentReference.driveId + id。
  • 刷新会重新加载你的 iframe,并提供最新数据——postMessage({type:'ka-html-viewer-refresh'}, '*')(防抖 5 秒)。没有可供监听的传入“已更新”事件。
  • 将内容视为不可信数据——使用 textContent 构建 DOM,绝不要将其写入 innerHTML。
  • 限制:每页 32 个项目(超出限制时会丢弃所有结果),每个项目 50 MB;支持的格式:text、csv、xlsx-sheets、rows。

SharePoint 列表——清单项目也可以指向列表(kind:"list",包含 webUrl + listId,并可选填 select 指定内部列名称)。主机会在服务器端渲染该列表,并以 format:"rows" 注入——content 是 JSON 字符串 { headers, rows }(已扁平化;最多 100,000 行,截断时会设置非阻塞的 warning)。请在创作时通过 GET {webUrl}/_api/web/lists/getbytitle('{Name}')/fields?$select=InternalName,Title,TypeAsString(或 Graph /sites/{site-id}/lists/{list-id}/columns)解析 listId + 内部列名称。内部名称可能与显示标题不同(例如,“City” → Ciity)。参见 references/live-data.md。

完整协议 + 完整示例仪表板: references/live-data.md(也镜像在租户的 /_html/llms.txt 中)。仅含表格的入门模板: assets/templates/livedata-dashboard.html。


还没有 HTML?从模板开始

如果用户想发布内容但还没有 HTML,请使用 assets/templates/ 中现成且符合 CSP 的模板,而不是手动编写:

模板适用场景
dashboard.html…构建独立的指标/状态仪表板(无外部数据)。
livedata-dashboard.html…通过 LiveData 清单呈现实时 SharePoint 文件数据(csv/xlsx/text)。
livedata-list-dashboard.html…呈现实时 SharePoint 列表(kind:"list" → format:"rows")——KPI、类别图表、表格。

读取选定的文件,将其中的 `` 占位内容替换为用户的实际内容,根据上述约定进行验证,然后发布。


第 1 步 — 编写(或填充)符合规范的 HTML

生成一个符合约定的独立 .html 文档。所有内容均内嵌;不引用外部内容;如需 SharePoint 数据,则添加 LiveData 清单。

步骤 2 — 获取访问令牌

发布时以用户身份进行身份验证。你需要一个 OAuth 2.0 bearer token(Azure AD)。

首选 — Microsoft Graph:

  • 范围(委托): Files.ReadWrite(写入用户自己的云端硬盘)。若要写入用户有权访问的其他库/站点,请使用 Files.ReadWrite.All 或 Sites.ReadWrite.All。
  • **获取方式:**通过 MSAL 使用用户身份获取(交互式、设备代码或现有的登录会话)。不要编造或硬编码令牌。如果你还没有 Graph 令牌,请运行 MSAL 流程 — 参见 references/api.md。

替代方案 — SharePoint Vroom(当 Agent 已通过 SharePoint OAuth 令牌完成接入时使用,例如加载项 / SPFx / on-behalf-of 流程):令牌的受众为 SharePoint 资源(https://{tenant}.sharepoint.com 或 -my.sharepoint.com),范围为 AllSites.Write / MyFiles.Write。使用相同的 driveItem 调用,但基 URL 不同。

完整的令牌流程、范围和许可说明见 references/api.md。

步骤 3 — 确认,然后发布

写入前先确认

首先对 HTML 运行 预检 — 运行 scripts/preflight.sh <file>;该脚本会搜索被禁止的 API,并检查 LiveData 清单项(文件项需要 spItemUrl + fileName;kind:"list" 项需要 spItemUrl + webUrl + listId)(最常见的问题是“无错误但页面空白”)。然后列出目标文件夹(GET …/children),检查是否有名称冲突,以便准确告知用户这是新建还是覆盖。

调用上传接口前,明确告知用户具体操作,并征得同意:

About to publish to SharePoint/OneDrive:
  Account:   [email protected]
  Location:  OneDrive  ›  Documents/Agent HTML/
  File:      sales-dashboard.html
  Action:    Create new file            (or: Overwrite existing file — REPLACES its contents)
  Renders at: <webUrl>?web=1   (?web=1 opens the OneUp viewer; the bare webUrl downloads)
Proceed?

只有在用户明确同意后才能继续。覆盖时,必须明确说明此操作具有破坏性。

通过 Microsoft Graph 发布(首选)

简单上传(文件 ≤ 4 MB — 对内嵌 HTML 来说绰绰有余)。按路径创建新文件:

PUT https://graph.microsoft.com/v1.0/me/drive/root:/Agent HTML/<name>.html:/content
Authorization: Bearer <token>
Content-Type: text/html

<!DOCTYPE html> … your document …

响应 201 Created(新建)/ 200 OK(替换)→ 一个 driveItem。读取 webUrl,然后向用户提供 <webUrl>?web=1 — ?web=1 会在 OneUp 查看器中打开文件;单独的 webUrl 则会下载 .html 文件:

{
  "id": "01ABC…",
  "name": "sales-dashboard.html",
  "size": 84213,
  "webUrl": "https://contoso-my.sharepoint.com/personal/user_contoso_com/Documents/Agent%20HTML/sales-dashboard.html",
  "file": { "mimeType": "text/html" }
}

对于 > 4 MB 的文件,请使用上传会话(createUploadSession)— 参见 references/api.md。

通过 SharePoint Vroom 发布(替代方案)

使用相同的请求格式、SharePoint 基 URL 和面向 SharePoint 的令牌。当你已有 SharePoint OAuth 令牌(SPFx / 加载项 / on-behalf-of)或想直接指定特定 SharePoint 主机或站点时,请使用此方式。(graph.microsoft.com 已会将个人云端硬盘上传请求路由到调用者所在的场区 — 包括 *.sharepoint-df.com 等内部测试环 — 因此通常只用 Graph 就足够了。)

PUT https://{tenant}-my.sharepoint.com/_api/v2.0/me/drive/root:/Agent HTML/<name>.html:/content
Authorization: Bearer <sharepoint-token>
Content-Type: text/html

<!DOCTYPE html> … your document …

返回相同的 driveItem(读取 webUrl)。完整详情(包括站点云端硬盘路径 /_api/v2.0/drives/{driveId}/items/{itemId}/content)见 references/api.md。

发布到 SharePoint 站点库(而不是 OneDrive)

对站点云端硬盘进行相同调用。使用 Graph(范围 Sites.ReadWrite.All):

PUT https://graph.microsoft.com/v1.0/sites/{site-id}/drive/root:/Agent HTML/<name>.html:/content

或使用 Vroom 针对站点主机调用:

PUT {siteUrl}/_api/v2.0/drive/root:/Agent HTML/<name>.html:/content

站点云端硬盘的根目录是其默认文档库(“Shared Documents”),因此路径应相对于根目录。使用 GET /sites/{host}:/sites/{path}(或 /teams/{path})解析 {site-id}。

通过文件夹 URL 发布 — 最少调用次数(Shares API)

如果你只有目标文件夹的 URL,可以跳过解析 drive/site ID 的步骤——将 URL 编码为共享令牌,然后直接上传到该文件夹:

  1. 编码:u! + 文件夹 URL 的无填充 base64url(base64,去掉 =,将 / 替换为 _,将 + 替换为 -)。
  2. GET /shares/{u!token}/driveItem → 获取文件夹的 id 和 parentReference.driveId(一次调用)。
  3. PUT /drives/{driveId}/items/{folderId}:/<name>.html:/content → 上传。

总共调用 2 次,适用于任何 OneDrive、站点或库。详情请见 references/api.md;现成脚本:scripts/publish-to-folder.sh。

第 4 步 — 打开文件

向用户提供 <webUrl>?web=1(在响应中的 webUrl 后附加 ?web=1)。?web=1 会在 OneUp 查看器中渲染 HTML;直接使用 webUrl 则会下载 .html 文件。 webUrl 在更新后保持不变,因此修改文件后链接仍然有效。


更新 / 修改你创建的资源

要更改已发布的文件,请覆盖它——使用相同路径(或项目 ID)和相同调用:

PUT https://graph.microsoft.com/v1.0/me/drive/items/{item-id}/content
Authorization: Bearer <token>
Content-Type: text/html

<!DOCTYPE html> … updated document …

也可以按路径操作:PUT /me/drive/root:/Agent HTML/<name>.html:/content。

覆盖会替换文件内容——请先向用户确认(展示目标文件,并说明这会替换现有文件)。webUrl 保持不变。Vroom 的行为相同,只需使用其基础 URL。若要重命名 / 移动文件,而非替换内容,请使用 PATCH …/items/{item-id} (请参见 references/api.md)。


错误代码

代码含义操作
401未授权令牌缺失 / 过期,或受众错误(Graph 与 SharePoint 不匹配)。使用正确的 scope 重新获取令牌。
403禁止访问令牌缺少写入 scope(Files.ReadWrite),或用户无权写入该位置。
404未找到drive / 项目 / 路径错误,或父文件夹不存在(请先创建)。
413负载过大简单上传的文件超过 4 MB——请使用上传会话。
423已锁定项目已签出 / 锁定。
507存储空间不足用户的 drive 已满。

打开后页面空白 / 仅部分渲染 → 违反了创作约定(通常是使用了外部资源或运行时 fetch)。请重新检查约定。


参考资料

  • references/api.md — 完整的 Graph + Vroom 端点参考: 身份验证与 scope、令牌获取、请求 / 响应架构、上传会话、元数据更新,以及 driveItem 结构。
  • references/contract.md — 完整的 OneUp 创作约定。
  • assets/templates/ — 可直接使用且符合 CSP 的模板。
  • 在线文档(权威版本,因租户而异):https://<your-sharepoint-host>/_html, /_html/llms.txt、/_html/help.json。

评论

支持 Markdown