@open-feishu-card/renderer 0.3.1 → 0.3.2

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/dist/all.css CHANGED
@@ -288,6 +288,13 @@
288
288
  word-break: break-word;
289
289
  vertical-align: middle;
290
290
  }
291
+ /* 前缀图标(markdown.icon):与首行文字垂直居中,右侧留 4px。
292
+ 容器是 flex row,图标作为首个 flex 子项参与排布。 */
293
+ .universal-card-markdown__icon {
294
+ display: inline-flex; align-items: center; justify-content: center;
295
+ flex-shrink: 0; margin-right: 4px;
296
+ height: 1.6em;
297
+ }
291
298
  .universal-card-markdown__children {
292
299
  flex: 1;
293
300
  min-width: 0;
package/dist/index.cjs CHANGED
@@ -1258,6 +1258,13 @@ var BASE_STYLES_CSS = `/**
1258
1258
  word-break: break-word;
1259
1259
  vertical-align: middle;
1260
1260
  }
1261
+ /* \u524D\u7F00\u56FE\u6807\uFF08markdown.icon\uFF09\uFF1A\u4E0E\u9996\u884C\u6587\u5B57\u5782\u76F4\u5C45\u4E2D\uFF0C\u53F3\u4FA7\u7559 4px\u3002
1262
+ \u5BB9\u5668\u662F flex row\uFF0C\u56FE\u6807\u4F5C\u4E3A\u9996\u4E2A flex \u5B50\u9879\u53C2\u4E0E\u6392\u5E03\u3002 */
1263
+ .universal-card-markdown__icon {
1264
+ display: inline-flex; align-items: center; justify-content: center;
1265
+ flex-shrink: 0; margin-right: 4px;
1266
+ height: 1.6em;
1267
+ }
1261
1268
  .universal-card-markdown__children {
1262
1269
  flex: 1;
1263
1270
  min-width: 0;
@@ -5725,15 +5732,50 @@ function registerBuiltins() {
5725
5732
  }
5726
5733
  const childCtx = { ...ctx, textMetrics: { fontSize, lineHeight } };
5727
5734
  const linesStyle = lineClampStyle(p.lines ?? p.textLines);
5735
+ const iconVNode = renderPrefixIcon(p.icon, ctx, fontSize);
5728
5736
  return h(
5729
5737
  "div",
5730
5738
  { className: `${CLS}-markdown`, style },
5739
+ iconVNode,
5731
5740
  h("div", {
5732
5741
  className: `${CLS}-markdown__children`,
5733
5742
  style: Object.keys(linesStyle).length ? linesStyle : void 0
5734
5743
  }, renderElements(p.elements, childCtx))
5735
5744
  );
5736
5745
  }
5746
+ function renderPrefixIcon(raw, ctx, fontSize) {
5747
+ if (!isRecord(raw)) return null;
5748
+ const inner = isRecord(raw.property) ? raw.property : raw;
5749
+ const tag = typeof raw.tag === "string" ? raw.tag : "standard_icon";
5750
+ const sizeProp = typeof inner.size === "string" ? inner.size : typeof raw.size === "string" ? raw.size : void 0;
5751
+ if (tag === "custom_icon") {
5752
+ const imgKey = typeof inner.img_key === "string" ? inner.img_key : typeof raw.img_key === "string" ? raw.img_key : void 0;
5753
+ if (!imgKey) return null;
5754
+ const src = resolveImageSrc({ img_key: imgKey }, ctx) ?? imgKey;
5755
+ const sizePx = sizeProp && /^\d/.test(sizeProp) ? Number(/^(\d+(?:\.\d+)?)/.exec(sizeProp)[1]) : fontSize;
5756
+ return h(
5757
+ "span",
5758
+ { className: `${CLS}-markdown__icon` },
5759
+ h("img", {
5760
+ src,
5761
+ alt: "",
5762
+ style: { width: sizePx + "px", height: sizePx + "px", objectFit: "contain" }
5763
+ })
5764
+ );
5765
+ }
5766
+ const token = typeof inner.token === "string" ? inner.token : "";
5767
+ if (!token) return null;
5768
+ const iconNode = renderIcon({
5769
+ property: {
5770
+ token,
5771
+ color: typeof inner.color === "string" ? inner.color : void 0,
5772
+ // 未显式给 size 时跟随文本字号,避免回落到固定 16px 与文字不搭
5773
+ size: sizeProp ?? fontSize + "px"
5774
+ }
5775
+ }, ctx);
5776
+ if (!iconNode) return null;
5777
+ return h("span", { className: `${CLS}-markdown__icon` }, iconNode);
5778
+ }
5737
5779
  registerComponent("markdown", MarkdownComponent);
5738
5780
  registerComponent("markdown_v1", MarkdownComponent);
5739
5781
  function lineClampStyle(lines) {
package/dist/index.js CHANGED
@@ -1257,6 +1257,13 @@ var BASE_STYLES_CSS = `/**
1257
1257
  word-break: break-word;
1258
1258
  vertical-align: middle;
1259
1259
  }
1260
+ /* \u524D\u7F00\u56FE\u6807\uFF08markdown.icon\uFF09\uFF1A\u4E0E\u9996\u884C\u6587\u5B57\u5782\u76F4\u5C45\u4E2D\uFF0C\u53F3\u4FA7\u7559 4px\u3002
1261
+ \u5BB9\u5668\u662F flex row\uFF0C\u56FE\u6807\u4F5C\u4E3A\u9996\u4E2A flex \u5B50\u9879\u53C2\u4E0E\u6392\u5E03\u3002 */
1262
+ .universal-card-markdown__icon {
1263
+ display: inline-flex; align-items: center; justify-content: center;
1264
+ flex-shrink: 0; margin-right: 4px;
1265
+ height: 1.6em;
1266
+ }
1260
1267
  .universal-card-markdown__children {
1261
1268
  flex: 1;
1262
1269
  min-width: 0;
@@ -5724,15 +5731,50 @@ function registerBuiltins() {
5724
5731
  }
5725
5732
  const childCtx = { ...ctx, textMetrics: { fontSize, lineHeight } };
5726
5733
  const linesStyle = lineClampStyle(p.lines ?? p.textLines);
5734
+ const iconVNode = renderPrefixIcon(p.icon, ctx, fontSize);
5727
5735
  return h(
5728
5736
  "div",
5729
5737
  { className: `${CLS}-markdown`, style },
5738
+ iconVNode,
5730
5739
  h("div", {
5731
5740
  className: `${CLS}-markdown__children`,
5732
5741
  style: Object.keys(linesStyle).length ? linesStyle : void 0
5733
5742
  }, renderElements(p.elements, childCtx))
5734
5743
  );
5735
5744
  }
5745
+ function renderPrefixIcon(raw, ctx, fontSize) {
5746
+ if (!isRecord(raw)) return null;
5747
+ const inner = isRecord(raw.property) ? raw.property : raw;
5748
+ const tag = typeof raw.tag === "string" ? raw.tag : "standard_icon";
5749
+ const sizeProp = typeof inner.size === "string" ? inner.size : typeof raw.size === "string" ? raw.size : void 0;
5750
+ if (tag === "custom_icon") {
5751
+ const imgKey = typeof inner.img_key === "string" ? inner.img_key : typeof raw.img_key === "string" ? raw.img_key : void 0;
5752
+ if (!imgKey) return null;
5753
+ const src = resolveImageSrc({ img_key: imgKey }, ctx) ?? imgKey;
5754
+ const sizePx = sizeProp && /^\d/.test(sizeProp) ? Number(/^(\d+(?:\.\d+)?)/.exec(sizeProp)[1]) : fontSize;
5755
+ return h(
5756
+ "span",
5757
+ { className: `${CLS}-markdown__icon` },
5758
+ h("img", {
5759
+ src,
5760
+ alt: "",
5761
+ style: { width: sizePx + "px", height: sizePx + "px", objectFit: "contain" }
5762
+ })
5763
+ );
5764
+ }
5765
+ const token = typeof inner.token === "string" ? inner.token : "";
5766
+ if (!token) return null;
5767
+ const iconNode = renderIcon({
5768
+ property: {
5769
+ token,
5770
+ color: typeof inner.color === "string" ? inner.color : void 0,
5771
+ // 未显式给 size 时跟随文本字号,避免回落到固定 16px 与文字不搭
5772
+ size: sizeProp ?? fontSize + "px"
5773
+ }
5774
+ }, ctx);
5775
+ if (!iconNode) return null;
5776
+ return h("span", { className: `${CLS}-markdown__icon` }, iconNode);
5777
+ }
5736
5778
  registerComponent("markdown", MarkdownComponent);
5737
5779
  registerComponent("markdown_v1", MarkdownComponent);
5738
5780
  function lineClampStyle(lines) {
package/dist/styles.css CHANGED
@@ -288,6 +288,13 @@
288
288
  word-break: break-word;
289
289
  vertical-align: middle;
290
290
  }
291
+ /* 前缀图标(markdown.icon):与首行文字垂直居中,右侧留 4px。
292
+ 容器是 flex row,图标作为首个 flex 子项参与排布。 */
293
+ .universal-card-markdown__icon {
294
+ display: inline-flex; align-items: center; justify-content: center;
295
+ flex-shrink: 0; margin-right: 4px;
296
+ height: 1.6em;
297
+ }
291
298
  .universal-card-markdown__children {
292
299
  flex: 1;
293
300
  min-width: 0;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@open-feishu-card/renderer",
3
- "version": "0.3.1",
3
+ "version": "0.3.2",
4
4
  "description": "零框架依赖的飞书卡片渲染引擎:Web / DOM / SSR,输入 RAW 或公开 DSL,输出真实 DOM 或 HTML 字符串",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",