chubes4/static-site-importer
GitHub: chubes4/static-site-importer
这是一个WordPress插件,用于将静态HTML网站自动导入并转换为WordPress区块主题。
Stars: 35 | Forks: 1
# 静态网站导入器
使用捆绑的 [Block Format Bridge](https://github.com/chubes4/block-format-bridge) 转换器,将静态网站导入到 WordPress 页面和一个配套的区块主题中。
静态网站导入器是一个 WordPress 插件。它通过 Composer 安装 [Block Format Bridge](https://github.com/chubes4/block-format-bridge),并直接从 `vendor/` 目录加载其捆绑的转换器。
## 它能做什么
- 在 **外观 -> 主题** 界面添加一个 **导入静态网站** 按钮。
- 接受粘贴的 HTML、一个公开的 HTML URL、一个直接上传的 `.html` / `.htm` 文件,或一个包含静态网站文件夹且带有 `index.html` 入口外壳的 ZIP 压缩包。
- 允许 ZIP/CLI 源站点导入包含嵌套的 `.md` / `.markdown` 内容文档;由于不支持 MDX 运行时组件,`.mdx` 文件将被跳过并提供明确诊断。
- 为本地 HTML 入口文件或一个公开的 HTML URL 提供 WP-CLI 导入器;本地源文件无需命名为 `index.html`,除非您希望自动分配首页。
- 发现所选入口文件旁可读的同级 `*.html` 文件以及源目录树下递归的 Markdown 内容文档,然后将它们作为 WordPress 页面导入。
- 通过 `bfb_convert( $html, 'html', 'blocks' )` 转换静态 HTML 片段,通过 `bfb_convert( $markdown, 'markdown', 'blocks' )` 转换 Markdown 内容。
- 将转换后的页面主体存储在导入的 WordPress 页面上,作为 `post_content`。
- 生成一个带有共享页眉/页脚模板部件、`core/post-content` 模板、用于可重用/引用组件的页面模式、`theme.json`、`style.css` 以及可选的 `assets/site.js` 的区块主题。
- 将本地 `.html` 链接重写为导入的 WordPress 页面永久链接。
- 为支持的页眉/页脚导航创建确定性的 `wp_navigation` 文章,并在生成的模板部件中引用它们。
- 保持导入的页面为原生且对编辑器可见;页面内容属于 WordPress 页面,而生成的主题拥有共享的外壳、背景装饰、样式、脚本和模板包装器。
- 当页面存在时,可选地激活生成的主题并将导入的 `index.html` 页面设置为首页。
## 要求
- WordPress 6.6 或更高版本。
- PHP 8.1 或更高版本。
- 为开发/源代码签出安装 Composer 依赖项。
- 仅当运行 JavaScript 区块验证冒烟测试时,才需要安装 Node 依赖项。
当前的 Composer 依赖项是 [`chubes4/block-format-bridge:^0.7.1`](https://github.com/chubes4/block-format-bridge)。该包包含导入器使用的带前缀的 HTML 转区块转换器。
## 管理员用法
1. 打开 **外观 -> 主题**,点击标准 **添加主题** 按钮旁边的 **导入静态网站**。
2. 粘贴单个 HTML 文档、输入一个公开的 `http` / `https` URL、上传单个 `.html` / `.htm` 文件,或上传一个包含静态网站文件夹且带有 `index.html` 入口点及可选的 `.md` / `.markdown` 内容文档的 ZIP 压缩包。
3. 可选地提供主题名称和标识符。
4. 如果希望生成的主题立即激活,请保持 **激活导入的主题** 为选中状态。
管理路径始终会覆盖具有相同标识符的现有生成主题。粘贴的 HTML、获取的 URL HTML 和直接上传的 HTML 会被复制到生成的上传工作目录中作为 `index.html`,并作为单页站点导入。ZIP 上传适用于多页静态网站或捆绑的源站点导出;它们被解压到上传工作目录,所选的 `index.html` 作为入口文件,从该解压站点目录中导入同级 HTML 文件,并将嵌套的 `.md` / `.markdown` 文件作为内容页面导入。导入器不要求原始源模型必须是单个 `index.html`;它需要选择一个 HTML 入口文件作为共享外壳/装饰,并导入它能读取的源内容文档。
URL 接收规则:
- 仅获取一个 URL;这不是爬虫,也不执行 JavaScript。
- 仅接受 `http` 和 `https` URL。
- 连接前会拒绝本地主机、环回、链路本地、私有及其他保留 IP 目标。
- 重定向目标会使用相同策略重新验证并设有上限。
- 请求使用超时时间和最大响应大小,要求类似 HTML 的内容类型,并且不转发 cookie、授权标头或嵌入的 URL 凭据。
- 导入报告包括源 URL、最终 URL、状态码、内容类型、获取时间戳、响应大小和重定向历史。
ZIP 接收规则:
- 存在时,根级别的 `index.html` 优先。
- 如果没有根级别的 `index.html`,ZIP 可能包含恰好一个嵌套的 `index.html`,例如 `site-export/index.html`。
- 如果存在多个嵌套的 `index.html` 文件且没有根 `index.html`,导入将失败,以避免猜测入口点。
- 当 PHP 的 `ZipArchive` 检查可用时,解压前会拒绝包含绝对路径、`../` 遍历段或服务器端可执行扩展名的存档条目。
- 所选源目录下的 `.md` 和 `.markdown` 文件将作为页面导入。`.mdx` 文件不会作为 Markdown 执行或解析;它们将被跳过并在 `import-report.json` 诊断中列出。
## 生成存储契约
静态存储生成器可以直接在原始 HTML 中公开产品。使用 `.product-card` 且带有可见标题和价格的产品卡将被接受为商业上下文,并且不需要单独的清单。生成器还可以在所选入口 HTML 文件旁包含一个可选的 `products.json` 文件。当存在时,静态网站导入器会验证该清单,并在 `import-report.json` 的 `commerce.products_manifest` 下记录契约结果。
最小模式:
```
{
"schema_version": 1,
"products": [
{
"name": "Signal Hoodie",
"slug": "signal-hoodie",
"regular_price": "64.00"
}
]
}
```
必填字段:
- `schema_version`:整数 `1`。
- `products`:产品对象数组。
- `products[].name`:非空字符串。
- `products[].slug`:使用字母、数字和连字符的小写 URL 标识符。
- `products[].regular_price`:小数字符串,如 `19.00`。
可选产品字段:
- `sale_price`:小数字符串。
- `description` 和 `short_description`:字符串。
- `categories`:非空类别名称字符串数组。
- `image`:相对于静态网站源的字符串路径。
- `status`:字符串产品文章状态元数据。
- `stock_status`:字符串库存状态元数据。
- `stock_quantity`:整数库存数量。
- `source_selectors`:非空 CSS 选择器字符串数组,用于源产品卡。
无效清单不会中止导入。报告会标记清单无效,并记录诸如 `$.products[0].slug` 之类的路径地址错误。如果原始 HTML 产品卡提供了产品上下文,则可选的清单不会添加顶层的 `products_manifest_invalid` 诊断。
## WooCommerce 依赖
带商业内容的导入需要 WooCommerce。当存在以下任一信号时,将检测到商业意图:
- 一个有效的 `products.json` 清单且至少包含一个产品,或
- 调用方提供的 `commerce_context` 且至少包含一个产品,或
- 从 JSON-LD `Product` 数据或可见产品卡推断出的商业上下文。
当存在商业意图但 WooCommerce 未激活时,静态网站导入器默认会硬失败导入。主题文件仍会写入,以便可以检查导入报告和生成的组件。失败以三种方式呈现:
- 导入报告上的 `commerce.dependencies.woocommerce` 块(`required`、`active`、`waived`、`sources`、`product_count`、`missing_apis`)。
- 报告 `diagnostics[]` 列表中的 `woocommerce_missing` 错误诊断。
- `quality.failure_reasons[]` 包含 `woocommerce_missing`,`quality.commerce_dependency_failures` 非零,并且无论 `--fail-on-quality` 如何设置,`quality.fail_import` 都会被设置。
传递 `--allow-missing-woocommerce`(CLI)或 `'allow_missing_woocommerce' => true`(PHP API)可在不生成产品的情况下导入主题。该豁免会记录 `woocommerce_waived` 警告诊断并清除依赖失败。非商业导入(无清单、无推断上下文)不受影响:不记录 `commerce.dependencies` 块,也不发出依赖诊断。
此门控不包含导入时的自动安装 WooCommerce(`--ensure-woocommerce`);在重试导入之前,请使用 `wp plugin install woocommerce --activate` 明确安装 WooCommerce。
## CLI 用法
```
wp static-site-importer import-theme /path/to/site/index.html \
--slug=wordpress-is-dead \
--name="WordPress Is Dead" \
--activate \
--overwrite
wp static-site-importer import-theme \
--url=https://example.com/ \
--slug=example-import \
--keep-source \
--report=report.json
wp static-site-importer import-url https://example.com/ \
--slug=example-import \
--keep-source \
--report=report.json
# 在无 WooCommerce 的主机上执行 Commerce-bearing 导入:跳过 seeding 并继续。
wp static-site-importer import-theme /path/to/store/index.html \
--slug=store-no-woo \
--allow-missing-woocommerce \
--keep-source
```
CLI 路径导入所提供入口文件所在目录中的所有可读同级 `*.html` 文件,以及源目录树下递归的 `.md` / `.markdown` 内容文档。入口文件提供主题标题、共享的源装饰、背景装饰、样式和内联脚本;每个源内容文件提供一个 WordPress 页面主体。`.mdx` 文件不受支持,并将作为跳过的诊断报告。
`index.html` 具有特殊的首页行为:它成为 `home` 页面标识符,并且当使用 `--activate` 时,它会被设置为站点的静态首页。如果导入的目录没有 `index.html`,页面仍会被导入,但导入器不会自动分配 `page_on_front`。
默认情况下,成功干净导入后,源目录会被删除,因此生成的上传工作目录不会累积。当转换质量检查报告问题时,源会被保留。当您希望为调试或开发在成功干净导入后保留原始本地源目录或获取的 URL 固定数据时,在 CLI 导入时使用 `--keep-source`。导入报告包含一个 `source_documents` 摘要,其中包含按格式的计数、跳过的 MDX 数量、未解析的本地链接以及 Markdown 解析错误诊断。
## 生成主题结构
导入会在 `wp-content/themes//` 下写入一个传统的区块主题目录:
```
/
style.css
functions.php
theme.json
assets/site.js # only when the source has inline JS
parts/header.html
parts/footer.html
templates/front-page.html
templates/index.html
templates/page.html
templates/page-.html
patterns/page-.php
```
重要行为:
- `style.css` 包含源链接的本地样式表、内联样式以及保留源按钮类在 `core/button` 链接上的兼容性规则。
- `functions.php` 排列前端样式、编辑器样式以及可选的生成 `assets/site.js`。
- `theme.json` 从明显的 `:root` CSS 自定义属性中提取保守的调色板令牌。
- 共享的装饰存储在 `parts/header.html` 中,如果源中存在,也存储在 `parts/footer.html` 中。
- 生成的模板是轻量级的区块主题包装器:页眉模板部件、导入的背景装饰、`core/post-content` 以及可选的页脚模板部件。
- 导入的 WordPress 页面文章将转换后的页面主体存储在 `post_content` 中,因此路由、标题、首页分配、编辑器可见性和主体编辑保持原生。
- 页面模式作为每个转换页面主体的可重用/引用副本生成;它们不是导入页面内容的主要存储。
## 验证
存储库同时具有 WordPress 端的固定数据覆盖和生成的组件验证。
### 完整验证工具
从存储库根目录运行完整的本地契约:
```
npm install
npm run test:validation
```
该工具将 `tests/fixtures/wordpress-is-dead/` 导入到配置的 WordPress 站点中,然后按依赖顺序运行 PHP 冒烟测试和 JavaScript 区块验证冒烟测试。
默认使用:
```
studio wp --path /Users/chubes/Studio/intelligence-chubes4
```
有用的覆盖:
```
STATIC_SITE_IMPORTER_SITE_PATH=/path/to/site npm run test:validation
STATIC_SITE_IMPORTER_WP_CLI="wp" npm run test:validation
npm run test:validation -- --skip-import /path/to/wp-content/themes/wordpress-is-dead
npm run test:validation -- --json
```
### PHP 冒烟测试
PHP 冒烟测试在 WordPress 内部运行,并通过插件运行时加载插件捆绑的 Block Format Bridge 副本:
```
wp eval-file tests/smoke-admin-import-html-entry.php
wp eval-file tests/smoke-url-import-entry.php
wp eval-file tests/smoke-editor-style-support.php
wp eval-file tests/smoke-wordpress-is-dead-fixture.php
wp eval-file tests/smoke-mixed-source-fixture.php
```
`wordpress-is-dead` 冒烟测试验证多页固定数据、生成的区块主题组件、内部链接重写、持久导航实体、源 CSS 保留、编辑器样式支持、保守的 `theme.json` 调色板提取以及存储/渲染路径间的保真度。`mixed-source-site` 冒烟测试验证类似 Astro 的源目录树,包含 `index.html`、嵌套的 Markdown 内容文档、显式的跳过 MDX 诊断、报告源计数以及生成的页面区块标记。
### PHPUnit 固定数据测试
`tests/StaticSiteImporterFixtureTest.php` 以 PHPUnit 形式镜像 `wordpress-is-dead` 固定数据契约,适用于 Homeboy WordPress 测试运行器和 CI。
```
homeboy test static-site-importer --path /path/to/static-site-importer
```
GitHub 工作流使用 `Extra-Chill/homeboy-action@v2` 的 `test` 命令,在 PHP 8.1、8.2、8.3 和 8.4 上运行。
### JavaScript 区块验证
生成的区块主题的 JavaScript 冒烟测试运行 Gutenberg 的解析器和区块验证器,针对生成的主题组件:
```
npm install
npm run test:js-block-validation -- /path/to/wp-content/themes/wordpress-is-dead
npm run test:js-block-validation -- --json /path/to/wp-content/themes/wordpress-is-dead
```
如果不传递路径,冒烟测试会使用 `STATIC_SITE_IMPORTER_THEME_DIR`,然后如果设置了 `WP_CONTENT_DIR`,则使用 `WP_CONTENT_DIR/themes/wordpress-is-dead`,最后使用存储库根目录下的本地 `wordpress-is-dead` 目录。
它验证 `parts/header.html`、`parts/footer.html`、`patterns/*.php` 和 `templates/*.html`,并报告无效区块,包括文件、嵌套区块路径、区块名称、验证原因以及按区块名称和文件分组的失败摘要。
## 发布工作流
此存储库由 Homeboy 管理:
- `homeboy.json` 声明组件 ID、WordPress 扩展、`static-site-importer.php` 中的版本目标以及 `docs/CHANGELOG.md` 的生成更新日志目标。
- 请勿手动编辑 `docs/CHANGELOG.md`。Homeboy 在发布时根据提交生成更新日志。
- 请勿手动更新插件版本。Homeboy 在发布期间更新版本目标。
- 使用约定式提交,以便发布说明和更新日志条目有意义。
## 当前边界与限制
- 导入器有意作为静态网站到区块主题的粘合剂。Block Format Bridge 负责格式转换;HTML 到区块的转换保真度属于上游 BFB/h2bc 的范畴。
- 导入器当前发现所选入口文件旁平级的 `*.html` 文件以及递归的 Markdown 内容文档;它不会爬取任意的嵌套 HTML 路由。
- 管理员导入接受粘贴的 HTML、一个公开的 URL、一个直接的 `.html` / `.htm` 文件,或带有根 `index.html` 或恰好一个嵌套 `index.html` 的 ZIP;CLI 导入接受一个直接的 HTML 入口路径或一个公开的 URL。
- MDX、Astro、Eleventy、Hugo 和其他运行时/构建编排不在范围内。请先将这些项目构建为静态 HTML,或者在 HTML 外壳旁边提供普通的 `.md` / `.markdown` 源内容。
- 链接的本地样式表和内联样式会被复制到 `style.css`;内联脚本会被复制到 `assets/site.js`。其他资源复制目前尚未成为通用爬虫。
- 导航持久性仅限于可以转换为确定性的 `wp_navigation` 实体而无需猜测的受支持的页眉/页脚形状。
- 外部现场分诊已测试了更多静态网站;提交的一方固定数据包括 `tests/fixtures/wordpress-is-dead/` 和 `tests/fixtures/mixed-source-site/`。
## 边界
此插件拥有静态网站导入工作流和生成的 WordPress 组件。[Block Format Bridge](https://github.com/chubes4/block-format-bridge) 负责内容格式转换。
导入的页面仍然是 WordPress 页面,用于路由、标题、首页分配、编辑器可见性和主体内容编辑。它们导入的页面布局作为区块标记存储在页面文章的 `post_content` 中。生成的区块主题拥有共享的页眉/页脚部件、可选的背景装饰、前端/编辑器样式、脚本以及通过 `core/post-content` 渲染页面主体的模板包装器;通用的 `templates/page.html` 仍然是导入后创建的页面的后备模板。
标签:Block主题, Composer依赖, ffuf, Gutenberg编辑器, HTML转换, Markdown支持, SEO优化, Syscall, Web开发, WordPress主题, WordPress插件, WP-CLI, 主题定制, 主题开发, 主题生成, 内容管理系统, 内容迁移, 多模态安全, 数据可视化, 数据导入, 文件完整性监控, 模板管理, 模板部分, 站点迁移, 静态站点导入, 静态网站, 页面生成, 页面管理