---
name: detail-page-self-edit-plugin
description: Attach and test the standalone self-editing JavaScript plugin for HTML layout/page deliveries when the user wants to modify a delivered HTML page themselves. Covers selectable/highlightable modules/images/text, drag/delete, Ctrl/Cmd+Z undo, inline text editing, injection, cloud sync, testing, and preview links.
version: 1.0.0
author: Hermes Agent
license: MIT
metadata:
  hermes:
    tags: [ecommerce, detail-page, html, javascript, self-editing, qa]
---

# HTML Self-Edit Plugin

Use this skill whenever a user wants to personally modify a delivered HTML page/layout in a browser or Feishu/Lark WebView, including ecommerce detail pages, landing pages, posters rendered as HTML, dashboards, long-form promotional pages, or any other HTML排版场景. Trigger phrases include “我需要自己改”, “让我自己微调”, “能不能选中拖动删除”, “文字我自己改”, “我想自己修改这个 HTML/页面”, “给我一个可编辑链接”, or “需要手机或飞书里自己调”.

## Canonical Files

The working implementation created in May 2026 is stored locally at:

```text
/Users/qianliyun/Documents/aiwork/详情页自编辑插件/detail-page-editor.js
/Users/qianliyun/Documents/aiwork/详情页自编辑插件/inject_detail_page_editor.py
/Users/qianliyun/Documents/aiwork/详情页自编辑插件/tests/editor_plugin_jsdom_test.js
/Users/qianliyun/Documents/aiwork/详情页自编辑插件/detail-page-editor-plugin.zip
```

The shared NAS copy for other robots / cross-machine access is usually:

```text
/Volumes/root_for_ai/00_共享区/通用插件/详情页自编辑插件/detail-page-editor.js
/Volumes/root_for_ai/00_共享区/通用插件/详情页自编辑插件/inject_detail_page_editor.py
/Volumes/root_for_ai/00_共享区/通用插件/详情页自编辑插件/deploy_detail_page_public.py
/Volumes/root_for_ai/00_共享区/通用插件/详情页自编辑插件/fetch_detail_page_version.py
/Volumes/root_for_ai/00_共享区/通用插件/详情页自编辑插件/detail-page-editor-plugin.zip
```

Prefer the environment variable when available because bot1 uses a user-local NAS mount:

```text
NAS_DETAIL_PAGE_PLUGIN_DIR
```

On bot1 this currently points under:

```text
/Users/bot1/Volumes/root_for_ai/00_共享区/通用插件/详情页自编辑插件/
```

As of the NAS reorganization on 2026-05-15, the local and NAS shared copies matched by SHA-256 prefix for the core plugin files. Prefer the local path for active work on this Mac; use the NAS shared path or `NAS_DETAIL_PAGE_PLUGIN_DIR` when another robot or machine needs to read/copy the plugin.

After skill cleanup, the generic ecommerce detail-page workflow skill should not store plugin script copies. Plugin scripts live in this skill and the canonical project/NAS locations only. Any old copies moved out of `ecommerce-detail-page-workflow/scripts/` are preserved under this skill's archive folder.

## Plugin Capabilities

The plugin adds a draggable floating “详情页自编辑” panel and supports:

- click editable page elements to select/highlight them: `div/section/article/figure` modules, regular product images (`img/picture/svg/video/canvas`), recognized logo images, and text elements (`h1-h6/p/span/li/a/label/...`);
- drag the selected image/text/module via `transform: translate(x, y)` for fine positioning;
- double-click text elements to enable `contenteditable` inline editing; single-click still selects text for dragging;
- selecting an element locks page scrolling and shows a lock badge; click the lock badge or press Escape to clear selection and restore scrolling;
- delete selected element using toolbar button, Delete, or Backspace;
- undo delete/drag/text edits with Ctrl+Z or Cmd+Z, and undo also clears stale scroll locks;
- drag the panel itself by its top handle; hide/collapse the panel into a small round “编” launcher icon, then click the launcher to expand it again;
- no user-facing “下载HTML” button; cloud sync is the primary save path. `exportHtmlString()` remains available internally for cloud sync/fetch workflows.

