npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@lark-apaas/coding-cd-elements

v0.1.4

Published

Custom elements SDK for the buildless runtime (design-html / 创意模式) — self-contained IIFE bundles served from feishucdn, consumed via <script src>

Downloads

1,262

Readme

@lark-apaas/coding-cd-elements

buildless 运行时(design-html / 创意模式,AppType=8)的自定义元素 SDK。TS 源码经 tsup 编译成自包含 IIFE,由 feishucdn 分发,产物用 <script src> 引入。

⚠️ 与同目录的 buildless/(registry 包)分发模型相反

两个包都在 packages/registries/ 下、都服务 buildless 运行时,但交付方式完全不同,别混:

| | buildless/(registry) | cd-elements/(本包) | | ------ | ---------------------------------------------------- | ------------------------------------------------------------------ | | 分发 | miaoda registry add 抓 tarball,源码拷进项目根 | CDN,产物 <script src> 引远端钉版 URL | | 可改性 | AI 与用户都能改(改坏只影响该产物) | 产物里改不到,行为在所有引用它的产物间一致 | | CLI | 由 miaoda-cli 消费 | 不由 CLI 消费(无 miaodaRegistry 块,registry add 抓不到) | | 适合 | shadcn 式 UI 素材,用户要改样式和结构 | 基建型元素,行为必须全局统一、且不该被产物作者改动 |

<cd-image> 属于后者——它封装 TOS 图片参数拼接、webp 探测、DEFAULT_RESOLUTIONS 阶梯、SRC_ALLOWLIST 白名单。这些用户不该改:改坏 SRC_ALLOWLIST 会让优化静默失效,改坏阶梯会造出踩服务端冷处理的一次性尺寸变体(实测冷启 ~23s)。copy-in 把源码摊在项目根,AI 完全可能"顺手优化"掉它们。

选型判据见 docs/design-html-sdk-spec.md §1.1:用户该改的放 registry,用户不该改的放本包。

⚠️ 不要把 CDN 理解成「升级能自动覆盖存量产物」:产物里写的是钉版 URL(design-html-sdk-spec.md §8 的固定版本契约要求如此),发新版本只作用于新产物——这点和 copy-in 一样。真实优势是代码不落进产物源码、跨产物共享浏览器缓存,以及为将来的平台注入留了口子(只有注入方统一控制版本时"覆盖存量"才成立)。

目录结构

src/
  core/          # 元素间共享的内核(一份,避免各元素复制导致漂移)
    tos.ts       #   TOS 图片处理:applyParamsToUrl / buildSrcSet / supportWebp / 白名单与阶梯常量
    dom.ts       #   DOM 工具:defineOnce(防重复注册)/ injectStyleOnce(防重复注样式)
  elements/      # 元素实现,一个元素一个文件
    image.ts     #   <cd-image>
  index.ts       # 全量入口:引入即注册所有元素
dist/            # tsup 产物(gitignore,发布物)
__tests__/       # vitest(happy-dom 环境)
__gallery/       # 浏览器手工冒烟页

元素一览

| 元素 | 单文件产物 | 说明 | | ------------ | ------------------- | ---------------------------------------------------------- | | <cd-image> | dist/image.min.js | 图片性能优化:TOS resize / webp / 响应式 srcSet / 异步解码 |

每个元素源码顶部有 /* BEGIN USAGE */ … /* END USAGE */ 块,声明注册的标签名、属性与约束。

用法

引全部元素(推荐,元素总量小):

<script src="<CDN_BASE>/@lark-apaas/coding-cd-elements@<ver>/dist/cd-elements.min.js"></script>

只引一个元素(各单文件自包含,内核已 inline,无加载顺序要求):

<script src="<CDN_BASE>/@lark-apaas/coding-cd-elements@<ver>/dist/image.min.js"></script>

<cd-image src="/aily/api/v1/files/static/x.png" width="400" height="260" alt="…"></cd-image>

版本精确 pin,不用浮动版本——与 design-html-sdk-spec.md §8 的 CDN 固定版本契约一致。调试时可把 .min.js 换成 .js(未压缩同源产物)。

