惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

D
DataBreaches.Net
Engineering at Meta
Engineering at Meta
AI
AI
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
C
CXSECURITY Database RSS Feed - CXSecurity.com
S
Schneier on Security
H
Hackread – Cybersecurity News, Data Breaches, AI and More
F
Fortinet All Blogs
T
Threat Research - Cisco Blogs
B
Blog
K
Kaspersky official blog
Cisco Talos Blog
Cisco Talos Blog
T
The Exploit Database - CXSecurity.com
U
Unit 42
NISL@THU
NISL@THU
D
Docker
Vercel News
Vercel News
C
Check Point Blog
Blog — PlanetScale
Blog — PlanetScale
GbyAI
GbyAI
C
CERT Recently Published Vulnerability Notes
J
Java Code Geeks
Hugging Face - Blog
Hugging Face - Blog
Latest news
Latest news
Martin Fowler
Martin Fowler
Microsoft Azure Blog
Microsoft Azure Blog
I
InfoQ
Know Your Adversary
Know Your Adversary
A
Arctic Wolf
L
LINUX DO - 热门话题
IT之家
IT之家
SecWiki News
SecWiki News
博客园 - 【当耐特】
Schneier on Security
Schneier on Security
C
Cybersecurity and Infrastructure Security Agency CISA
The Last Watchdog
The Last Watchdog
S
Secure Thoughts
P
Proofpoint News Feed
N
News and Events Feed by Topic
S
Security @ Cisco Blogs
Google DeepMind News
Google DeepMind News
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
爱范儿
爱范儿
罗磊的独立博客
C
Cyber Attacks, Cyber Crime and Cyber Security
D
Darknet – Hacking Tools, Hacker News & Cyber Security
Cloudbric
Cloudbric
O
OpenAI News
V
V2EX
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC

Halo - 强大易用的开源建站工具 | 应用市场

软件分发管理 山月记 Shortcode 初春图床 AI智能套件 文档 Cosolar 演示站防护 业余无线电 GardMap 通联网格地图 元数据字段管家 评论组件 Next 统一身份认证 Morpho Moesora 全能右键 保险箱插件 Earthquake Aurora InkNest Quiet 项目集 AI回评 AI Foundation Kaze 域名主题路由 代码增强(高亮+折叠+长图折叠) 氢·简 文章组件 Floating Particles Huohuo Weather Glass Vahlok AstraHub 星链 全局私密 业余无线电 QSL卡片管理系统 Bark 推送 微信读书(WeRead)信息展示 自定义社交分享卡片 Halorum 文章加密 KMath 轻言 Navidrome 播放器 家庭私厨 页面转换器 Sky Blog 3(macOS) 在线显示 邀请码注册 安全跳转助手 日程日历 Cartly 商城主题
Moonlit Playground
2026-07-16 · via Halo - 强大易用的开源建站工具 | 应用市场

Moonlit Playground

一个自包含的 Halo 2.25+ 代码 Playground 插件。它为 Halo 默认富文本编辑器注册可配置的多文件内容块,并通过 Halo 标准主题扩展点在文章前台按需加载运行器,不依赖指定主题。

作者:dingdangmaoup

能力

  • 通过编辑器工具箱或 /playground 插入内容块
  • React 与原生 HTML/CSS/JavaScript 模板
  • 多文件、入口文件、npm 依赖、隐藏和只读文件
  • 自动或手动运行,以及 Preview / Console 默认视图
  • CodeMirror 编辑与 CodeSandbox Sandpack 隔离预览
  • 交互增强安全上限:24 个文件、单文件 200,000 字符、总计 600,000 字符;超限内容保留为静态源码而不截断
  • 版本化的公开 HTML 协议,并只读兼容旧版结构与历史 Markdown sentinel
  • 无 Playground 的页面只执行轻量检测,不下载完整运行器

插件不创建数据库表。配置与源码随 Halo 文章内容及快照持久化。

主题接入

第三方主题无需复制插件 JavaScript 或 CSS。主题只需遵循 Halo 的标准约定:

  1. 保留由 Halo 渲染的正常 HTML <head>,不要绕过 Halo 的主题模板处理流程;TemplateHeadProcessor 会向其中注入延迟加载器。
  2. 正常输出 Halo 提供的文章 HTML,不移除 data-code-playgrounddata-playground-*<pre><code>
  3. 如果站点使用严格 CSP,允许 CodeSandbox Sandpack 实际需要的 frame-srcconnect-src

加载器先检测页面内容,只有发现受支持的 Playground 协议才动态加载运行器。插件运行器自带明暗配色和布局;主题可在 Playground 根元素上覆盖 --moonlit-playground-accent--moonlit-playground-font-sans--moonlit-playground-font-mono 等 CSS 变量做轻量品牌适配。

