Files
photo-live/eslint.config.js
T
浅念 8f2c21d25a feat(viewer): embed carousel iframe with visibility pause
P4b Task 4:宿主 loader 以 iframe 载入的轮播页(/embed/:slotToken,裸布局)。

- src/embed/feed.ts:纯函数集——A22 旧响应裁决(dispatch seq + configVersion
  双闸:过期/回看丢弃、等值差分合并、升值全量重置)、照片队列差分(新照片
  追加队尾、缺席淘汰、thumb 签名刷新)、interval/高度夹取、轮询退避;
- src/embed/useEmbedFeed.ts:取数编排(If-None-Match → 304 零处理)、轮询
  (查询 interval 覆盖 → EMBED_POLL_INTERVAL_MS,连续 5 失败 ×5 退避,成功
  归零;404/410 静默 collapse 隐藏自身)、A23 不可见暂停(document 隐藏 +
  IntersectionObserver 滚出视口 + 本地收起;恢复立即校准)、轮播 intervalMs
  切换;__embedPollMs e2e 注入点;
- src/embed/postMessage.ts:上行 resize/collapse(referrer origin 收敛,缺失
  退 '*'——载荷无敏感数据,宿主侧 loader source+origin 双校验)、下行 expand
  (event.source === window.parent 白名单);
- EmbedPage.vue:交叉淡入淡出(仅 thumb 小图省流量)、点击 window.open 单图
  深链(noopener)、计数圆点、「照片即将上线」空态卡、×收起;lang 查询
  (auto→相册 defaultLocale)驱动嵌入词条子集;
- api client:fetchPublicEmbedSlot(304/ETag 分支,不走 apiRequest);
- e2e:宿主夹具页 public/__test__/embed-host.html(仅测试资产)+ embed.spec 7
  用例(轮换/新标签深链/收起记忆/窄屏 sm/轮询增量/换绑重置/空态/幽灵槽);
  helpers 增展示位 admin API 种子 + flushOutbox;
- vitest 18 用例(裁决矩阵/队列差分/夹取/退避/304/可见性状态机)。

配套修正:api CORS exposedHeaders ETag(跨源浏览器可读,304 语义成立);
contracts 新增浏览器安全子路径 ./constants(根出口 re-export internal-sync
的 node:crypto 会打进浏览器包);eslint ignore embed-loader 产物拷贝
(Task 3 起 viewer lint 红,先修)。

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-20 23:02:07 +08:00

59 lines
2.6 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// eslint.config.js —— 根 flat config(覆盖 packages/services/apps 全部 TS + apps 的 Vue SFC)。
// 各包 lint 脚本为 `eslint .`,在包目录执行时向上发现本文件,turbo 不会静默跳过。
// 仅 typescript-eslint recommended(无类型感知规则,无需 project service),
// 避免跨包 tsconfig 差异(contracts NodeNext / api node16)带来的配置负担。
// Vue SFC(P1b Task 5 起,apps 前端):vue-eslint Parser 解析 .vue,script 块交给
// @typescript-eslint/parser;逐项收敛 files 到 apps/**/*.vue,不影响既有纯 TS 包。
// @ts-check
const globals = require('globals');
const tseslint = require('typescript-eslint');
const pluginVue = require('eslint-plugin-vue');
module.exports = tseslint.config(
{
ignores: [
'**/node_modules/',
'**/dist/',
'**/coverage/',
'**/.turbo/',
// 生成产物不参与 lint(契约生成类型已提交入库,改动随 `pnpm gen` 审查)
'**/generated/',
// embed-loader 发布产物拷贝(viewer publicDir 携带,源在 packages/embed-loader
// ——esbuild minify 输出不适用 lint;P4b Task 3 起 viewer lint 曾因此红)
'apps/viewer/public/embed/v1/',
// Playwright 运行产物
'**/playwright-report/',
'**/test-results/',
'**/blob-report/',
// apps/admin(P1b Task 9,art-design-pro 模板)自带 eslint9 flat config
// (eslint.config.mjs + prettier/stylelint 规则集),与根配置的规则集不同;
// 计划「执行注意」注册的偏差:根配置不覆盖 admin,admin `lint` 脚本跑自己的配置。
'apps/admin/**',
],
},
...tseslint.configs.recommended,
{
files: ['apps/**/*.{ts,tsx}', 'packages/**/*.ts', 'services/**/*.ts'],
languageOptions: {
globals: { ...globals.node },
},
},
// eslint-plugin-vue flat/recommended 的每一段都显式限定到 apps/**/*.vue,
// 避免其无 files 的基础段作用于全部包。
...pluginVue.configs['flat/recommended'].map((config) => ({ ...config, files: ['apps/**/*.vue'] })),
{
files: ['apps/**/*.vue'],
languageOptions: {
globals: { ...globals.browser },
parserOptions: { parser: tseslint.parser, sourceType: 'module' },
},
rules: {
// 根组件 App.vue 是约定俗成的单词名,其余组件仍要求多词命名
'vue/multi-word-component-names': ['error', { ignores: ['App'] }],
// 模板排版类规则与 prettier 职责重叠,交给格式化工具(与官方建议一致)
'vue/max-attributes-per-line': 'off',
'vue/singleline-html-element-content-newline': 'off',
},
},
);