CDN 路径从哪来

本包不自己上传 CDN。产物由 apaas/fullstack-plugincoding-unpkg-sdk 镜像产线从 npm 搬到 feishucdn:

<CDN_BASE> = https://sf3-scmcdn-cn.feishucdn.com/obj/feishu-static/miaoda/coding-unpkg-sdk

路径与 unpkg 原生对齐(<pkg>@<version>/<包内原始路径>),scoped 包自然嵌套。

为什么必须走 CDN:创意模式产物的 CSP 把 script-src 收口到 feishucdn,引 unpkg.com 会被浏览器拦截。

<cd-image> 与原生 <img> 的等价性

模型是把 cd-imageimg 用的,所以它的承诺是「常见写法下等同原生 img」——不是完全等同。差异的根源只有一条:DOM 里多了一层普通元素,而 CSS 里替换元素与普通元素的语义不同。

三条机制守住等价性:

| 机制 | 解决什么 | | ----------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- | | 宿主 display:contents | 宿主不生成盒子,参与布局的始终是那个原生 img,替换元素语义全部为真 | | :where(cd-image>img){…:inherit} | display:contents 只从盒子树摘掉宿主,DOM 树没变section > .bg 这类结构选择器仍命中宿主而其值会被丢弃;这条把已算好的 computed value 搬给内层 img | | width/height → 宿主 --cd-w/--cd-h/--cd-ar | 内层 img 上属性是表现层提示,层叠位置低于一切作者规则,会被上面的 width:inherit 抹掉;改由宿主变量承载后尺寸只剩一条路径 |

后两条一律包 :where() 归零权重——它们是兜底,任何直接命中 img 的作者规则都该赢。

已知偏差(改动前先读,别重复论证)

  1. 结构选择器 + displaysection > .bg{display:block} 传不过去。display 不能进搬运名单——替换元素上的 display:contents 计算为 none,搬过去图片会整个消失。作者写 .bg{display:block}(非结构选择器)正常,class 已拷到内层 img。
  2. 搬运名单漏项:名单外的非继承属性,只有当作者用结构选择器设置时才会丢。加条目是安全的(见下),所以发现一条补一条即可。
  3. 宿主的伪元素会渲染.bg::after{content:"x"} 在宿主上会生成盒子,原生 img 是替换元素不渲染伪元素。
  4. 带 tag 名的结构选择器section > img.bg 两头都不命中(宿主标签是 cd-image,内层 img 又多一级)。

为什么是白名单,什么时候可以删掉它

这套机制是约束组合下的唯一解,不是随手挑的方案。三条约束同时成立才需要它:

  1. buildless 静态 HTML —— 没有编译期,行为只能靠运行时自定义元素承载,wrapper 必然出现在 DOM 里;
  2. 作者是模型,把 cd-imageimg 用,不能靠文档约定它的契约;
  3. 承诺等同原生 img —— 于是布局主体必须是那个原生 img,宿主只能 display:contents,命中宿主的样式就必须搬。

去掉任何一条,白名单都可以整个删掉:

  • 去掉 ③ → 改用生态标准姿势「宿主即盒子」(:host{display:inline-block} + 内层 width:100%,Shoelace / Cloudinary / lazy-img 都这么做),代价是模型得知道 cd-image 有自己的尺寸契约(Shopify 给 Polaris web components 就是配 agent skill 解决的);
  • 去掉 ①(产物下发时由服务端把 <cd-image> 重写成 <img srcset>)→ DOM 里没有 wrapper,整类问题一次性消失,这是 Next/unpic 那条路。

平台层没有别的出路:csswg-drafts#11647display:contentsnth-child)已被 CSSWG Closed as Question Answered——「只有盒子树受影响,基于文档树的选择器匹配不受影响」是设计如此;补救提案(#7012 只统计已渲染子元素的伪类、::wrap/::contents)都还停在提案阶段。

加名单条目是安全的:475 属性全枚举比对过宿主与原生 img 的默认计算值,只有 displayoverflow 系列不同。所以名单只要不碰那几个,加多少条都不引入新偏差;漏一条也只是该属性在「仅命中宿主的结构选择器」这条支路上不生效。

