@lark-apaas/coding-steering 0.1.32-beta.0 → 0.1.32-dev.3598eb3
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.
- package/package.json +6 -6
- package/steering/design-html/skills/charts/SKILL.md +4 -0
- package/steering/design-html/skills/pptx-style-extract/SKILL.md +71 -26
- package/steering/design-html/skills/pptx-style-extract/font-fallback.yaml +3 -3
- package/steering/design-html/skills/pptx-style-extract/scripts/census.py +26 -14
- package/steering/design-html/skills/pptx-style-extract/scripts/check_v2.py +153 -8
- package/steering/design-html/skills/pptx-style-extract/scripts/draft.py +2831 -293
- package/steering/design-html/skills/pptx-style-extract/scripts/extract.py +544 -22
- package/steering/design-html/skills/pptx-style-extract/scripts/ooxml.py +19 -2
- package/steering/design-html/skills/pptx-style-extract/scripts/package.py +991 -165
- package/steering/design-html/skills/pptx-style-extract/scripts/parts.py +22 -3
- package/steering/design-html/skills/pptx-style-extract/scripts/query.py +4 -9
- package/steering/design-html/skills/pptx-style-extract/scripts/render_pages.py +20 -12
- package/steering/design-html/skills/pptx-style-extract/scripts/test_asset_judgment_package.py +556 -0
- package/steering/design-html/skills/pptx-style-extract/scripts/test_background_composite.py +364 -0
- package/steering/design-html/skills/pptx-style-extract/scripts/test_color_contract.py +60 -0
- package/steering/design-html/skills/pptx-style-extract/scripts/test_design_consumer_contract.py +76 -0
- package/steering/design-html/skills/pptx-style-extract/scripts/test_flow_layout_contract.py +528 -0
- package/steering/design-html/skills/pptx-style-extract/scripts/test_layout_css.py +1814 -0
- package/steering/design-html/skills/pptx-style-extract/scripts/test_logo_scope.py +600 -0
- package/steering/design-html/skills/pptx-style-extract/scripts/test_rounded_contract.py +112 -0
- package/steering/design-html/skills/pptx-style-extract/scripts/test_text_role_contract.py +315 -0
- package/steering/design-html/skills/pptx-style-extract/scripts/verify_layout_assets.py +421 -0
- package/steering/design-html/skills/pptx-style-extract/scripts/verify_logo_scope.py +12 -0
- package/steering/design-html/skills/pptx-style-extract/v2-format-spec.md +27 -15
- package/steering/design-html/skills/preflight/scripts/probe.sh +0 -0
- package/steering/nestjs-react-fullstack/skills/app-init-feasibility-guide/SKILL.md +1 -0
- package/steering/nestjs-react-fullstack/skills/authn-guide/SKILL.md +6 -0
- package/steering/nestjs-react-fullstack/skills/authz-guide/SKILL.md +5 -5
- package/steering/nestjs-react-fullstack/skills/authz-guide/references/dynamic-permission-guide.md +1 -1
- package/steering/nestjs-react-fullstack/skills/client-builtins-file-storage-service/SKILL.md +37 -113
- package/steering/nestjs-react-fullstack/skills/client-builtins-user-service/SKILL.md +13 -2
- package/steering/nestjs-react-fullstack/skills/code-fix/SKILL.md +7 -7
- package/steering/nestjs-react-fullstack/skills/coding-guide/SKILL.md +149 -24
- package/steering/nestjs-react-fullstack/skills/connections-sdk/SKILL.md +202 -0
- package/steering/nestjs-react-fullstack/skills/nestjs-cache/SKILL.md +255 -0
- package/steering/nestjs-react-fullstack/skills/plugin-guide/SKILL.md +158 -543
- package/steering/nestjs-react-fullstack/skills/plugin-guide/references/plugin-coding-guide.md +15 -1
- package/steering/nestjs-react-fullstack/skills/plugin-guide/references/table.md +30 -14
- package/steering/nestjs-react-fullstack/skills/raw-sql-boundary-audit/SKILL.md +63 -0
- package/steering/nestjs-react-fullstack/skills/server-builtins-file-storage-service/SKILL.md +1 -1
- package/steering/nestjs-react-fullstack/skills_common/trigger-guide/SKILL.md +284 -12
- package/steering/nestjs-react-fullstack/skills_local/plugin-guide/SKILL.md +4 -0
- package/steering/vite-react/skills/plugin-guide/SKILL.md +3 -1
- package/steering/vite-react/skills/react-three-fiber/SKILL.md +4 -0
- package/steering/nestjs-react-fullstack/skills/client-add-aily-web-chat/SKILL.md +0 -139
- package/steering/nestjs-react-fullstack/skills/feishu/SKILL.md +0 -269
- package/steering/nestjs-react-fullstack/skills/feishu/references/approval.md +0 -214
- package/steering/nestjs-react-fullstack/skills/feishu/references/attendance.md +0 -163
- package/steering/nestjs-react-fullstack/skills/feishu/references/bitable.md +0 -311
- package/steering/nestjs-react-fullstack/skills/feishu/references/calendar.md +0 -190
- package/steering/nestjs-react-fullstack/skills/feishu/references/contacts.md +0 -160
- package/steering/nestjs-react-fullstack/skills/feishu/references/doc.md +0 -257
- package/steering/nestjs-react-fullstack/skills/feishu/references/drive.md +0 -104
- package/steering/nestjs-react-fullstack/skills/feishu/references/events.md +0 -199
- package/steering/nestjs-react-fullstack/skills/feishu/references/id-convert.md +0 -128
- package/steering/nestjs-react-fullstack/skills/feishu/references/messaging.md +0 -207
- package/steering/nestjs-react-fullstack/skills/feishu/references/oauth.md +0 -165
- package/steering/nestjs-react-fullstack/skills/feishu/references/perm.md +0 -91
- package/steering/nestjs-react-fullstack/skills/feishu/references/wiki.md +0 -165
- package/steering/nestjs-react-fullstack/skills_common/trigger-guide/references/trigger-lifecycle.md +0 -301
|
@@ -39,15 +39,15 @@ class Package:
|
|
|
39
39
|
self.masters = sorted((n for n in self.names if MASTER_RE.match(n)), key=_num)
|
|
40
40
|
self.themes, self.theme_discovery = self._find_themes(ct)
|
|
41
41
|
# zip directory entries ('ppt/media/') must not be counted as assets —
|
|
42
|
-
#
|
|
42
|
+
# they inflate media totals by one.
|
|
43
43
|
self.media = sorted(n for n in self.names
|
|
44
44
|
if n.startswith('ppt/media/') and not n.endswith('/'))
|
|
45
45
|
|
|
46
46
|
def _find_themes(self, ct):
|
|
47
47
|
"""Theme parts come from [Content_Types].xml, not from a path pattern.
|
|
48
48
|
|
|
49
|
-
Compressors relocate them —
|
|
50
|
-
ppt/slideMasters/theme/
|
|
49
|
+
Compressors relocate them — some rewrite them under
|
|
50
|
+
ppt/slideMasters/theme/ — and a `ppt/theme/` regex then finds
|
|
51
51
|
nothing to bind the masters to, so every schemeClr resolves to
|
|
52
52
|
UNRESOLVED:no-scheme. The path regex stays as the fallback for packages
|
|
53
53
|
whose content types are unreadable.
|
|
@@ -299,6 +299,22 @@ NV_TAGS = {'sp': 'p:nvSpPr', 'pic': 'p:nvPicPr', 'grpSp': 'p:nvGrpSpPr',
|
|
|
299
299
|
'cxnSp': 'p:nvCxnSpPr', 'graphicFrame': 'p:nvGraphicFramePr'}
|
|
300
300
|
|
|
301
301
|
|
|
302
|
+
def blip_opacity(blip):
|
|
303
|
+
"""Combine the alpha modulation transforms attached to one local picture."""
|
|
304
|
+
opacity = 1.0
|
|
305
|
+
found = False
|
|
306
|
+
for effect in blip:
|
|
307
|
+
if local(effect.tag) not in ('alphaMod', 'alphaModFix'):
|
|
308
|
+
continue
|
|
309
|
+
try:
|
|
310
|
+
amount = int(effect.get('amt'))
|
|
311
|
+
except (TypeError, ValueError):
|
|
312
|
+
continue
|
|
313
|
+
opacity *= max(0.0, min(amount / 100000.0, 1.0))
|
|
314
|
+
found = True
|
|
315
|
+
return round(opacity, 6) if found else None
|
|
316
|
+
|
|
317
|
+
|
|
302
318
|
def walk_tree(el, ctx, out, path=(), xf=(1.0, 1.0, 0.0, 0.0), depth=0):
|
|
303
319
|
sx, sy, dx, dy = xf
|
|
304
320
|
U, W, H = ctx.units, ctx.units.w, ctx.units.h
|
|
@@ -393,6 +409,9 @@ def walk_tree(el, ctx, out, path=(), xf=(1.0, 1.0, 0.0, 0.0), depth=0):
|
|
|
393
409
|
blip = sp.find('p:blipFill/a:blip', NS)
|
|
394
410
|
if blip is not None:
|
|
395
411
|
rec['media'] = ctx.media_of(blip.get(R_EMBED)) or ctx.media_of(blip.get(R_LINK))
|
|
412
|
+
opacity = blip_opacity(blip)
|
|
413
|
+
if opacity is not None:
|
|
414
|
+
rec['opacity'] = opacity
|
|
396
415
|
svg = blip.find('a:extLst//asvg:svgBlip', NS)
|
|
397
416
|
if svg is not None:
|
|
398
417
|
rec['media_svg'] = ctx.media_of(svg.get(R_EMBED))
|
|
@@ -244,14 +244,10 @@ def _recipe_css(fill, line, radii, effects):
|
|
|
244
244
|
dash = (line or {}).get('dash')
|
|
245
245
|
style = 'dashed' if dash and 'dash' in dash else 'solid'
|
|
246
246
|
out.append('border: %dpx %s %s' % (w, style, lc))
|
|
247
|
-
if radii:
|
|
247
|
+
if radii and all(r >= 1 for r in radii):
|
|
248
248
|
lo, hi = min(radii), max(radii)
|
|
249
249
|
if abs(hi - lo) <= 0.5:
|
|
250
250
|
out.append('border-radius: %gpx' % round(lo, 1))
|
|
251
|
-
else:
|
|
252
|
-
out.append('border-radius: %gpx\x00/* 源内 %g~%gpx 共 %d 档,归一档位由 L11 定 */'
|
|
253
|
-
% (round(sum(radii) / len(radii), 1), round(lo, 1), round(hi, 1),
|
|
254
|
-
len(set(round(r, 1) for r in radii))))
|
|
255
251
|
for e in effects or []:
|
|
256
252
|
if e.get('type') == 'outerShdw':
|
|
257
253
|
col = _css_color(e.get('color')) or 'rgba(0,0,0,0.25)'
|
|
@@ -266,8 +262,8 @@ def _recipe_css(fill, line, radii, effects):
|
|
|
266
262
|
|
|
267
263
|
def _sig(fill, line, effects):
|
|
268
264
|
"""分组键 = 填充 + 描边 + 效果。**不含圆角**——OOXML 圆角是 min(w,h) 的百分比,
|
|
269
|
-
同一配方在不同尺寸的卡上绝对 px
|
|
270
|
-
|
|
265
|
+
同一配方在不同尺寸的卡上绝对 px 必然不同,把它计入键会把一个配方拆成多组;
|
|
266
|
+
只有组内每个形状都明确共享同一绝对半径时才输出组级圆角,否则留给逐形状 CSS。"""
|
|
271
267
|
f = 'none'
|
|
272
268
|
if isinstance(fill, dict):
|
|
273
269
|
if fill.get('type') == 'solid':
|
|
@@ -305,8 +301,7 @@ def cmd_recipes(a, outdir):
|
|
|
305
301
|
g = groups.setdefault(k, {'n': 0, 'parts': Counter(), 'sizes': [], 'radii': [],
|
|
306
302
|
'fill': fill, 'line': line, 'fx': fx})
|
|
307
303
|
g['n'] += 1
|
|
308
|
-
|
|
309
|
-
g['radii'].append(radius)
|
|
304
|
+
g['radii'].append(radius or 0)
|
|
310
305
|
g['parts'][short(s['part'])] += 1
|
|
311
306
|
b = s.get('box') or {}
|
|
312
307
|
if b.get('w'):
|
|
@@ -88,13 +88,15 @@ def css_gradient(grad):
|
|
|
88
88
|
def background_css(bg):
|
|
89
89
|
"""页底 <p:bg> 描述符 → CSS background 值。解析不出返回 None,交上层回退到下一层底色。
|
|
90
90
|
|
|
91
|
-
bgPr solid / bgRef 都带 `color
|
|
92
|
-
|
|
91
|
+
bgPr solid / bgRef 都带 `color`;线性 gradient 与形状渐变共用 css_gradient;
|
|
92
|
+
path 渐变和背景图不重建,按无底色处理,不能伪装成线性渐变。
|
|
93
93
|
"""
|
|
94
94
|
if not bg:
|
|
95
95
|
return None
|
|
96
96
|
kind = bg.get('type')
|
|
97
97
|
if kind == 'gradient':
|
|
98
|
+
if bg.get('path'):
|
|
99
|
+
return None
|
|
98
100
|
return css_gradient(bg)
|
|
99
101
|
if kind in ('image', 'none', 'pattern'):
|
|
100
102
|
return None
|
|
@@ -279,18 +281,19 @@ def render_shape(shape, media_url, stats):
|
|
|
279
281
|
|
|
280
282
|
HEAD = """<style>
|
|
281
283
|
body{margin:0;background:#2b2b2b;font-family:%s}
|
|
282
|
-
.page{position:relative;width
|
|
284
|
+
.page{position:relative;width:%dpx;height:%dpx;overflow:hidden}
|
|
283
285
|
.sp{position:absolute;box-sizing:border-box}
|
|
284
286
|
.sp p{margin:0}
|
|
285
287
|
.ph{position:absolute;left:6px;top:4px;font:16px/1.2 monospace;color:#ff2b88;background:#fff9;padding:1px 4px}
|
|
286
288
|
</style>
|
|
287
|
-
"""
|
|
289
|
+
"""
|
|
288
290
|
|
|
291
|
+
# 缩略框跟着画布比例走,缩放比也一起算——写死 16:9 会把非 16:9 模板的页面裁掉一截
|
|
289
292
|
INDEX_EXTRA = """<style>
|
|
290
|
-
.wrap{width
|
|
293
|
+
.wrap{width:%dpx;margin:0 auto;padding:16px 0}
|
|
291
294
|
.lbl{color:#eee;font:13px/1.6 monospace;margin:14px 0 4px}
|
|
292
|
-
.box{width
|
|
293
|
-
.box .page{transform:scale(
|
|
295
|
+
.box{width:%dpx;height:%dpx;overflow:hidden;margin-bottom:6px}
|
|
296
|
+
.box .page{transform:scale(%g);transform-origin:top left}
|
|
294
297
|
</style>
|
|
295
298
|
"""
|
|
296
299
|
|
|
@@ -508,7 +511,8 @@ def render_pages_png(pages, outdir, data, scale=0.5):
|
|
|
508
511
|
for m in data.get('media') or [] if m.get('exported') and m.get('out')}
|
|
509
512
|
png_dir = os.path.join(outdir, 'ref', 'rebuild', 'png')
|
|
510
513
|
os.makedirs(png_dir, exist_ok=True)
|
|
511
|
-
|
|
514
|
+
cpx = ((data.get('canvas') or {}).get('px') or [1920, 1080])
|
|
515
|
+
W, H = int(cpx[0] * scale), int(cpx[1] * scale)
|
|
512
516
|
for kind, n, label, layers, default_color, page_bg in pages:
|
|
513
517
|
canvas = Image.new('RGBA', (W, H), _rgba(page_bg) or (136, 136, 136, 255))
|
|
514
518
|
g = _grad_stops(page_bg or '')
|
|
@@ -642,15 +646,19 @@ def main():
|
|
|
642
646
|
tx1_of_master.get(master, '#000000'),
|
|
643
647
|
layout_bg.get(part, '#888')))
|
|
644
648
|
|
|
645
|
-
if only is not None:
|
|
646
|
-
pages = [p for p in pages if p[
|
|
649
|
+
if only is not None: # 对样张和版式一律生效(form=3 的代表页是版式,不是样张)
|
|
650
|
+
pages = [p for p in pages if p[1] in only]
|
|
647
651
|
|
|
648
652
|
stats = {'shapes': 0, 'text': 0, 'img_ok': 0, 'img_missing': 0, 'no_box': 0}
|
|
649
|
-
|
|
653
|
+
cw, ch = ((data.get('canvas') or {}).get('px') or [1920, 1080])[:2]
|
|
654
|
+
head = HEAD % (CJK_STACK, cw, ch) # 视口跟画布走,非 16:9 模板不能按 1920x1080 裁
|
|
655
|
+
thumb_scale = 960.0 / cw
|
|
656
|
+
index = [head, INDEX_EXTRA % (960, 960, round(ch * thumb_scale), thumb_scale),
|
|
657
|
+
'<div class="wrap">']
|
|
650
658
|
for kind, n, label, layers, default_color, page_bg in (() if args.no_html else pages):
|
|
651
659
|
html = page_html(layers, default_color, page_bg, media_url, stats)
|
|
652
660
|
with open(os.path.join(rebuild, '%s-%d.html' % (kind, n)), 'w', encoding='utf-8') as f:
|
|
653
|
-
f.write(
|
|
661
|
+
f.write(head + html)
|
|
654
662
|
index += ['<div class="lbl">%s</div>' % esc(label),
|
|
655
663
|
'<div class="box">%s</div>' % html]
|
|
656
664
|
index.append('</div>')
|