Important: the plugin is for human HTML micro-adjustment, not for final PNG export. Hide/remove it or use the non-plugin HTML before capturing formal long images, otherwise the floating toolbar can appear in screenshots.

## Inject into a Detail Page

Always inject into a **copy** unless explicitly asked to modify the original. In non-ecommerce HTML scenes, use the same copy-first rule and keep any project-specific assets next to the editable HTML.

```bash
python3 /Users/qianliyun/Documents/aiwork/详情页自编辑插件/inject_detail_page_editor.py \
  /path/to/04_页面制作/detail.html \
  --out /path/to/04_页面制作/detail_editable.html
```

The injector copies `detail-page-editor.js` into the output HTML directory and inserts:

```html
<script src="./detail-page-editor.js" data-detail-page-editor></script>
```

## Verification Checklist

Before telling the user it is ready:

1. Syntax/test:
   ```bash
   cd /tmp/detail_page_editor_plugin  # symlink if Chinese path is blocked
   NPM_CONFIG_USERCONFIG=/tmp/empty-npmrc npm test
   NPM_CONFIG_USERCONFIG=/tmp/empty-npmrc npm run check
   ```
2. Browser/manual or browser tool check:
   - page loads normally;
   - draggable floating editor panel appears;
   - no user-facing `下载HTML` button is present;
   - hiding the panel leaves a small round launcher icon, and clicking it expands the panel again;
   - dragging the panel handle changes its fixed position;
   - selecting a module (`div/section`), regular product image (`img` without logo naming), and text element highlights the exact clicked element;
   - image/text/module drag then Ctrl+Z restores position and clears scroll lock;
   - delete then Ctrl+Z restores it;
   - double-click a text element, edit text, Ctrl+Z restores text;
   - browser console has no JS errors.

If Chrome headless/CDP is flaky on the user’s macOS, do not spend time fighting it. Known noisy Chrome logs include Crashpad `settings.dat` missing, `CVDisplayLinkCreateWithCGDisplay failed`, GCM `DEPRECATED_ENDPOINT`, and GPU process exit after killing Chrome. Prefer `jsdom` unit tests plus the Hermes browser tool for visual/manual verification.

## Temporary Test Link

When the user asks for a link to test the editable HTML on the same Mac/LAN:

1. Create a simple ASCII symlink to avoid Chinese-path workdir issues:
   ```bash
   ln -sfn '/actual/project/04_页面制作' /tmp/detail_page_editable_test
   ```
2. Start a temporary local server:
   ```bash
   python3 -m http.server 8765 --bind 0.0.0.0
   ```
   Use `terminal(background=true)` so Hermes tracks and can kill it later.
3. Verify locally:
   ```bash
   python3 - <<'PY'
   import urllib.request
   for url in ['http://127.0.0.1:8765/detail_editable.html','http://127.0.0.1:8765/detail-page-editor.js']:
       with urllib.request.urlopen(url, timeout=5) as r:
           print(url, r.status)
   PY
   ```
4. Send both links:
   - same machine: `http://127.0.0.1:8765/detail_editable.html`
   - same Wi‑Fi devices: `http://<local-ip>:8765/detail_editable.html`

When done, kill the tracked background process.

## Public Cloud Link For Feishu Review Outside LAN

When the user needs the page to open from outside the local network, deploy a self-contained package to the cloud nginx static directory instead of sending a single local HTML file.

Current stable setup:

```text
Cloud host: 175.27.229.243
SSH user: ubuntu
Cloud dir: /srv/detail-pages/public/<slug>/
URL: https://wwyl.yipeng.online/detail-pages/<slug>/
Nginx config: /etc/nginx/sites-available/ecommerce-pricing
Nginx location: location /detail-pages/ { alias /srv/detail-pages/public/; }
```

