@open-feishu-card/adapter 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/index.cjs +101 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +101 -1
- package/dist/normalize-stored-colors.d.ts +14 -0
- package/dist/normalize-stored-colors.d.ts.map +1 -0
- package/package.json +3 -2
package/dist/index.cjs
CHANGED
|
@@ -1861,8 +1861,109 @@ function degradeUnknown(el) {
|
|
|
1861
1861
|
return { tag: "unknown", raw_tag: rawTag, fallback: el };
|
|
1862
1862
|
}
|
|
1863
1863
|
|
|
1864
|
+
// src/normalize-stored-colors.ts
|
|
1865
|
+
function hexColorToRgba(hex) {
|
|
1866
|
+
const h = hex.trim().replace(/^#/, "");
|
|
1867
|
+
if (h.length === 8) {
|
|
1868
|
+
const r = parseInt(h.slice(0, 2), 16);
|
|
1869
|
+
const g = parseInt(h.slice(2, 4), 16);
|
|
1870
|
+
const b = parseInt(h.slice(4, 6), 16);
|
|
1871
|
+
const a = Math.round(parseInt(h.slice(6, 8), 16) / 255 * 100) / 100;
|
|
1872
|
+
return `rgba(${r},${g},${b},${a})`;
|
|
1873
|
+
}
|
|
1874
|
+
if (h.length === 6) {
|
|
1875
|
+
const r = parseInt(h.slice(0, 2), 16);
|
|
1876
|
+
const g = parseInt(h.slice(2, 4), 16);
|
|
1877
|
+
const b = parseInt(h.slice(4, 6), 16);
|
|
1878
|
+
return `rgba(${r},${g},${b},1)`;
|
|
1879
|
+
}
|
|
1880
|
+
return void 0;
|
|
1881
|
+
}
|
|
1882
|
+
function readCustomBackgroundStyle(node) {
|
|
1883
|
+
const raw = node.custom_background_style;
|
|
1884
|
+
if (!raw || typeof raw !== "object") return void 0;
|
|
1885
|
+
const o = raw;
|
|
1886
|
+
const lightRaw = typeof o.light_mode === "string" ? o.light_mode : void 0;
|
|
1887
|
+
const darkRaw = typeof o.dark_mode === "string" ? o.dark_mode : void 0;
|
|
1888
|
+
if (!lightRaw || !darkRaw) return void 0;
|
|
1889
|
+
const light = lightRaw.startsWith("#") ? hexColorToRgba(lightRaw) : lightRaw;
|
|
1890
|
+
const dark = darkRaw.startsWith("#") ? hexColorToRgba(darkRaw) : darkRaw;
|
|
1891
|
+
if (!light || !dark) return void 0;
|
|
1892
|
+
return { light_mode: light, dark_mode: dark };
|
|
1893
|
+
}
|
|
1894
|
+
function normalizeStoredCardColors(dsl) {
|
|
1895
|
+
const colorEntries = {};
|
|
1896
|
+
const styleKey = (entry) => `${entry.light_mode}|${entry.dark_mode}`;
|
|
1897
|
+
const keyToAlias = /* @__PURE__ */ new Map();
|
|
1898
|
+
let bgSeq = 0;
|
|
1899
|
+
const ensureAlias = (prefix, entry) => {
|
|
1900
|
+
const existing2 = keyToAlias.get(styleKey(entry));
|
|
1901
|
+
if (existing2) return existing2;
|
|
1902
|
+
const alias = `${prefix}-${bgSeq++}`;
|
|
1903
|
+
colorEntries[alias] = entry;
|
|
1904
|
+
keyToAlias.set(styleKey(entry), alias);
|
|
1905
|
+
return alias;
|
|
1906
|
+
};
|
|
1907
|
+
const walk = (node) => {
|
|
1908
|
+
if (Array.isArray(node)) {
|
|
1909
|
+
for (const child of node) walk(child);
|
|
1910
|
+
return;
|
|
1911
|
+
}
|
|
1912
|
+
if (!node || typeof node !== "object") return;
|
|
1913
|
+
const obj = node;
|
|
1914
|
+
if (obj.tag === "column") {
|
|
1915
|
+
const custom = readCustomBackgroundStyle(obj);
|
|
1916
|
+
if (custom) {
|
|
1917
|
+
obj.background_style = ensureAlias("cus-bg", custom);
|
|
1918
|
+
delete obj.custom_background_style;
|
|
1919
|
+
}
|
|
1920
|
+
}
|
|
1921
|
+
for (const value of Object.values(obj)) walk(value);
|
|
1922
|
+
};
|
|
1923
|
+
walk(dsl.body);
|
|
1924
|
+
if (Object.keys(colorEntries).length === 0) return;
|
|
1925
|
+
const firstBg = colorEntries["cus-bg-0"] ?? Object.values(colorEntries)[0];
|
|
1926
|
+
if (firstBg) {
|
|
1927
|
+
const m = firstBg.light_mode.match(/^rgba\((\d+),(\d+),(\d+),/);
|
|
1928
|
+
if (m) {
|
|
1929
|
+
colorEntries["cus-accent"] = {
|
|
1930
|
+
light_mode: `rgba(${m[1]},${m[2]},${m[3]},1)`,
|
|
1931
|
+
dark_mode: firstBg.dark_mode.replace(/,\s*[\d.]+\)$/, ",1)")
|
|
1932
|
+
};
|
|
1933
|
+
}
|
|
1934
|
+
}
|
|
1935
|
+
colorEntries["cus-muted"] ??= {
|
|
1936
|
+
light_mode: "rgba(100,106,115,1)",
|
|
1937
|
+
dark_mode: "rgba(166,166,166,1)"
|
|
1938
|
+
};
|
|
1939
|
+
const config = dsl.config && typeof dsl.config === "object" ? dsl.config : {};
|
|
1940
|
+
dsl.config = config;
|
|
1941
|
+
const style = config.style && typeof config.style === "object" ? config.style : {};
|
|
1942
|
+
config.style = style;
|
|
1943
|
+
const existing = style.color && typeof style.color === "object" ? style.color : {};
|
|
1944
|
+
style.color = { ...colorEntries, ...existing };
|
|
1945
|
+
if (!colorEntries["cus-accent"]) return;
|
|
1946
|
+
const applyDefaultFontColors = (node) => {
|
|
1947
|
+
if (Array.isArray(node)) {
|
|
1948
|
+
for (const child of node) applyDefaultFontColors(child);
|
|
1949
|
+
return;
|
|
1950
|
+
}
|
|
1951
|
+
if (!node || typeof node !== "object") return;
|
|
1952
|
+
const obj = node;
|
|
1953
|
+
if (obj.tag === "markdown" && obj.font_color === void 0) {
|
|
1954
|
+
const size = obj.text_size;
|
|
1955
|
+
const content = typeof obj.content === "string" ? obj.content : "";
|
|
1956
|
+
if (size === "small") obj.font_color = "cus-muted";
|
|
1957
|
+
else if (size === "heading" || content.includes("**")) obj.font_color = "cus-accent";
|
|
1958
|
+
}
|
|
1959
|
+
for (const value of Object.values(obj)) applyDefaultFontColors(value);
|
|
1960
|
+
};
|
|
1961
|
+
applyDefaultFontColors(dsl.body);
|
|
1962
|
+
}
|
|
1963
|
+
|
|
1864
1964
|
exports.degradeUnknown = degradeUnknown;
|
|
1865
1965
|
exports.dslToRaw = dslToRaw;
|
|
1866
1966
|
exports.isRawCardEnvelope = isRawCardEnvelope;
|
|
1967
|
+
exports.normalizeStoredCardColors = normalizeStoredCardColors;
|
|
1867
1968
|
exports.rawCardToDsl = rawCardToDsl;
|
|
1868
1969
|
exports.rawToDsl = rawToDsl;
|
package/dist/index.d.ts
CHANGED
|
@@ -8,5 +8,7 @@
|
|
|
8
8
|
*/
|
|
9
9
|
export { dslToRaw } from './dsl-to-raw.js';
|
|
10
10
|
export { rawToDsl, rawCardToDsl, isRawCardEnvelope, degradeUnknown, } from './raw-to-dsl.js';
|
|
11
|
+
export { normalizeStoredCardColors } from './normalize-stored-colors.js';
|
|
12
|
+
export type { CustomColorEntry } from './normalize-stored-colors.js';
|
|
11
13
|
export type { CardElement, ElementProperty, JsonCard } from './types.js';
|
|
12
14
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAC3C,OAAO,EACL,QAAQ,EACR,YAAY,EACZ,iBAAiB,EACjB,cAAc,GACf,MAAM,iBAAiB,CAAC;AACzB,YAAY,EAAE,WAAW,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAC3C,OAAO,EACL,QAAQ,EACR,YAAY,EACZ,iBAAiB,EACjB,cAAc,GACf,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,yBAAyB,EAAE,MAAM,8BAA8B,CAAC;AACzE,YAAY,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AACrE,YAAY,EAAE,WAAW,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1859,4 +1859,104 @@ function degradeUnknown(el) {
|
|
|
1859
1859
|
return { tag: "unknown", raw_tag: rawTag, fallback: el };
|
|
1860
1860
|
}
|
|
1861
1861
|
|
|
1862
|
-
|
|
1862
|
+
// src/normalize-stored-colors.ts
|
|
1863
|
+
function hexColorToRgba(hex) {
|
|
1864
|
+
const h = hex.trim().replace(/^#/, "");
|
|
1865
|
+
if (h.length === 8) {
|
|
1866
|
+
const r = parseInt(h.slice(0, 2), 16);
|
|
1867
|
+
const g = parseInt(h.slice(2, 4), 16);
|
|
1868
|
+
const b = parseInt(h.slice(4, 6), 16);
|
|
1869
|
+
const a = Math.round(parseInt(h.slice(6, 8), 16) / 255 * 100) / 100;
|
|
1870
|
+
return `rgba(${r},${g},${b},${a})`;
|
|
1871
|
+
}
|
|
1872
|
+
if (h.length === 6) {
|
|
1873
|
+
const r = parseInt(h.slice(0, 2), 16);
|
|
1874
|
+
const g = parseInt(h.slice(2, 4), 16);
|
|
1875
|
+
const b = parseInt(h.slice(4, 6), 16);
|
|
1876
|
+
return `rgba(${r},${g},${b},1)`;
|
|
1877
|
+
}
|
|
1878
|
+
return void 0;
|
|
1879
|
+
}
|
|
1880
|
+
function readCustomBackgroundStyle(node) {
|
|
1881
|
+
const raw = node.custom_background_style;
|
|
1882
|
+
if (!raw || typeof raw !== "object") return void 0;
|
|
1883
|
+
const o = raw;
|
|
1884
|
+
const lightRaw = typeof o.light_mode === "string" ? o.light_mode : void 0;
|
|
1885
|
+
const darkRaw = typeof o.dark_mode === "string" ? o.dark_mode : void 0;
|
|
1886
|
+
if (!lightRaw || !darkRaw) return void 0;
|
|
1887
|
+
const light = lightRaw.startsWith("#") ? hexColorToRgba(lightRaw) : lightRaw;
|
|
1888
|
+
const dark = darkRaw.startsWith("#") ? hexColorToRgba(darkRaw) : darkRaw;
|
|
1889
|
+
if (!light || !dark) return void 0;
|
|
1890
|
+
return { light_mode: light, dark_mode: dark };
|
|
1891
|
+
}
|
|
1892
|
+
function normalizeStoredCardColors(dsl) {
|
|
1893
|
+
const colorEntries = {};
|
|
1894
|
+
const styleKey = (entry) => `${entry.light_mode}|${entry.dark_mode}`;
|
|
1895
|
+
const keyToAlias = /* @__PURE__ */ new Map();
|
|
1896
|
+
let bgSeq = 0;
|
|
1897
|
+
const ensureAlias = (prefix, entry) => {
|
|
1898
|
+
const existing2 = keyToAlias.get(styleKey(entry));
|
|
1899
|
+
if (existing2) return existing2;
|
|
1900
|
+
const alias = `${prefix}-${bgSeq++}`;
|
|
1901
|
+
colorEntries[alias] = entry;
|
|
1902
|
+
keyToAlias.set(styleKey(entry), alias);
|
|
1903
|
+
return alias;
|
|
1904
|
+
};
|
|
1905
|
+
const walk = (node) => {
|
|
1906
|
+
if (Array.isArray(node)) {
|
|
1907
|
+
for (const child of node) walk(child);
|
|
1908
|
+
return;
|
|
1909
|
+
}
|
|
1910
|
+
if (!node || typeof node !== "object") return;
|
|
1911
|
+
const obj = node;
|
|
1912
|
+
if (obj.tag === "column") {
|
|
1913
|
+
const custom = readCustomBackgroundStyle(obj);
|
|
1914
|
+
if (custom) {
|
|
1915
|
+
obj.background_style = ensureAlias("cus-bg", custom);
|
|
1916
|
+
delete obj.custom_background_style;
|
|
1917
|
+
}
|
|
1918
|
+
}
|
|
1919
|
+
for (const value of Object.values(obj)) walk(value);
|
|
1920
|
+
};
|
|
1921
|
+
walk(dsl.body);
|
|
1922
|
+
if (Object.keys(colorEntries).length === 0) return;
|
|
1923
|
+
const firstBg = colorEntries["cus-bg-0"] ?? Object.values(colorEntries)[0];
|
|
1924
|
+
if (firstBg) {
|
|
1925
|
+
const m = firstBg.light_mode.match(/^rgba\((\d+),(\d+),(\d+),/);
|
|
1926
|
+
if (m) {
|
|
1927
|
+
colorEntries["cus-accent"] = {
|
|
1928
|
+
light_mode: `rgba(${m[1]},${m[2]},${m[3]},1)`,
|
|
1929
|
+
dark_mode: firstBg.dark_mode.replace(/,\s*[\d.]+\)$/, ",1)")
|
|
1930
|
+
};
|
|
1931
|
+
}
|
|
1932
|
+
}
|
|
1933
|
+
colorEntries["cus-muted"] ??= {
|
|
1934
|
+
light_mode: "rgba(100,106,115,1)",
|
|
1935
|
+
dark_mode: "rgba(166,166,166,1)"
|
|
1936
|
+
};
|
|
1937
|
+
const config = dsl.config && typeof dsl.config === "object" ? dsl.config : {};
|
|
1938
|
+
dsl.config = config;
|
|
1939
|
+
const style = config.style && typeof config.style === "object" ? config.style : {};
|
|
1940
|
+
config.style = style;
|
|
1941
|
+
const existing = style.color && typeof style.color === "object" ? style.color : {};
|
|
1942
|
+
style.color = { ...colorEntries, ...existing };
|
|
1943
|
+
if (!colorEntries["cus-accent"]) return;
|
|
1944
|
+
const applyDefaultFontColors = (node) => {
|
|
1945
|
+
if (Array.isArray(node)) {
|
|
1946
|
+
for (const child of node) applyDefaultFontColors(child);
|
|
1947
|
+
return;
|
|
1948
|
+
}
|
|
1949
|
+
if (!node || typeof node !== "object") return;
|
|
1950
|
+
const obj = node;
|
|
1951
|
+
if (obj.tag === "markdown" && obj.font_color === void 0) {
|
|
1952
|
+
const size = obj.text_size;
|
|
1953
|
+
const content = typeof obj.content === "string" ? obj.content : "";
|
|
1954
|
+
if (size === "small") obj.font_color = "cus-muted";
|
|
1955
|
+
else if (size === "heading" || content.includes("**")) obj.font_color = "cus-accent";
|
|
1956
|
+
}
|
|
1957
|
+
for (const value of Object.values(obj)) applyDefaultFontColors(value);
|
|
1958
|
+
};
|
|
1959
|
+
applyDefaultFontColors(dsl.body);
|
|
1960
|
+
}
|
|
1961
|
+
|
|
1962
|
+
export { degradeUnknown, dslToRaw, isRawCardEnvelope, normalizeStoredCardColors, rawCardToDsl, rawToDsl };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 飞书存储卡片时会将 config.style.color 的 cus-N 展开为 custom_background_style(#RRGGBBAA),
|
|
3
|
+
* 并丢弃 config.style 与 markdown.font_color。回读底稿后须 normalize,否则 modify 再发会丢色。
|
|
4
|
+
*/
|
|
5
|
+
export type CustomColorEntry = {
|
|
6
|
+
light_mode: string;
|
|
7
|
+
dark_mode: string;
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* 将飞书回读的 custom_background_style 还原为可再次发送的 background_style cus-N + config.style.color。
|
|
11
|
+
* 若 markdown 缺少 font_color,按 text_size / 加粗内容补 cus-accent / cus-muted(飞书回读会丢 font_color)。
|
|
12
|
+
*/
|
|
13
|
+
export declare function normalizeStoredCardColors(dsl: Record<string, unknown>): void;
|
|
14
|
+
//# sourceMappingURL=normalize-stored-colors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"normalize-stored-colors.d.ts","sourceRoot":"","sources":["../src/normalize-stored-colors.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,MAAM,gBAAgB,GAAG;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC;AAmCzE;;;GAGG;AACH,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAoF5E"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@open-feishu-card/adapter",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.2",
|
|
4
4
|
"description": "公开 DSL 与飞书内部 RAW JSON 的双向适配器;raw→DSL 对齐 feishu-raw-card-to-dsl",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -21,7 +21,8 @@
|
|
|
21
21
|
"tsup": "^8.3.5",
|
|
22
22
|
"tsx": "^4.19.3",
|
|
23
23
|
"typescript": "^7.0.2",
|
|
24
|
-
"vitest": "^2.1.9"
|
|
24
|
+
"vitest": "^2.1.9",
|
|
25
|
+
"@open-feishu-card/schema": "0.1.4"
|
|
25
26
|
},
|
|
26
27
|
"license": "MIT",
|
|
27
28
|
"publishConfig": {
|