@lark-apaas/coding-steering 0.1.18-dev.4e64c13 → 0.1.18-dev.61b3ece

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (24) hide show
  1. package/package.json +1 -1
  2. package/steering/design-html/skills/charts/SKILL.md +4 -0
  3. package/steering/design-html/skills/pptx-style-extract/SKILL.md +11 -8
  4. package/steering/design-html/skills/pptx-style-extract/scripts/check_v2.py +33 -3
  5. package/steering/design-html/skills/pptx-style-extract/scripts/draft.py +526 -110
  6. package/steering/design-html/skills/pptx-style-extract/scripts/extract.py +226 -6
  7. package/steering/design-html/skills/pptx-style-extract/scripts/ooxml.py +18 -1
  8. package/steering/design-html/skills/pptx-style-extract/scripts/package.py +167 -28
  9. package/steering/design-html/skills/pptx-style-extract/scripts/parts.py +3 -0
  10. package/steering/design-html/skills/pptx-style-extract/scripts/query.py +3 -8
  11. package/steering/design-html/skills/pptx-style-extract/scripts/test_background_composite.py +57 -0
  12. package/steering/design-html/skills/pptx-style-extract/scripts/test_color_contract.py +60 -0
  13. package/steering/design-html/skills/pptx-style-extract/scripts/test_design_consumer_contract.py +63 -0
  14. package/steering/design-html/skills/pptx-style-extract/scripts/test_flow_layout_contract.py +468 -0
  15. package/steering/design-html/skills/pptx-style-extract/scripts/test_layout_css.py +127 -0
  16. package/steering/design-html/skills/pptx-style-extract/scripts/test_rounded_contract.py +112 -0
  17. package/steering/design-html/skills/pptx-style-extract/scripts/test_text_role_contract.py +208 -0
  18. package/steering/design-html/skills/pptx-style-extract/v2-format-spec.md +14 -7
  19. package/steering/design-html/skills/slide-deck/SKILL.md +15 -20
  20. package/steering/design-html/skills/slide-deck/scripts/check_local_references.py +179 -0
  21. package/steering/nestjs-react-fullstack/skills/plugin-guide/SKILL.md +5 -3
  22. package/steering/nestjs-react-fullstack/skills_local/plugin-guide/SKILL.md +4 -0
  23. package/steering/vite-react/skills/plugin-guide/SKILL.md +3 -1
  24. package/steering/vite-react/skills/react-three-fiber/SKILL.md +4 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lark-apaas/coding-steering",
3
- "version": "0.1.18-dev.4e64c13",
3
+ "version": "0.1.18-dev.61b3ece",
4
4
  "description": "Stack-specific steering content for miaoda-coding templates",
5
5
  "type": "module",