Use the helper created for this workflow:

```bash
python3 /Users/qianliyun/Documents/aiwork/详情页自编辑插件/deploy_detail_page_public.py \
  /path/to/project/04_页面制作/detail_editable.html \
  --slug my-detail-page-slug
```

The helper:

- copies referenced `src`/`href`/CSS `url(...)` assets into the package;
- writes deployed entrypoint `index.html`;
- rewrites `../00_原始资料/` references to `00_原始资料/`;
- copies the latest canonical `detail-page-editor.js` into the package;
- injects `data-dpe-project-id=<slug>` and `data-dpe-api-base=/detail-page-api` onto the plugin script;
- adds a cache-busting query (`detail-page-editor.js?v=<mtime>`) so Feishu/mobile webviews do not keep stale plugin JS after redeploy;
- optimizes copied images with macOS `sips` by default for faster mobile/Feishu viewing;
- uploads with `rsync --delete` to `/srv/detail-pages/public/<slug>/`;
- prints the public URL.

Cloud version-sync service for user micro-edits:

```text
systemd: detail-page-version-api.service
script:  /opt/detail-page-version-service/version_server.py
storage: /srv/detail-page-versions/projects/<slug>/
API:     https://wwyl.yipeng.online/detail-page-api/projects/<slug>/
```

Plugin version behavior:

- On page open/refresh, the plugin loads the cloud `current_version_id` and replaces the static body with the current cloud version, so refresh shows the latest saved version automatically.
- `同步云端` saves cleaned current HTML to `POST /detail-page-api/projects/<slug>/versions` and makes it current.
- The version dropdown lists `GET /detail-page-api/projects/<slug>/versions`.
- Selecting a version loads that saved HTML and marks it current via `POST /current`.
- The cloud version service keeps only the latest 20 versions per project and prunes older HTML/metadata files automatically on save.
- On mobile/Lark webviews, the page may use `meta viewport width=1440`, so normal CSS media queries do not trigger and toolbar text becomes tiny. The plugin detects mobile/Lark user agents and applies `html.dpe-mobile-ui` oversized floating-panel/lock-badge/launcher CSS instead of relying only on `@media (max-width: 640px)`.
- The panel is a draggable floating window. Users drag it from the top handle, hide it into the small round “编” launcher, and click the launcher to expand it again.
- The user-facing `下载HTML` button is intentionally removed; cloud version sync is the supported save path.
- Multiple active projects are isolated by unique `<slug>` / `project_id`; never reuse a slug for unrelated pages.
- When the user says they have finished adjustments, fetch the current cloud version locally:

```bash
python3 /Users/qianliyun/Documents/aiwork/详情页自编辑插件/fetch_detail_page_version.py \
  --project-id <slug> \
  --out /path/to/project/04_页面制作/detail_current_from_cloud.html
```

Verification before replying:

1. HTTP checks for `index.html`, `detail-page-editor.js`, representative images, `/detail-page-api/healthz`, and `/detail-page-api/projects/<slug>/versions` return 200.
2. Browser DOM check shows all `document.images` loaded, `window.DetailPageEditor` present, toolbar present, `getConfig().projectId` equals the slug, version dropdown loads, and no console JS errors.
3. For version-sync changes, perform an end-to-end save/fetch test and ensure `fetch_detail_page_version.py` writes the current version locally.
4. Do not expose secrets; this workflow uses SSH, nginx, and a local-only version API service.

## Syncing the Tested Plugin to Designer Profile

When the user asks to “同步这个 skill 给设计 / 设计师3号” after a plugin fix, keep the coordinator responsible for file writes and do **not** restart gateways or modify unrelated profile config.

1. Copy the full self-edit skill into the designer profile if absent:
   ```text
   /Users/qianliyun/.hermes/profiles/feishu6/skills/software-development/detail-page-self-edit-plugin/
   ```