验收

__tests__/*.test.ts 跑在 happy-dom 上,没有布局引擎——只能断言注入的 CSS 文本与 DOM 属性。真正的几何等价性靠浏览器手工验收页:

pnpm --filter @lark-apaas/coding-cd-elements build
open __tests__/manual/native-parity.html      # 31 组 CSS 场景,逐格比对 cd-image 与原生 img

页面顶部会给出「N/N 全部与原生一致」的结论,不一致的行高亮。改搬运名单或尺寸逻辑后必须重跑,并且尽量在目标 WKWebView 上也跑一次——搬运名单选的是白名单而非 all:inherit 黑名单,正是因为黑名单的边界由各引擎的 UA 样式表决定,而我们只能在 Chrome 上验证。

开发

pnpm --filter @lark-apaas/coding-cd-elements build       # tsup → dist/
pnpm --filter @lark-apaas/coding-cd-elements dev         # watch 模式
pnpm --filter @lark-apaas/coding-cd-elements typecheck
pnpm --filter @lark-apaas/coding-cd-elements lint

pnpm test                                                       # 全仓 vitest(含本包)
open __gallery/image.html                                       # 浏览器冒烟(先 build)

__tests__ 直接 import src/(不测产物),所以改源码即可跑测试,不必先 build。

新增一个元素

  1. src/elements/<name>.ts 写实现,export class + 文件末尾 defineOnce('cd-<name>', Class)
  2. 顶部补 /* BEGIN USAGE */ 块(标签名 / 属性 / 约束)
  3. tsup.config.tsENTRY 加一项 <name>: 'src/elements/<name>.ts'
  4. src/index.ts 加一行 import './elements/<name>'
  5. __tests__/<name>.test.ts 加单测(首行 // @vitest-environment happy-dom
  6. __gallery/<name>.html 加冒烟页
  7. 更新本文「元素一览」
  8. 让 Agent 知道它存在——在 packages/skills/coding-steering/steering/design-html/ 补 skill 说明(含 CDN URL 与用法)

共享逻辑放 src/core/不要在元素间互相 import——每个元素产物必须自包含,能被单独引入。

发版流程(两步,跨仓)

1. 本仓:改元素 → chiya 发 npm(registry.npmjs.org)
2. fullstack-plugin:coding-unpkg-sdk/manifest.json 追加新版本号 → MR → SCM build 上传 feishucdn

manifest 条目形如:

{
  "@lark-apaas/coding-cd-elements": {
    "versions": ["0.1.0"],
    "files": ["dist/*.js"],
  },
}

versions 是数组、多版本并存——升级时追加而非替换,老产物 pin 的旧 URL 继续可用(保留降级能力)。

files 是「目录 + 扩展名」级 glob:dist/ 下新增或重命名产物文件不用动 fullstack-plugin(下次发版自动被镜像搬走)。只有改 tsup 的 outDir 目录名才必须同步改这条 glob,而且得写成两条并存(["dist/*.js", "umd/*.js"] 之类)——glob 对 versions 里所有版本一起生效,老版本 tarball 里只有老目录。这是产物目录不轻易改名的主要原因。

⚠️ registry.npmmirror.com(mirror 脚本默认源)同步公网 npm 有延迟。发布脚本末尾虽有 npx cnpm sync 主动推同步,但那只是触发;SCM 构建环境建议把 NPM_MIRROR 指向 https://registry.npmjs.org(源站无延迟)。

docs/conventions.md §9 的两处偏离

§9 的 SDK 模板是给import 消费的 npm 包写的,本包消费方是浏览器 <script src>,故:

  • format: ['iife'] 而非 ['esm','cjs'] —— design-html-sdk-spec.md §2 明令避免 type="module"(产物内 Babel 编译基于 classic scripts,window 是唯一跨脚本共享机制)
  • 不出 dts —— 没有 import 型消费者,类型声明无处可用

其余均按 §9:target: 'es2022' 对齐 root tsconfig、src/ 布局、构建前 clean。

License

MIT — see LICENSE.