6
6
  "files": [
@@ -7,6 +7,8 @@ metadata:
7
7
  en-US: Charts
8
8
  ---
9
9
 
10
+ {% raw %}
11
+
10
12
  # 图表
11
13
 
12
14
  你是用 ECharts 呈现信息的数据叙事设计者。你的图表会出现在创意 HTML 产物中,例如仪表盘、幻灯片、设计探索。ECharts 是你的媒介,不是目标;你的工作是让数据故事一眼可读,而不是堆配置项。一个图表只表达一个主要信息。
@@ -202,3 +204,5 @@ Object.assign(window, { EChart });
202
204
  | Line 连接未按时间排序的点 | Bar 或 Scatter |
203
205
  | markPoint 重复(统计极值 = 业务事件) | 仅保留业务注释 |
204
206
  | 用 Stacked Bar 表示 Gantt | 使用带 `renderItem` 的 `custom` series |
207
+
208
+ {% endraw %}
@@ -9,7 +9,9 @@ metadata:
9
9
 
10
10
  # pptx-style-extract(PPT 模板风格抽取)
11
11
 
12
- 一份 PPTX → 一个风格包:`manifest.json`(机器清单)+ `design.md`(消费入口)+ `layouts.md` + `assets/` + `ref/`。**机械动作全部由脚本承担**(解析、普查、聚类、草案、落盘、门禁),你只做机器做不了的三件事:**认图、命名、写气质**。
12
+ 一份 PPTX → 一个风格包:`manifest.json`(机器清单)+ `design.md`(消费入口)+ `layouts.md` + `assets/` + `ref/`。
13
+
14
+ 三步依次跑完才有这个包:**抽取**(脚本出草案)→ **判断**(你改草案里的 TODO——认图、命名、写气质)→ **打包**(脚本产出 `design.md` + `layouts.md`)。deck 的版式坐标、资产路径、logo 出现在哪些页型,全部从包里读。
13
15
 
14
16
  脚本路径相对本 skill 根目录;不做环境检测,依赖缺失脚本自己降级并在输出里报。
15
17
 
@@ -71,26 +73,27 @@ mkdir -p tmp/pptx-style-extract/<unique-id> && PYTHONDONTWRITEBYTECODE=1 python3
71
73
 
72
74
  1. 读 `<outdir>/l-out/BRIEF.md` —— 事实、草案依据、待判断清单一页看完。清单是实时扫出来的,**只列真正还有 TODO 的文件**,没列到的那份不用打开。
73
75
  2. 看 `<outdir>/l-out/contact-sheet.png` 与 `<outdir>/l-out/layout-sheet.png` —— 候选图和代表页型都已拼好,对应 BRIEF 的表。
74
- 3. 用 `multi_edit` 一次批量改掉四件草案里的每一处 `TODO`:风格命名与气质、页型角色、以及下面第 4 条的禁放区。草案就在项目内相对路径下,直接编辑,**不要写脚本去改 YAML**。看过重建图后真有这套模板特有的硬规则(例如主色只许用在哪类元素)再往 `## Hard Rules` 补一条;没有就不补,别为凑数编规则。
76
+ 3. 用 `multi_edit` 一次批量改掉四件草案里的每一处 `TODO`:风格命名与气质、页型角色、`text_roles` 里的文本角色、`layout_modes` 里的布局模式、以及下面第 4 条的禁放区。文本角色只按模板中实际存在的文字判断为 `title|subtitle|header|footer|body`;判断不清就填 `body`,不补模板里没有的标题、页眉或页脚。草案就在项目内相对路径下,直接编辑,**不要写脚本去改 YAML**。看过重建图后真有这套模板特有的硬规则(例如主色只许用在哪类元素)再往 `## Hard Rules` 补一条;没有就不补,别为凑数编规则。
75
77
  4. `layouts.yaml` 顶部 `bg_rules:` 按**背景资产**分组(不是按页型),逐张背景填 `text_safe` / `avoid` / `pairing_rule`:看图标清视觉主体、强光斑、深色透明区,打包时自动并入用该背景的所有页型。标题、正文、关键数字、图表、卡片、时间线及其容器的外接矩形都不得压住背景主体,透明容器也不能跨进禁放区。
76
78
 
77
79
  `layouts.yaml` 的 `layouts:` 段是普查数值——页型、坐标、字号、色值、对齐、以及各页型自带的 `role: logo` 资产槽全部直读,**一个字都不要动**。模板自己给版式起过名时 `names:` 已经填好,读一遍确认表意即可。
78
80
 
79
81
  判断口径:
80
82
 
81
- - **满屏图默认属背景族**——整幅替换底图的艺术图/摄影图就是背景(首页那张记 `role: cover`);「内容图不进包」只指内容区里的图表、截图、配图。
82
- - **logo 宁缺勿错**——看图确认有品牌文字或标志图形才留;拿不准就把该条从 `manifest.yaml` 删掉,在 `gaps` 写一句,候选图留在 `media-out/`。
83
+ - **图片按用途三分**——一张图先问它服务于什么:整幅替换底图的艺术图/摄影图属**背景族**(首页那张记 `role: cover`);服务于具体内容的图表、截图、产品说明图是**内容图,不进包**;剩下既不是 logo、也不服务于内容的(纹理、装饰插画、色块、几何点缀)都是**装饰图,标 `texture` 进 assets**。满屏图默认走背景,不必逐张看图确认。
84
+ - **logo 特指这份 deck 自己的品牌标志**——看图确认是本 PPT 的品牌文字或标志图形才留 `logo`;一页若是 logo 墙(客户/合作方 logo 罗列),那些是内容图、不当风格 logo。宁缺勿错:拿不准就把该条从 `manifest.yaml` 删掉,在 `gaps` 写一句,候选图留在 `media-out/`。
83
85
  - **anchors 是事实不是结论**——草案里每条只报测到的数(覆盖率、计数、占比),没有「这套风格的特征是 X」这种断言。这一段在 design.md 里读起来像总纲,消费端会照它建全局样式,所以脚本不敢替你下结论:一条 1/8 覆盖率的元素被描述成「跨页不动」,消费端就会每页都摆它。看过重建图后,把真正是这套模板特征的那几条改写成设计要点,不是特征的直接删掉。
84
86
  - **数值只改名不改值**——草案里的坐标/色值/字号来自普查;确需推导值(CJK 行高转译、投影尺度上抬)在 manifest 写 `derived:` 声明理由,机检认声明。
85
87
  - **页型命名**——模板自带版式名时草案已填好;只有靠样张聚类的模板(`names` 里还是 TODO)才需要按 BRIEF 的 slot 原文起中文名。
86
88
  - **页型角色**——`roles:` 段有 TODO 时,看 `layout-sheet.png` 上对应的代表页定 `cover|section|content|quote|closing|blank|custom`。草案只把客观事实摆在注释里(代表页页码、页数、文字块数、字号序列、图片数、有无满屏底图),不替你下结论:字号多大算章节页、文字块多少算密集页,每套模板的答案都不一样。
87
- - **资产位置不要写成全局规则**——同一个 logo 常按页型换位换尺寸(封面一个位置一个尺寸、内容页另一个)。位置只存在于 `layouts.md` 各页型的 `slots`,正文里只说「按该页型的 slot 摆放,没有就不放」。
89
+ - **文本角色**——`text_roles:` 段有 TODO 时,结合重建图和该行给出的来源、占位符、样例文字、box、字号与 CSS 判断标题、副标题、页眉、页脚或正文。这里仅改变已有文本槽的语义;所有文本槽、图片、容器与装饰仍由 `layouts:` 保留。标题、页眉或页脚已在背景中可见时,在 Hard Rules 写明对应页型只渲染已有 slots,不重复叠加文字。
90
+ - **资产位置不要写成全局规则**——同一个 logo 常按页型换位换尺寸(封面一个位置一个尺寸、内容页另一个)。位置只存在于 `layouts.md` 各页型的 `slots`,正文里只说「按该页型的 slot 摆放,没有就不放」。一张图只在 `manifest` 标了 `kind` 还不够:生成侧只摆 `slots` 里带 `asset:` 引用它的那些,没有任何页型引用它就不会被放出来。要它出现,就在对应页型的 `slots` 加一条 `asset:` 引用。
88
91
  - **背景和版式要配对**——真实背景不是纯色底。看 `contact-sheet.png` 判断每张背景的视觉主体/禁放区,看 `layout-sheet.png` 判断文字与卡片落点;`background` 草案已按版式直读填好,你只需在 `bg_rules` 里逐张背景补 `text_safe`、`avoid`、`pairing_rule`,避免消费 Agent 把文字、图表、卡片、时间线、标题容器、正文容器或宽透明容器的外接矩形压到金字塔、人物、产品图、强光斑或深色区域上。
89
92
  - 双主题只认 BRIEF 的 `themes`;单主题包不写 `theme` 字段。
90
93
 
91
94
  判断单里的**结构事实**(每个页型上方的注释)是判「这页该用绝对坐标还是流式」的依据:栅格几列、垂直间距序列(突变处即区带边界)、样张里每个文字槽的实际字数、命中哪个容器样式配方。文件头另有容器样式配方清单,带出现次数与跨页数——跨页多的是共性风格,只在一处出现的多半不是。
92
95
 
93
- **页型给 `flow` 还是 `slots`,由你定**:内容长度会变的页(列表、表格、卡片组)用 `flow`,区带依次排、高度由内容决定,上面变高下面自动被推下去;构图固定的页(封面、章节页)用 `slots` 绝对坐标。草案两份都给了,删掉不要的那份——两份都留着打包会 FAIL,因为消费端不知道该按哪份渲染。
96
+ **页型给 `flow` 还是 `slots`,由你定**:内容长度会变的内容页(列表、表格、卡片组)优先用 `flow`,区带依次排,高度由实际内容决定;构图固定的页(封面、章节页)用 `slots` 绝对坐标。在扁平 `layout_modes:` 段为每个候选页型填 `flow` 或 `slots`,打包时按它落一份。判据就在该页型上方的结构事实里:规整多列栅格、等距重复的间距、成对出现的长文本槽都指向 `flow`。`flow` 中并列卡片以 `grid` 表达,每张卡片的容器、标题和正文放在同一个一层 `role: group` 中;logo、页码、页眉和页脚等固定锚点留在带 `box` 的 `free` 区带。模型结合实际内容判断纵向间距与留白,不机械照搬样张的 `y` 坐标。
94
97
 
95
98
  普查是有损的。判断不了时可以直接翻 `<outdir>/ref/source/` —— PPTX 解压后的原文都在那里(`ppt/slides/slideN.xml`、`ppt/slideLayouts/`、`ppt/theme/`)。它只在中间产物里,不进交付包。
96
99
 
@@ -114,7 +117,7 @@ exit 0 即交付。FAIL 会指名道姓(TODO 未改 / 数值不可追溯 / 枚
114
117
  - [ ] Agent Fast Path 写清 `assetRoot` / `assetPaths` 的不透明前缀协议,并禁止目录探索。
115
118
  - [ ] 抽不出的都在 `gaps`,无编造
116
119
 
117
- 配套 `v2-format-spec.md`(包形态与 schema)、`font-fallback.yaml`(商业字体降级表)只在你要偏离草案结构时才需要读——草案已经是最终格式。
120
+ 配套 `v2-format-spec.md`(包形态与 schema)、`font-fallback.yaml`(商业字体降级表)只在你要偏离草案结构时才需要读——草案的字段结构与包一致,`package.py` 按它落盘。
118
121
 
119
122
  ## Consume The Style Pack In A Deck
120
123
 
@@ -128,7 +131,7 @@ When generating a deck:
128
131
  2. Build `<deck-stage width="<canvas width>" height="<canvas height>">` using the `canvas` declared in `layouts.md` — source decks are not always 16:9, and a default-sized stage shifts every coordinate on the page. Each slide is one static `<section>`.
129
132
  3. Inline CSS variables from `design.md` into the HTML `<style>` block using a `--ppt-*` prefix.
130
133
  4. **位移动画用独立的 `translate` 属性**:`@keyframes fadeUp { from{opacity:0; translate:0 24px} to{opacity:1; translate:0 0} }`。`transform` 是单一属性,动画里碰它会覆盖掉元素原有的那条(`left:50%; transform:translateX(-50%)` 的居中就此丢失);`translate` / `rotate` / `scale` 各自独立,与已有 `transform` 叠加。
131
- 5. Map `layouts.md` slots to absolute-positioned elements inside each section: `box` is `[x,y,w,h]`, and each slot also carries the template's own `size` / `weight` / `color` / `align` / `valign` use them as-is instead of picking your own type scale. A slot with `asset` is a fixed image element (logo, mark): place that asset at that box on that archetype only. Do not reflow any of this as generic web grids.
134
+ 5. Map `layouts.md` slots to absolute-positioned elements inside each section: expand `box: [x,y,w,h]` mechanically to `left/top/width/height`, then apply the slot's `css` declaration string unchanged. `box` owns geometry; `css` owns all rendering style, including the template's text padding, typography, alignment, line height, letter spacing, and rotation. Do not reinterpret PPTX fields or replace slot CSS with your own type scale. A slot with `asset` is a fixed image element (logo, mark): place that asset at that box on that archetype only. Do not reflow any of this as generic web grids.
132
135
  6. Copy `<pack_dir>/assets/` into the project, for example `assets/pptx-style/<pack-name>/`, and reference those copied files with relative URLs. The scratch `tmp/pptx-style-extract/...` path must never appear in the final HTML.
133
136
  7. Use the font stacks and fallback rules from `design.md`; do not install fonts or dependencies at runtime.
134
137
  8. Run the slide preflight checks: no resource failures, no section overflow, and sampled screenshots follow the package colors, typography, layouts, assets, and Hard Rules.
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env python3
2
- """风格包 v2 机器门禁(镜像 ../v2-format-spec.md §5 十八行:V2-1..V2-15 + V2-R5/R6/R7)。
2
+ """风格包 v2 机器门禁(镜像 ../v2-format-spec.md §5V2-1..V2-16 + V2-R5/R6/R7)。
3
3
 
4
4
  用法: check_v2.py <包目录>
5
5
  只做 v2 追加校验;check_v1 的规则不重复实现,调用方须先跑 check_v1.py。
@@ -937,6 +937,36 @@ def rule_v2_15(pack):
937
937
  return res
938
938
 
939
939
 
940
+ LEGACY_SLOT_STYLE_KEYS = frozenset(('size', 'weight', 'color', 'align', 'valign', 'insets_px'))
941
+
942
+
943
+ def rule_v2_16(pack):
944
+ """V2-16 slot 的渲染样式只通过 CSS 承载,禁止泄漏 PPTX/旧契约字段。"""
945
+ res = Result('V2-16', 'slot 渲染样式统一使用 css(box 只负责几何)')
946
+ checked = 0
947
+ for name, (layout, _md) in sorted(pack.layouts.items()):
948
+ if not isinstance(layout, dict):
949
+ continue
950
+ groups = [('slots', layout.get('slots') or [])]
951
+ flow = layout.get('flow')
952
+ if isinstance(flow, dict):
953
+ for i, region in enumerate(flow.get('regions') or []):
954
+ if isinstance(region, dict):
955
+ groups.append((f'flow.regions[{i}].items', region.get('items') or []))
956
+ for group, items in groups:
957
+ for i, item in enumerate(items):
958
+ if not isinstance(item, dict):
959
+ continue
960
+ checked += 1
961
+ legacy = sorted(LEGACY_SLOT_STYLE_KEYS & set(item))
962
+ if legacy:
963
+ res.fails.append(
964
+ f'layouts.{name}.{group}[{i}] 含旧样式键 {"/".join(legacy)};'
965
+ '保留 box/role/type/asset,把渲染属性转换为可直接写入 style 的 css')
966
+ res.notes.append(f'校验 {checked} 个 slot/flow item')
967
+ return res
968
+
969
+
940
970
  def rule_v2_14(pack):
941
971
  """V2-14 flow 与 slots 二选一;flow 的区带类型合法、grid 必带 cols"""
942
972
  res = Result('V2-14', 'flow 形态合法(与 slots 互斥,区带类型在枚举内)')
@@ -980,8 +1010,8 @@ def rule_v2_14(pack):
980
1010
 
981
1011
  RULES = [rule_v2_1, rule_v2_2, rule_v2_3, rule_v2_4, rule_v2_5, rule_v2_6,
982
1012
  rule_v2_7, rule_v2_8, rule_v2_9, rule_v2_10, rule_v2_11, rule_v2_12,
983
- rule_v2_13, rule_v2_14, rule_v2_15, rule_sidecar_dup, rule_audit_fields,
984
- rule_layouts_pointer]
1013
+ rule_v2_13, rule_v2_14, rule_v2_15, rule_v2_16, rule_sidecar_dup,
1014
+ rule_audit_fields, rule_layouts_pointer]
985
1015
 
986
1016
 
987
1017
  def main():