2. Sync the tested scripts from the current canonical working tree, commonly `/tmp/detail_page_editor_plugin/`, into:
   ```text
   /Users/qianliyun/.hermes/profiles/feishu6/skills/software-development/detail-page-self-edit-plugin/scripts/
   ```
   Include at least `detail-page-editor.js`, `inject_detail_page_editor.py`, `deploy_detail_page_public.py`, and `fetch_detail_page_version.py` when present. Do not re-copy plugin scripts back into the generic `ecommerce-detail-page-workflow` skill.
3. Keep plugin behavior documentation in this `detail-page-self-edit-plugin` skill only; do not patch plugin details into the generic `ecommerce-detail-page-workflow` skill.
4. Verify sync without exposing secrets:
   ```bash
   node --check /Users/qianliyun/.hermes/profiles/feishu6/skills/software-development/detail-page-self-edit-plugin/scripts/detail-page-editor.js
   python3 -m py_compile \
     /Users/qianliyun/.hermes/profiles/feishu6/skills/software-development/detail-page-self-edit-plugin/scripts/inject_detail_page_editor.py \
     /Users/qianliyun/.hermes/profiles/feishu6/skills/software-development/detail-page-self-edit-plugin/scripts/deploy_detail_page_public.py \
     /Users/qianliyun/.hermes/profiles/feishu6/skills/software-development/detail-page-self-edit-plugin/scripts/fetch_detail_page_version.py
   ```
   Optionally compare short SHA-256 prefixes and check the copied JS contains `dpe-mobile-ui` and the deploy script contains `cache_bust`.

## Non-Intrusive HTML Authoring Guidance For Agents

When improving future agent-generated detail pages for this plugin, do **not** let plugin needs reduce visual quality or constrain layout creativity. The standard is intentionally non-invasive:

- Prefer semantic/diagnostic attributes that do not affect rendering, such as `data-dpe-editable="true"`, `data-dpe-role="image|text|module|logo"`, `data-name="01_hero"`, or meaningful `alt/title` text.
- Do not add CSS rules, wrapper boxes, fixed grids, extra margins, or forced DOM structures only for the plugin.
- Do not change typography, spacing, layering, absolute positioning, or composition just to make editing easier.
- Keep the visual HTML/CSS exactly as the design requires; 页面设计优先，插件适配页面，而不是页面为了插件牺牲美感。The plugin should adapt to the page, not the page to the plugin.
- Use `data-dpe-ignore` or `data-dpe-editable="false"` only for elements that should never be selected, such as decorative masks or invisible technical layers.
- Useful optional pattern: mark modules/images/text while preserving layout, e.g. `<section class="hero" data-dpe-role="module" data-name="01_hero">`, `<img data-dpe-role="image" alt="产品主图">`, `<h2 data-dpe-role="text">卖点标题</h2>`.

## Pitfalls

- Hermes `terminal(workdir=...)` may reject Chinese paths; use `/tmp` symlinks with ASCII names.
- Existing detail pages can be very tall; visual verification may show apparent repeated sections if the screenshot capture spans unusual scroll ranges. Inspect DOM/console before assuming the page duplicated content.
- Browser-console verification must dispatch `PointerEvent` for plugin drag paths where possible; synthetic `MouseEvent` does not trigger handlers bound to `pointerdown/pointermove/pointerup`, which can falsely suggest image/text drag is broken.
- After undo replaces `document.body.innerHTML`, DOM references from before the undo are stale; re-query elements before checking restored transforms/classes.
- Do not overwrite the formal `detail.html` unless the user explicitly wants the editable version as the main file.
- If npm complains `prefix cannot be changed from project config` because of `~/.npmrc`, use a temporary clean npm config:
  ```bash
  touch /tmp/empty-npmrc
  NPM_CONFIG_USERCONFIG=/tmp/empty-npmrc npm test
  ```