body [data-code-playground].moonlit-playground {
  --moonlit-playground-accent: var(--theme-accent, #3fa4ff);
  --moonlit-playground-font-sans: inherit;
}

常规客户端路由与 PJAX 的节点新增/移除,以及协议根或版本属性变化,会由 DOM 观察器自动识别。若主题通过 morph/复用节点的方式原地改写整个 Playground,可在批次完成后触发公开的强制刷新事件:

document.dispatchEvent(new Event("moonlit:playground:refresh"));

强制刷新会销毁旧前台实例,并以此时文章 DOM 中的属性和源码重新解析;因此只应在主题完成内容替换后触发,访客尚未运行或保存到文章的临时编辑会被丢弃。

这些样式覆盖是可选项,不应在主题中重新实现 Playground 运行时,也无需为插件增加主题配置项。

如果页面绕过 Halo 主题渲染、JavaScript 被禁用、运行器加载失败,或文章声明了插件尚不支持的新协议版本,原始 <pre><code> 仍会保留为可读静态内容。data-hidden-file 只是交互界面的显示选项,并不是保密机制。

公开内容协议

新内容使用 data-playground-version="1"。根属性使用 data-playground-* 命名空间,文件保留为直系 <pre> 子节点;Halo 语法高亮生成的单层 <shiki-code> 包装也受支持。

<div
  data-code-playground
  data-playground-version="1"
  data-playground-template="vanilla"
  data-playground-entry="/index.html"
  data-playground-run="manual"
  data-playground-view="preview"
  data-playground-title="多文件示例"
  data-playground-show-files="true"
  data-playground-show-preview="true"
  data-playground-show-console="false"
  data-playground-dependencies="{}"
>
  <pre
    data-playground-file="/index.html"
    data-language="html"
    data-label="index.html"
    data-active-file
  ><code class="language-html">&lt;main id="app"&gt;&lt;/main&gt;
&lt;script type="module" src="/index.js"&gt;&lt;/script&gt;</code></pre>
  <pre
    data-playground-file="/index.js"
    data-language="javascript"
    data-label="index.js"
  ><code class="language-javascript">document.querySelector("#app").textContent = "Hello";</code></pre>
</div>

根属性:

属性
data-playground-version 当前为 1;缺失时按旧版无版本协议读取
data-playground-template reactvanilla
data-playground-entry 入口文件的绝对项目路径
data-playground-run automanual
data-playground-view previewconsole
data-playground-title 无障碍名称和界面标题
data-playground-show-files 是否显示文件标签栏
data-playground-show-preview 是否提供 Preview 视图
data-playground-show-console 是否提供 Console 视图
data-playground-dependencies npm 依赖名到版本的 JSON 对象

文件属性:

属性 说明
data-playground-file 唯一文件路径,必需
data-language 语法语言标识
data-label 可选的显示名称
data-active-file 标记初始打开的文件
data-hidden-file="true" 不显示在文件标签栏,但仍会发送给运行环境
data-readonly="true" 在 Playground 中只读

协议版本不是 1 时,当前运行器不会猜测或降级解析,前台保留静态 HTML。默认编辑器也会将其作为不可编辑的 opaque 内容块保留(同时移除可执行标签和事件属性),避免旧插件在保存时改写未来协议。

兼容旧内容

插件继续读取以下历史格式:

  • 缺少 data-playground-version 的结构化内容
  • data-templatedata-entrydata-rundata-view 等旧根属性
  • 原有代码块第一条非空行中的 @moonlit-playground sentinel

sentinel 只用于读取历史文章,不是公开创作协议。新内容必须使用编辑器内容块或结构化 v1 HTML;插件不会识别通用的 @code-playground 文本,避免文档示例被意外变成可执行内容。历史格式示例:

// @moonlit-playground {"template":"react","view":"preview","run":"auto","title":"React 示例"}
export default function App() {
  return <main>Hello Playground</main>;
}

历史 sentinel 必须位于代码块第一条非空行。结构化 v1 是完整多文件能力的唯一标准交换格式。

编辑器新建内容块默认为 manual;只有作者显式改为 auto,或访客点击 Run、刷新、重置或导出后,才会创建 CodeSandbox 运行客户端。

构建与安装

需要 JDK 21。Gradle 会自动准备 Node.js 22.23.1 与 pnpm 11.12.0,用于构建 Halo Console 扩展和独立的前台懒加载资源。

./gradlew clean build
halo plugin install --file build/libs/moonlit-playground-0.0.1.jar --yes
halo plugin enable moonlit-playground --force

升级已安装插件:

halo plugin upgrade moonlit-playground \
  --file build/libs/moonlit-playground-0.0.1.jar \
  --yes

运行验证:

./gradlew test
./gradlew build

隐私与安全

Playground 使用 CodeSandbox Sandpack 的跨域运行服务。运行和导出示例时,源码、依赖信息及运行请求会发送给 CodeSandbox;请先确认其服务条款、隐私政策和所在地区要求。

不要在文章源码、隐藏文件、只读文件或依赖配置中放入密码、访问令牌、个人信息或私有代码。跨域 iframe 能降低示例代码直接访问 Halo 页面上下文的风险,但不能把第三方运行服务变成可信的秘密存储。

授权

MIT © 2026 dingdangmaoup。第三方依赖授权见 THIRD_PARTY_NOTICES.md