@open-feishu-card/adapter 0.3.3 → 0.3.5
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/custom-colors.d.ts +8 -4
- package/dist/custom-colors.d.ts.map +1 -1
- package/dist/index.cjs +228 -66
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +223 -67
- package/dist/normalize-stored-colors.d.ts +12 -1
- package/dist/normalize-stored-colors.d.ts.map +1 -1
- package/dist/raw-to-dsl.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/custom-colors.d.ts
CHANGED
|
@@ -3,11 +3,10 @@
|
|
|
3
3
|
* customBackgroundStyle / custom_background_style → column backgrounds
|
|
4
4
|
* textStyle.customColor / textStyle.custom_color → inline text color
|
|
5
5
|
*
|
|
6
|
-
* Public DSL
|
|
7
|
-
*
|
|
8
|
-
* `<font color='…'>`. These helpers pick the light-mode value for projection
|
|
9
|
-
* and rendering (dark mode follows Feishu client theme — out of scope here).
|
|
6
|
+
* Public DSL stores custom colors in config.style.color (cus-accent / cus-bg-N …)
|
|
7
|
+
* and references them via <font color> in markdown content / background_style — not inline #hex.
|
|
10
8
|
*/
|
|
9
|
+
import type { CustomColorEntry } from './normalize-stored-colors.js';
|
|
11
10
|
export type ThemeColorPair = {
|
|
12
11
|
light_mode?: string;
|
|
13
12
|
lightMode?: string;
|
|
@@ -15,8 +14,13 @@ export type ThemeColorPair = {
|
|
|
15
14
|
darkMode?: string;
|
|
16
15
|
};
|
|
17
16
|
export declare function readThemeColorLight(pair: unknown): string | undefined;
|
|
17
|
+
export declare function readThemeColorDark(pair: unknown): string | undefined;
|
|
18
|
+
export declare function isCustomHexColor(color: string): boolean;
|
|
18
19
|
/** Enum `color` wins; else fall back to customColor light hex/rgba. */
|
|
19
20
|
export declare function resolveTextStyleColor(textStyle: unknown): string | undefined;
|
|
21
|
+
/** When text color comes from customColor (not enum), return the full light/dark pair. */
|
|
22
|
+
export declare function resolveTextStyleCustomColorPair(textStyle: unknown): ThemeColorPair | undefined;
|
|
23
|
+
export declare function themePairToColorEntry(pair: ThemeColorPair): CustomColorEntry | undefined;
|
|
20
24
|
/** Light hex/rgba from column (or container) custom background, if any. */
|
|
21
25
|
export declare function resolveCustomBackgroundLight(property: unknown): string | undefined;
|
|
22
26
|
//# sourceMappingURL=custom-colors.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"custom-colors.d.ts","sourceRoot":"","sources":["../src/custom-colors.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"custom-colors.d.ts","sourceRoot":"","sources":["../src/custom-colors.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAGrE,MAAM,MAAM,cAAc,GAAG;IAC3B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAOrE;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAOpE;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAGvD;AAED,uEAAuE;AACvE,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAO5E;AAED,0FAA0F;AAC1F,wBAAgB,+BAA+B,CAAC,SAAS,EAAE,OAAO,GAAG,cAAc,GAAG,SAAS,CAQ9F;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,cAAc,GAAG,gBAAgB,GAAG,SAAS,CAQxF;AAED,2EAA2E;AAC3E,wBAAgB,4BAA4B,CAAC,QAAQ,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAKlF"}
|
package/dist/index.cjs
CHANGED
|
@@ -868,31 +868,22 @@ function isRecord(v) {
|
|
|
868
868
|
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
869
869
|
}
|
|
870
870
|
|
|
871
|
-
// src/
|
|
872
|
-
function
|
|
873
|
-
|
|
874
|
-
const o = pair;
|
|
875
|
-
const raw = o.light_mode ?? o.lightMode;
|
|
876
|
-
if (typeof raw !== "string") return void 0;
|
|
877
|
-
const v = raw.trim();
|
|
878
|
-
return v || void 0;
|
|
871
|
+
// src/normalize-stored-colors.ts
|
|
872
|
+
function createColorRegistry() {
|
|
873
|
+
return { entries: {}, keyToAlias: /* @__PURE__ */ new Map(), bgSeq: 0, textSeq: 0 };
|
|
879
874
|
}
|
|
880
|
-
function
|
|
881
|
-
|
|
882
|
-
const ts = textStyle;
|
|
883
|
-
const enumColor = typeof ts.color === "string" ? ts.color.trim() : void 0;
|
|
884
|
-
if (enumColor && enumColor !== "default") return enumColor;
|
|
885
|
-
const custom = ts.custom_color ?? ts.customColor;
|
|
886
|
-
return readThemeColorLight(custom);
|
|
875
|
+
function colorEntryKey(entry) {
|
|
876
|
+
return `${entry.light_mode}|${entry.dark_mode}`;
|
|
887
877
|
}
|
|
888
|
-
function
|
|
889
|
-
|
|
890
|
-
const
|
|
891
|
-
|
|
892
|
-
|
|
878
|
+
function registerColorEntry(registry, entry, prefix) {
|
|
879
|
+
const key = colorEntryKey(entry);
|
|
880
|
+
const existing = registry.keyToAlias.get(key);
|
|
881
|
+
if (existing) return existing;
|
|
882
|
+
const alias = prefix === "cus-bg" ? `cus-bg-${registry.bgSeq++}` : `cus-text-${registry.textSeq++}`;
|
|
883
|
+
registry.entries[alias] = entry;
|
|
884
|
+
registry.keyToAlias.set(key, alias);
|
|
885
|
+
return alias;
|
|
893
886
|
}
|
|
894
|
-
|
|
895
|
-
// src/normalize-stored-colors.ts
|
|
896
887
|
function hexColorToRgba(hex) {
|
|
897
888
|
const h = hex.trim().replace(/^#/, "");
|
|
898
889
|
if (h.length === 8) {
|
|
@@ -922,17 +913,17 @@ function readCustomBackgroundStyle(node) {
|
|
|
922
913
|
if (!light || !dark) return void 0;
|
|
923
914
|
return { light_mode: light, dark_mode: dark };
|
|
924
915
|
}
|
|
925
|
-
function normalizeStoredCardColors(dsl) {
|
|
926
|
-
const colorEntries = {};
|
|
927
|
-
const
|
|
928
|
-
|
|
929
|
-
let
|
|
916
|
+
function normalizeStoredCardColors(dsl, preRegistered) {
|
|
917
|
+
const colorEntries = { ...preRegistered?.entries ?? {} };
|
|
918
|
+
const keyToAlias = new Map(preRegistered?.keyToAlias ?? []);
|
|
919
|
+
let bgSeq = preRegistered?.bgSeq ?? 0;
|
|
920
|
+
let textSeq = preRegistered?.textSeq ?? 0;
|
|
930
921
|
const ensureAlias = (prefix, entry) => {
|
|
931
|
-
const existing2 = keyToAlias.get(
|
|
922
|
+
const existing2 = keyToAlias.get(colorEntryKey(entry));
|
|
932
923
|
if (existing2) return existing2;
|
|
933
|
-
const alias =
|
|
924
|
+
const alias = prefix === "cus-bg" ? `cus-bg-${bgSeq++}` : `cus-text-${textSeq++}`;
|
|
934
925
|
colorEntries[alias] = entry;
|
|
935
|
-
keyToAlias.set(
|
|
926
|
+
keyToAlias.set(colorEntryKey(entry), alias);
|
|
936
927
|
return alias;
|
|
937
928
|
};
|
|
938
929
|
const walk = (node) => {
|
|
@@ -949,11 +940,15 @@ function normalizeStoredCardColors(dsl) {
|
|
|
949
940
|
delete obj.custom_background_style;
|
|
950
941
|
}
|
|
951
942
|
}
|
|
943
|
+
if (obj.tag === "markdown" && typeof obj.content === "string") {
|
|
944
|
+
normalizeMarkdownInlineHexColors(obj, ensureAlias, !!preRegistered);
|
|
945
|
+
}
|
|
952
946
|
for (const value of Object.values(obj)) walk(value);
|
|
953
947
|
};
|
|
954
948
|
walk(dsl.body);
|
|
955
949
|
if (Object.keys(colorEntries).length === 0) return;
|
|
956
|
-
const
|
|
950
|
+
const firstBgKey = Object.keys(colorEntries).find((k) => k.startsWith("cus-bg-"));
|
|
951
|
+
const firstBg = firstBgKey ? colorEntries[firstBgKey] : void 0;
|
|
957
952
|
if (firstBg) {
|
|
958
953
|
const m = firstBg.light_mode.match(/^rgba\((\d+),(\d+),(\d+),/);
|
|
959
954
|
if (m) {
|
|
@@ -967,6 +962,13 @@ function normalizeStoredCardColors(dsl) {
|
|
|
967
962
|
light_mode: "rgba(100,106,115,1)",
|
|
968
963
|
dark_mode: "rgba(166,166,166,1)"
|
|
969
964
|
};
|
|
965
|
+
const aliasRenames = /* @__PURE__ */ new Map();
|
|
966
|
+
for (const to of ["cus-accent", "cus-muted"]) {
|
|
967
|
+
for (const [from, target] of unifyMatchingAlias(colorEntries, "cus-text", to)) {
|
|
968
|
+
aliasRenames.set(from, target);
|
|
969
|
+
}
|
|
970
|
+
}
|
|
971
|
+
remapColorReferences(dsl.body, aliasRenames);
|
|
970
972
|
const config = dsl.config && typeof dsl.config === "object" ? dsl.config : {};
|
|
971
973
|
dsl.config = config;
|
|
972
974
|
const style = config.style && typeof config.style === "object" ? config.style : {};
|
|
@@ -974,22 +976,148 @@ function normalizeStoredCardColors(dsl) {
|
|
|
974
976
|
const existing = style.color && typeof style.color === "object" ? style.color : {};
|
|
975
977
|
style.color = { ...colorEntries, ...existing };
|
|
976
978
|
if (!colorEntries["cus-accent"]) return;
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
979
|
+
if (!preRegistered) {
|
|
980
|
+
const applyDefaultFontColors = (node) => {
|
|
981
|
+
if (Array.isArray(node)) {
|
|
982
|
+
for (const child of node) applyDefaultFontColors(child);
|
|
983
|
+
return;
|
|
984
|
+
}
|
|
985
|
+
if (!node || typeof node !== "object") return;
|
|
986
|
+
const obj = node;
|
|
987
|
+
if (obj.tag === "markdown" && obj.font_color === void 0) {
|
|
988
|
+
const size = obj.text_size;
|
|
989
|
+
const content = typeof obj.content === "string" ? obj.content : "";
|
|
990
|
+
if (size === "small") obj.font_color = "cus-muted";
|
|
991
|
+
else if (size === "heading" || content.includes("**")) obj.font_color = "cus-accent";
|
|
992
|
+
}
|
|
993
|
+
for (const value of Object.values(obj)) applyDefaultFontColors(value);
|
|
994
|
+
};
|
|
995
|
+
applyDefaultFontColors(dsl.body);
|
|
996
|
+
}
|
|
997
|
+
}
|
|
998
|
+
function unifyMatchingAlias(entries, fromPrefix, to) {
|
|
999
|
+
const renames = /* @__PURE__ */ new Map();
|
|
1000
|
+
const target = entries[to];
|
|
1001
|
+
if (!target) return renames;
|
|
1002
|
+
for (const alias of Object.keys(entries)) {
|
|
1003
|
+
if (alias === to) continue;
|
|
1004
|
+
if (!alias.startsWith(`${fromPrefix}-`) && alias !== fromPrefix) continue;
|
|
1005
|
+
const entry = entries[alias];
|
|
1006
|
+
const matches = to === "cus-accent" || to === "cus-muted" ? entry.light_mode === target.light_mode : colorEntryKey(entry) === colorEntryKey(target);
|
|
1007
|
+
if (matches) {
|
|
1008
|
+
renames.set(alias, to);
|
|
1009
|
+
delete entries[alias];
|
|
1010
|
+
}
|
|
1011
|
+
}
|
|
1012
|
+
return renames;
|
|
1013
|
+
}
|
|
1014
|
+
function remapColorReferences(node, aliasRenames) {
|
|
1015
|
+
const remap = (alias) => {
|
|
1016
|
+
if (!alias) return alias;
|
|
1017
|
+
return aliasRenames.get(alias) ?? alias;
|
|
1018
|
+
};
|
|
1019
|
+
const walk = (n) => {
|
|
1020
|
+
if (Array.isArray(n)) {
|
|
1021
|
+
for (const c of n) walk(c);
|
|
980
1022
|
return;
|
|
981
1023
|
}
|
|
982
|
-
if (!
|
|
983
|
-
const obj =
|
|
984
|
-
if (obj.
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
1024
|
+
if (!n || typeof n !== "object") return;
|
|
1025
|
+
const obj = n;
|
|
1026
|
+
if (typeof obj.font_color === "string") obj.font_color = remap(obj.font_color);
|
|
1027
|
+
if (typeof obj.content === "string" && obj.content.includes("<font")) {
|
|
1028
|
+
obj.content = obj.content.replace(
|
|
1029
|
+
/<font color=['"]([^'"]+)['"]>/g,
|
|
1030
|
+
(_m, color) => {
|
|
1031
|
+
const next = remap(color);
|
|
1032
|
+
return next ? `<font color='${next}'>` : _m;
|
|
1033
|
+
}
|
|
1034
|
+
);
|
|
989
1035
|
}
|
|
990
|
-
for (const value of Object.values(obj))
|
|
1036
|
+
for (const value of Object.values(obj)) walk(value);
|
|
991
1037
|
};
|
|
992
|
-
|
|
1038
|
+
walk(node);
|
|
1039
|
+
}
|
|
1040
|
+
function normalizeMarkdownInlineHexColors(obj, ensureAlias, keepFontTags = false) {
|
|
1041
|
+
const content = obj.content;
|
|
1042
|
+
const hexColor = (raw) => {
|
|
1043
|
+
const v = raw.trim();
|
|
1044
|
+
if (v.startsWith("#")) {
|
|
1045
|
+
const rgba = hexColorToRgba(v);
|
|
1046
|
+
return rgba ? { light_mode: rgba, dark_mode: rgba } : void 0;
|
|
1047
|
+
}
|
|
1048
|
+
if (/^rgba?\(/i.test(v)) return { light_mode: v, dark_mode: v };
|
|
1049
|
+
return void 0;
|
|
1050
|
+
};
|
|
1051
|
+
const single = content.match(/^<font color=['"]([^'"]+)['"]\s*>([\s\S]*)<\/font>$/);
|
|
1052
|
+
if (single && !keepFontTags) {
|
|
1053
|
+
const entry = hexColor(single[1]);
|
|
1054
|
+
if (entry) {
|
|
1055
|
+
const alias = ensureAlias("cus-text", entry);
|
|
1056
|
+
if (obj.font_color === void 0) obj.font_color = alias;
|
|
1057
|
+
obj.content = single[2];
|
|
1058
|
+
return;
|
|
1059
|
+
}
|
|
1060
|
+
}
|
|
1061
|
+
obj.content = content.replace(/<font color=['"]([^'"]+)['"]>/g, (match, raw) => {
|
|
1062
|
+
const entry = hexColor(raw);
|
|
1063
|
+
if (!entry) return match;
|
|
1064
|
+
const alias = ensureAlias("cus-text", entry);
|
|
1065
|
+
return `<font color='${alias}'>`;
|
|
1066
|
+
});
|
|
1067
|
+
}
|
|
1068
|
+
|
|
1069
|
+
// src/custom-colors.ts
|
|
1070
|
+
function readThemeColorLight(pair) {
|
|
1071
|
+
if (!pair || typeof pair !== "object") return void 0;
|
|
1072
|
+
const o = pair;
|
|
1073
|
+
const raw = o.light_mode ?? o.lightMode;
|
|
1074
|
+
if (typeof raw !== "string") return void 0;
|
|
1075
|
+
const v = raw.trim();
|
|
1076
|
+
return v || void 0;
|
|
1077
|
+
}
|
|
1078
|
+
function readThemeColorDark(pair) {
|
|
1079
|
+
if (!pair || typeof pair !== "object") return void 0;
|
|
1080
|
+
const o = pair;
|
|
1081
|
+
const raw = o.dark_mode ?? o.darkMode;
|
|
1082
|
+
if (typeof raw !== "string") return void 0;
|
|
1083
|
+
const v = raw.trim();
|
|
1084
|
+
return v || void 0;
|
|
1085
|
+
}
|
|
1086
|
+
function isCustomHexColor(color) {
|
|
1087
|
+
const v = color.trim();
|
|
1088
|
+
return v.startsWith("#") || /^rgba?\(/i.test(v);
|
|
1089
|
+
}
|
|
1090
|
+
function resolveTextStyleColor(textStyle) {
|
|
1091
|
+
if (!textStyle || typeof textStyle !== "object") return void 0;
|
|
1092
|
+
const ts = textStyle;
|
|
1093
|
+
const enumColor = typeof ts.color === "string" ? ts.color.trim() : void 0;
|
|
1094
|
+
if (enumColor && enumColor !== "default") return enumColor;
|
|
1095
|
+
const custom = ts.custom_color ?? ts.customColor;
|
|
1096
|
+
return readThemeColorLight(custom);
|
|
1097
|
+
}
|
|
1098
|
+
function resolveTextStyleCustomColorPair(textStyle) {
|
|
1099
|
+
if (!textStyle || typeof textStyle !== "object") return void 0;
|
|
1100
|
+
const ts = textStyle;
|
|
1101
|
+
const enumColor = typeof ts.color === "string" ? ts.color.trim() : void 0;
|
|
1102
|
+
if (enumColor && enumColor !== "default") return void 0;
|
|
1103
|
+
const custom = ts.custom_color ?? ts.customColor;
|
|
1104
|
+
if (!custom || typeof custom !== "object") return void 0;
|
|
1105
|
+
return custom;
|
|
1106
|
+
}
|
|
1107
|
+
function themePairToColorEntry(pair) {
|
|
1108
|
+
const lightRaw = readThemeColorLight(pair);
|
|
1109
|
+
const darkRaw = readThemeColorDark(pair);
|
|
1110
|
+
if (!lightRaw || !darkRaw) return void 0;
|
|
1111
|
+
const light = lightRaw.startsWith("#") ? hexColorToRgba(lightRaw) : lightRaw;
|
|
1112
|
+
const dark = darkRaw.startsWith("#") ? hexColorToRgba(darkRaw) : darkRaw;
|
|
1113
|
+
if (!light || !dark) return void 0;
|
|
1114
|
+
return { light_mode: light, dark_mode: dark };
|
|
1115
|
+
}
|
|
1116
|
+
function resolveCustomBackgroundLight(property) {
|
|
1117
|
+
if (!property || typeof property !== "object") return void 0;
|
|
1118
|
+
const p = property;
|
|
1119
|
+
const custom = p.custom_background_style ?? p.customBackgroundStyle;
|
|
1120
|
+
return readThemeColorLight(custom);
|
|
993
1121
|
}
|
|
994
1122
|
|
|
995
1123
|
// src/raw-to-dsl.ts
|
|
@@ -1007,12 +1135,19 @@ function rawCardToDsl(envelope) {
|
|
|
1007
1135
|
} catch {
|
|
1008
1136
|
return envelope;
|
|
1009
1137
|
}
|
|
1010
|
-
const ctx = {
|
|
1138
|
+
const ctx = makeCtx({
|
|
1011
1139
|
images: env.json_attachment?.images ?? {},
|
|
1012
1140
|
atUsers: env.json_attachment?.at_users ?? {}
|
|
1013
|
-
};
|
|
1141
|
+
});
|
|
1014
1142
|
return convertRoot(inner, ctx);
|
|
1015
1143
|
}
|
|
1144
|
+
function makeCtx(partial) {
|
|
1145
|
+
return {
|
|
1146
|
+
images: partial?.images ?? {},
|
|
1147
|
+
atUsers: partial?.atUsers ?? {},
|
|
1148
|
+
colors: createColorRegistry()
|
|
1149
|
+
};
|
|
1150
|
+
}
|
|
1016
1151
|
var RAW_ONLY_FIELDS = /* @__PURE__ */ new Set([
|
|
1017
1152
|
"new_body",
|
|
1018
1153
|
"source",
|
|
@@ -1100,7 +1235,7 @@ function convertRoot(root, ctx) {
|
|
|
1100
1235
|
out.config = convertConfig(isRecord2(root.config) ? root.config : {});
|
|
1101
1236
|
if (isRecord2(root.body)) out.body = convertBody2(root.body, ctx);
|
|
1102
1237
|
if (isRecord2(root.header)) out.header = convertHeader2(root.header, ctx);
|
|
1103
|
-
normalizeStoredCardColors(out);
|
|
1238
|
+
normalizeStoredCardColors(out, ctx.colors);
|
|
1104
1239
|
return out;
|
|
1105
1240
|
}
|
|
1106
1241
|
function convertConfig(_node) {
|
|
@@ -1202,7 +1337,7 @@ function unwrap(node, ctx) {
|
|
|
1202
1337
|
let value = isRecord2(cell) && "data" in cell ? cell.data : cell;
|
|
1203
1338
|
if (isRecord2(value) && value.tag === "markdown" && isRecord2(value.property)) {
|
|
1204
1339
|
const elements = Array.isArray(value.property.elements) ? value.property.elements : [];
|
|
1205
|
-
value = renderChildren(elements, ctx);
|
|
1340
|
+
value = renderChildren(elements, ctx).content;
|
|
1206
1341
|
}
|
|
1207
1342
|
r[k] = value;
|
|
1208
1343
|
}
|
|
@@ -1577,7 +1712,7 @@ function resolveAtUserId(prop, ctx) {
|
|
|
1577
1712
|
function rebuildMarkdown(property, ctx) {
|
|
1578
1713
|
const out = { tag: "markdown" };
|
|
1579
1714
|
const elements = Array.isArray(property.elements) ? property.elements : [];
|
|
1580
|
-
const content = renderChildren(elements, ctx);
|
|
1715
|
+
const { content } = renderChildren(elements, ctx);
|
|
1581
1716
|
if (content) out.content = content;
|
|
1582
1717
|
for (const [rawKey, rawValue] of Object.entries(property)) {
|
|
1583
1718
|
if (rawKey === "elements" || rawKey === "markdownElements" || rawKey === "originTag") continue;
|
|
@@ -1607,6 +1742,28 @@ function wrapEmphasis(text, bold, color) {
|
|
|
1607
1742
|
if (color) wrapped = `<font color='${color}'>${wrapped}</font>`;
|
|
1608
1743
|
return lead + wrapped + trail;
|
|
1609
1744
|
}
|
|
1745
|
+
function resolveInlineStyle(ts, ctx) {
|
|
1746
|
+
const bold = !!(ts && Array.isArray(ts.attributes) && ts.attributes.includes("bold"));
|
|
1747
|
+
const customPair = resolveTextStyleCustomColorPair(ts);
|
|
1748
|
+
if (customPair) {
|
|
1749
|
+
const entry = themePairToColorEntry(customPair);
|
|
1750
|
+
if (entry) {
|
|
1751
|
+
const alias = registerColorEntry(ctx.colors, entry, "cus-text");
|
|
1752
|
+
return { bold, color: alias, colorKind: "custom" };
|
|
1753
|
+
}
|
|
1754
|
+
}
|
|
1755
|
+
const rawColor = resolveTextStyleColor(ts);
|
|
1756
|
+
const color = rawColor === "default" ? void 0 : rawColor;
|
|
1757
|
+
if (!color) return { bold };
|
|
1758
|
+
if (isCustomHexColor(color)) {
|
|
1759
|
+
const rgba = color.startsWith("#") ? themePairToColorEntry({ lightMode: color, darkMode: color }) : { light_mode: color, dark_mode: color };
|
|
1760
|
+
if (rgba) {
|
|
1761
|
+
const alias = registerColorEntry(ctx.colors, rgba, "cus-text");
|
|
1762
|
+
return { bold, color: alias, colorKind: "custom" };
|
|
1763
|
+
}
|
|
1764
|
+
}
|
|
1765
|
+
return { bold, color, colorKind: "enum" };
|
|
1766
|
+
}
|
|
1610
1767
|
function renderChildren(children, ctx) {
|
|
1611
1768
|
let out = "";
|
|
1612
1769
|
let buffer = [];
|
|
@@ -1626,8 +1783,9 @@ function renderChildren(children, ctx) {
|
|
|
1626
1783
|
continue;
|
|
1627
1784
|
}
|
|
1628
1785
|
const head = group[0];
|
|
1629
|
-
if (head.bold === seg.bold && head.color === seg.color
|
|
1630
|
-
|
|
1786
|
+
if (head.bold === seg.bold && head.color === seg.color && head.colorKind === seg.colorKind) {
|
|
1787
|
+
group.push(seg);
|
|
1788
|
+
} else {
|
|
1631
1789
|
emitGroup();
|
|
1632
1790
|
group.push(seg);
|
|
1633
1791
|
}
|
|
@@ -1646,33 +1804,33 @@ function renderChildren(children, ctx) {
|
|
|
1646
1804
|
out += childToMarkdown(child, ctx);
|
|
1647
1805
|
}
|
|
1648
1806
|
flushBuffer();
|
|
1649
|
-
return out;
|
|
1807
|
+
return { content: out };
|
|
1650
1808
|
}
|
|
1651
1809
|
function childToInlineSegment(child, ctx) {
|
|
1652
1810
|
const tag = child.tag;
|
|
1653
1811
|
const prop = isRecord2(child.property) ? child.property : {};
|
|
1654
1812
|
const ts = isRecord2(prop.textStyle) ? prop.textStyle : void 0;
|
|
1655
|
-
const bold
|
|
1656
|
-
const rawColor = resolveTextStyleColor(ts);
|
|
1657
|
-
const color = rawColor === "default" ? void 0 : rawColor;
|
|
1813
|
+
const { bold, color, colorKind } = resolveInlineStyle(ts, ctx);
|
|
1658
1814
|
switch (tag) {
|
|
1659
1815
|
case "plain_text":
|
|
1660
1816
|
return {
|
|
1661
1817
|
content: typeof prop.content === "string" ? prop.content : "",
|
|
1662
1818
|
bold,
|
|
1663
|
-
color
|
|
1819
|
+
color,
|
|
1820
|
+
colorKind
|
|
1664
1821
|
};
|
|
1665
1822
|
case "code_span":
|
|
1666
1823
|
return {
|
|
1667
1824
|
content: `\`${typeof prop.content === "string" ? prop.content : ""}\``,
|
|
1668
1825
|
bold,
|
|
1669
|
-
color
|
|
1826
|
+
color,
|
|
1827
|
+
colorKind
|
|
1670
1828
|
};
|
|
1671
1829
|
case "link": {
|
|
1672
1830
|
const text = typeof prop.content === "string" ? prop.content : "";
|
|
1673
1831
|
const urlObj = isRecord2(prop.url) ? prop.url : void 0;
|
|
1674
1832
|
const url = urlObj && typeof urlObj.url === "string" ? urlObj.url : "";
|
|
1675
|
-
return { content: `[${text}](${url})`, bold, color };
|
|
1833
|
+
return { content: `[${text}](${url})`, bold, color, colorKind };
|
|
1676
1834
|
}
|
|
1677
1835
|
case "at_all":
|
|
1678
1836
|
return { content: "<at id=all></at>", bold, color };
|
|
@@ -1712,10 +1870,8 @@ function childToMarkdown(child, ctx) {
|
|
|
1712
1870
|
case "plain_text": {
|
|
1713
1871
|
const content = typeof prop.content === "string" ? prop.content : "";
|
|
1714
1872
|
const ts = isRecord2(prop.textStyle) ? prop.textStyle : void 0;
|
|
1715
|
-
const
|
|
1716
|
-
|
|
1717
|
-
const attrs = ts && Array.isArray(ts.attributes) ? ts.attributes : [];
|
|
1718
|
-
return wrapEmphasis(content, attrs.includes("bold"), color);
|
|
1873
|
+
const { bold, color } = resolveInlineStyle(ts, ctx);
|
|
1874
|
+
return wrapEmphasis(content, bold, color);
|
|
1719
1875
|
}
|
|
1720
1876
|
case "br":
|
|
1721
1877
|
return "\n";
|
|
@@ -1841,7 +1997,7 @@ ${"#".repeat(level)} ${body}
|
|
|
1841
1997
|
if (!data || data.tag !== "markdown") return "";
|
|
1842
1998
|
const cellProp = isRecord2(data.property) ? data.property : {};
|
|
1843
1999
|
const inner = Array.isArray(cellProp.elements) ? cellProp.elements : [];
|
|
1844
|
-
const text = renderChildren(inner, ctx);
|
|
2000
|
+
const { content: text } = renderChildren(inner, ctx);
|
|
1845
2001
|
return text.replace(/\|/g, "\\|").replace(/\n/g, " ");
|
|
1846
2002
|
});
|
|
1847
2003
|
return `| ${cells.join(" | ")} |`;
|
|
@@ -1964,10 +2120,10 @@ function rawToDsl(raw) {
|
|
|
1964
2120
|
}
|
|
1965
2121
|
}
|
|
1966
2122
|
const attachment = isRecord2(raw.json_attachment) ? raw.json_attachment : {};
|
|
1967
|
-
const ctx = {
|
|
2123
|
+
const ctx = makeCtx({
|
|
1968
2124
|
images: isRecord2(attachment.images) ? attachment.images : {},
|
|
1969
2125
|
atUsers: isRecord2(attachment.at_users) ? attachment.at_users : {}
|
|
1970
|
-
};
|
|
2126
|
+
});
|
|
1971
2127
|
return convertRoot(inner, ctx);
|
|
1972
2128
|
}
|
|
1973
2129
|
if (isRecord2(raw.card)) {
|
|
@@ -1975,10 +2131,10 @@ function rawToDsl(raw) {
|
|
|
1975
2131
|
if (typeof card.json_card === "string" || isRecord2(card.json_card)) {
|
|
1976
2132
|
return rawToDsl(card);
|
|
1977
2133
|
}
|
|
1978
|
-
return convertRoot(card,
|
|
2134
|
+
return convertRoot(card, makeCtx());
|
|
1979
2135
|
}
|
|
1980
2136
|
if ("body" in raw || "header" in raw || "schema" in raw) {
|
|
1981
|
-
return convertRoot(raw,
|
|
2137
|
+
return convertRoot(raw, makeCtx());
|
|
1982
2138
|
}
|
|
1983
2139
|
return raw;
|
|
1984
2140
|
}
|
|
@@ -1987,12 +2143,18 @@ function degradeUnknown(el) {
|
|
|
1987
2143
|
return { tag: "unknown", raw_tag: rawTag, fallback: el };
|
|
1988
2144
|
}
|
|
1989
2145
|
|
|
2146
|
+
exports.createColorRegistry = createColorRegistry;
|
|
1990
2147
|
exports.degradeUnknown = degradeUnknown;
|
|
1991
2148
|
exports.dslToRaw = dslToRaw;
|
|
2149
|
+
exports.isCustomHexColor = isCustomHexColor;
|
|
1992
2150
|
exports.isRawCardEnvelope = isRawCardEnvelope;
|
|
1993
2151
|
exports.normalizeStoredCardColors = normalizeStoredCardColors;
|
|
1994
2152
|
exports.rawCardToDsl = rawCardToDsl;
|
|
1995
2153
|
exports.rawToDsl = rawToDsl;
|
|
2154
|
+
exports.readThemeColorDark = readThemeColorDark;
|
|
1996
2155
|
exports.readThemeColorLight = readThemeColorLight;
|
|
2156
|
+
exports.registerColorEntry = registerColorEntry;
|
|
1997
2157
|
exports.resolveCustomBackgroundLight = resolveCustomBackgroundLight;
|
|
1998
2158
|
exports.resolveTextStyleColor = resolveTextStyleColor;
|
|
2159
|
+
exports.resolveTextStyleCustomColorPair = resolveTextStyleCustomColorPair;
|
|
2160
|
+
exports.themePairToColorEntry = themePairToColorEntry;
|
package/dist/index.d.ts
CHANGED
|
@@ -8,9 +8,9 @@
|
|
|
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';
|
|
11
|
+
export { normalizeStoredCardColors, createColorRegistry, registerColorEntry } from './normalize-stored-colors.js';
|
|
12
12
|
export type { CustomColorEntry } from './normalize-stored-colors.js';
|
|
13
|
-
export { readThemeColorLight, resolveCustomBackgroundLight, resolveTextStyleColor, } from './custom-colors.js';
|
|
13
|
+
export { readThemeColorLight, readThemeColorDark, resolveCustomBackgroundLight, resolveTextStyleColor, resolveTextStyleCustomColorPair, themePairToColorEntry, isCustomHexColor, } from './custom-colors.js';
|
|
14
14
|
export type { ThemeColorPair } from './custom-colors.js';
|
|
15
15
|
export type { CardElement, ElementProperty, JsonCard } from './types.js';
|
|
16
16
|
//# 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,OAAO,EAAE,yBAAyB,EAAE,MAAM,8BAA8B,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,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AAClH,YAAY,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AACrE,OAAO,EACL,mBAAmB,EACnB,kBAAkB,EAClB,4BAA4B,EAC5B,qBAAqB,EACrB,+BAA+B,EAC/B,qBAAqB,EACrB,gBAAgB,GACjB,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACzD,YAAY,EAAE,WAAW,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -866,31 +866,22 @@ function isRecord(v) {
|
|
|
866
866
|
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
867
867
|
}
|
|
868
868
|
|
|
869
|
-
// src/
|
|
870
|
-
function
|
|
871
|
-
|
|
872
|
-
const o = pair;
|
|
873
|
-
const raw = o.light_mode ?? o.lightMode;
|
|
874
|
-
if (typeof raw !== "string") return void 0;
|
|
875
|
-
const v = raw.trim();
|
|
876
|
-
return v || void 0;
|
|
869
|
+
// src/normalize-stored-colors.ts
|
|
870
|
+
function createColorRegistry() {
|
|
871
|
+
return { entries: {}, keyToAlias: /* @__PURE__ */ new Map(), bgSeq: 0, textSeq: 0 };
|
|
877
872
|
}
|
|
878
|
-
function
|
|
879
|
-
|
|
880
|
-
const ts = textStyle;
|
|
881
|
-
const enumColor = typeof ts.color === "string" ? ts.color.trim() : void 0;
|
|
882
|
-
if (enumColor && enumColor !== "default") return enumColor;
|
|
883
|
-
const custom = ts.custom_color ?? ts.customColor;
|
|
884
|
-
return readThemeColorLight(custom);
|
|
873
|
+
function colorEntryKey(entry) {
|
|
874
|
+
return `${entry.light_mode}|${entry.dark_mode}`;
|
|
885
875
|
}
|
|
886
|
-
function
|
|
887
|
-
|
|
888
|
-
const
|
|
889
|
-
|
|
890
|
-
|
|
876
|
+
function registerColorEntry(registry, entry, prefix) {
|
|
877
|
+
const key = colorEntryKey(entry);
|
|
878
|
+
const existing = registry.keyToAlias.get(key);
|
|
879
|
+
if (existing) return existing;
|
|
880
|
+
const alias = prefix === "cus-bg" ? `cus-bg-${registry.bgSeq++}` : `cus-text-${registry.textSeq++}`;
|
|
881
|
+
registry.entries[alias] = entry;
|
|
882
|
+
registry.keyToAlias.set(key, alias);
|
|
883
|
+
return alias;
|
|
891
884
|
}
|
|
892
|
-
|
|
893
|
-
// src/normalize-stored-colors.ts
|
|
894
885
|
function hexColorToRgba(hex) {
|
|
895
886
|
const h = hex.trim().replace(/^#/, "");
|
|
896
887
|
if (h.length === 8) {
|
|
@@ -920,17 +911,17 @@ function readCustomBackgroundStyle(node) {
|
|
|
920
911
|
if (!light || !dark) return void 0;
|
|
921
912
|
return { light_mode: light, dark_mode: dark };
|
|
922
913
|
}
|
|
923
|
-
function normalizeStoredCardColors(dsl) {
|
|
924
|
-
const colorEntries = {};
|
|
925
|
-
const
|
|
926
|
-
|
|
927
|
-
let
|
|
914
|
+
function normalizeStoredCardColors(dsl, preRegistered) {
|
|
915
|
+
const colorEntries = { ...preRegistered?.entries ?? {} };
|
|
916
|
+
const keyToAlias = new Map(preRegistered?.keyToAlias ?? []);
|
|
917
|
+
let bgSeq = preRegistered?.bgSeq ?? 0;
|
|
918
|
+
let textSeq = preRegistered?.textSeq ?? 0;
|
|
928
919
|
const ensureAlias = (prefix, entry) => {
|
|
929
|
-
const existing2 = keyToAlias.get(
|
|
920
|
+
const existing2 = keyToAlias.get(colorEntryKey(entry));
|
|
930
921
|
if (existing2) return existing2;
|
|
931
|
-
const alias =
|
|
922
|
+
const alias = prefix === "cus-bg" ? `cus-bg-${bgSeq++}` : `cus-text-${textSeq++}`;
|
|
932
923
|
colorEntries[alias] = entry;
|
|
933
|
-
keyToAlias.set(
|
|
924
|
+
keyToAlias.set(colorEntryKey(entry), alias);
|
|
934
925
|
return alias;
|
|
935
926
|
};
|
|
936
927
|
const walk = (node) => {
|
|
@@ -947,11 +938,15 @@ function normalizeStoredCardColors(dsl) {
|
|
|
947
938
|
delete obj.custom_background_style;
|
|
948
939
|
}
|
|
949
940
|
}
|
|
941
|
+
if (obj.tag === "markdown" && typeof obj.content === "string") {
|
|
942
|
+
normalizeMarkdownInlineHexColors(obj, ensureAlias, !!preRegistered);
|
|
943
|
+
}
|
|
950
944
|
for (const value of Object.values(obj)) walk(value);
|
|
951
945
|
};
|
|
952
946
|
walk(dsl.body);
|
|
953
947
|
if (Object.keys(colorEntries).length === 0) return;
|
|
954
|
-
const
|
|
948
|
+
const firstBgKey = Object.keys(colorEntries).find((k) => k.startsWith("cus-bg-"));
|
|
949
|
+
const firstBg = firstBgKey ? colorEntries[firstBgKey] : void 0;
|
|
955
950
|
if (firstBg) {
|
|
956
951
|
const m = firstBg.light_mode.match(/^rgba\((\d+),(\d+),(\d+),/);
|
|
957
952
|
if (m) {
|
|
@@ -965,6 +960,13 @@ function normalizeStoredCardColors(dsl) {
|
|
|
965
960
|
light_mode: "rgba(100,106,115,1)",
|
|
966
961
|
dark_mode: "rgba(166,166,166,1)"
|
|
967
962
|
};
|
|
963
|
+
const aliasRenames = /* @__PURE__ */ new Map();
|
|
964
|
+
for (const to of ["cus-accent", "cus-muted"]) {
|
|
965
|
+
for (const [from, target] of unifyMatchingAlias(colorEntries, "cus-text", to)) {
|
|
966
|
+
aliasRenames.set(from, target);
|
|
967
|
+
}
|
|
968
|
+
}
|
|
969
|
+
remapColorReferences(dsl.body, aliasRenames);
|
|
968
970
|
const config = dsl.config && typeof dsl.config === "object" ? dsl.config : {};
|
|
969
971
|
dsl.config = config;
|
|
970
972
|
const style = config.style && typeof config.style === "object" ? config.style : {};
|
|
@@ -972,22 +974,148 @@ function normalizeStoredCardColors(dsl) {
|
|
|
972
974
|
const existing = style.color && typeof style.color === "object" ? style.color : {};
|
|
973
975
|
style.color = { ...colorEntries, ...existing };
|
|
974
976
|
if (!colorEntries["cus-accent"]) return;
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
977
|
+
if (!preRegistered) {
|
|
978
|
+
const applyDefaultFontColors = (node) => {
|
|
979
|
+
if (Array.isArray(node)) {
|
|
980
|
+
for (const child of node) applyDefaultFontColors(child);
|
|
981
|
+
return;
|
|
982
|
+
}
|
|
983
|
+
if (!node || typeof node !== "object") return;
|
|
984
|
+
const obj = node;
|
|
985
|
+
if (obj.tag === "markdown" && obj.font_color === void 0) {
|
|
986
|
+
const size = obj.text_size;
|
|
987
|
+
const content = typeof obj.content === "string" ? obj.content : "";
|
|
988
|
+
if (size === "small") obj.font_color = "cus-muted";
|
|
989
|
+
else if (size === "heading" || content.includes("**")) obj.font_color = "cus-accent";
|
|
990
|
+
}
|
|
991
|
+
for (const value of Object.values(obj)) applyDefaultFontColors(value);
|
|
992
|
+
};
|
|
993
|
+
applyDefaultFontColors(dsl.body);
|
|
994
|
+
}
|
|
995
|
+
}
|
|
996
|
+
function unifyMatchingAlias(entries, fromPrefix, to) {
|
|
997
|
+
const renames = /* @__PURE__ */ new Map();
|
|
998
|
+
const target = entries[to];
|
|
999
|
+
if (!target) return renames;
|
|
1000
|
+
for (const alias of Object.keys(entries)) {
|
|
1001
|
+
if (alias === to) continue;
|
|
1002
|
+
if (!alias.startsWith(`${fromPrefix}-`) && alias !== fromPrefix) continue;
|
|
1003
|
+
const entry = entries[alias];
|
|
1004
|
+
const matches = to === "cus-accent" || to === "cus-muted" ? entry.light_mode === target.light_mode : colorEntryKey(entry) === colorEntryKey(target);
|
|
1005
|
+
if (matches) {
|
|
1006
|
+
renames.set(alias, to);
|
|
1007
|
+
delete entries[alias];
|
|
1008
|
+
}
|
|
1009
|
+
}
|
|
1010
|
+
return renames;
|
|
1011
|
+
}
|
|
1012
|
+
function remapColorReferences(node, aliasRenames) {
|
|
1013
|
+
const remap = (alias) => {
|
|
1014
|
+
if (!alias) return alias;
|
|
1015
|
+
return aliasRenames.get(alias) ?? alias;
|
|
1016
|
+
};
|
|
1017
|
+
const walk = (n) => {
|
|
1018
|
+
if (Array.isArray(n)) {
|
|
1019
|
+
for (const c of n) walk(c);
|
|
978
1020
|
return;
|
|
979
1021
|
}
|
|
980
|
-
if (!
|
|
981
|
-
const obj =
|
|
982
|
-
if (obj.
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
1022
|
+
if (!n || typeof n !== "object") return;
|
|
1023
|
+
const obj = n;
|
|
1024
|
+
if (typeof obj.font_color === "string") obj.font_color = remap(obj.font_color);
|
|
1025
|
+
if (typeof obj.content === "string" && obj.content.includes("<font")) {
|
|
1026
|
+
obj.content = obj.content.replace(
|
|
1027
|
+
/<font color=['"]([^'"]+)['"]>/g,
|
|
1028
|
+
(_m, color) => {
|
|
1029
|
+
const next = remap(color);
|
|
1030
|
+
return next ? `<font color='${next}'>` : _m;
|
|
1031
|
+
}
|
|
1032
|
+
);
|
|
987
1033
|
}
|
|
988
|
-
for (const value of Object.values(obj))
|
|
1034
|
+
for (const value of Object.values(obj)) walk(value);
|
|
989
1035
|
};
|
|
990
|
-
|
|
1036
|
+
walk(node);
|
|
1037
|
+
}
|
|
1038
|
+
function normalizeMarkdownInlineHexColors(obj, ensureAlias, keepFontTags = false) {
|
|
1039
|
+
const content = obj.content;
|
|
1040
|
+
const hexColor = (raw) => {
|
|
1041
|
+
const v = raw.trim();
|
|
1042
|
+
if (v.startsWith("#")) {
|
|
1043
|
+
const rgba = hexColorToRgba(v);
|
|
1044
|
+
return rgba ? { light_mode: rgba, dark_mode: rgba } : void 0;
|
|
1045
|
+
}
|
|
1046
|
+
if (/^rgba?\(/i.test(v)) return { light_mode: v, dark_mode: v };
|
|
1047
|
+
return void 0;
|
|
1048
|
+
};
|
|
1049
|
+
const single = content.match(/^<font color=['"]([^'"]+)['"]\s*>([\s\S]*)<\/font>$/);
|
|
1050
|
+
if (single && !keepFontTags) {
|
|
1051
|
+
const entry = hexColor(single[1]);
|
|
1052
|
+
if (entry) {
|
|
1053
|
+
const alias = ensureAlias("cus-text", entry);
|
|
1054
|
+
if (obj.font_color === void 0) obj.font_color = alias;
|
|
1055
|
+
obj.content = single[2];
|
|
1056
|
+
return;
|
|
1057
|
+
}
|
|
1058
|
+
}
|
|
1059
|
+
obj.content = content.replace(/<font color=['"]([^'"]+)['"]>/g, (match, raw) => {
|
|
1060
|
+
const entry = hexColor(raw);
|
|
1061
|
+
if (!entry) return match;
|
|
1062
|
+
const alias = ensureAlias("cus-text", entry);
|
|
1063
|
+
return `<font color='${alias}'>`;
|
|
1064
|
+
});
|
|
1065
|
+
}
|
|
1066
|
+
|
|
1067
|
+
// src/custom-colors.ts
|
|
1068
|
+
function readThemeColorLight(pair) {
|
|
1069
|
+
if (!pair || typeof pair !== "object") return void 0;
|
|
1070
|
+
const o = pair;
|
|
1071
|
+
const raw = o.light_mode ?? o.lightMode;
|
|
1072
|
+
if (typeof raw !== "string") return void 0;
|
|
1073
|
+
const v = raw.trim();
|
|
1074
|
+
return v || void 0;
|
|
1075
|
+
}
|
|
1076
|
+
function readThemeColorDark(pair) {
|
|
1077
|
+
if (!pair || typeof pair !== "object") return void 0;
|
|
1078
|
+
const o = pair;
|
|
1079
|
+
const raw = o.dark_mode ?? o.darkMode;
|
|
1080
|
+
if (typeof raw !== "string") return void 0;
|
|
1081
|
+
const v = raw.trim();
|
|
1082
|
+
return v || void 0;
|
|
1083
|
+
}
|
|
1084
|
+
function isCustomHexColor(color) {
|
|
1085
|
+
const v = color.trim();
|
|
1086
|
+
return v.startsWith("#") || /^rgba?\(/i.test(v);
|
|
1087
|
+
}
|
|
1088
|
+
function resolveTextStyleColor(textStyle) {
|
|
1089
|
+
if (!textStyle || typeof textStyle !== "object") return void 0;
|
|
1090
|
+
const ts = textStyle;
|
|
1091
|
+
const enumColor = typeof ts.color === "string" ? ts.color.trim() : void 0;
|
|
1092
|
+
if (enumColor && enumColor !== "default") return enumColor;
|
|
1093
|
+
const custom = ts.custom_color ?? ts.customColor;
|
|
1094
|
+
return readThemeColorLight(custom);
|
|
1095
|
+
}
|
|
1096
|
+
function resolveTextStyleCustomColorPair(textStyle) {
|
|
1097
|
+
if (!textStyle || typeof textStyle !== "object") return void 0;
|
|
1098
|
+
const ts = textStyle;
|
|
1099
|
+
const enumColor = typeof ts.color === "string" ? ts.color.trim() : void 0;
|
|
1100
|
+
if (enumColor && enumColor !== "default") return void 0;
|
|
1101
|
+
const custom = ts.custom_color ?? ts.customColor;
|
|
1102
|
+
if (!custom || typeof custom !== "object") return void 0;
|
|
1103
|
+
return custom;
|
|
1104
|
+
}
|
|
1105
|
+
function themePairToColorEntry(pair) {
|
|
1106
|
+
const lightRaw = readThemeColorLight(pair);
|
|
1107
|
+
const darkRaw = readThemeColorDark(pair);
|
|
1108
|
+
if (!lightRaw || !darkRaw) return void 0;
|
|
1109
|
+
const light = lightRaw.startsWith("#") ? hexColorToRgba(lightRaw) : lightRaw;
|
|
1110
|
+
const dark = darkRaw.startsWith("#") ? hexColorToRgba(darkRaw) : darkRaw;
|
|
1111
|
+
if (!light || !dark) return void 0;
|
|
1112
|
+
return { light_mode: light, dark_mode: dark };
|
|
1113
|
+
}
|
|
1114
|
+
function resolveCustomBackgroundLight(property) {
|
|
1115
|
+
if (!property || typeof property !== "object") return void 0;
|
|
1116
|
+
const p = property;
|
|
1117
|
+
const custom = p.custom_background_style ?? p.customBackgroundStyle;
|
|
1118
|
+
return readThemeColorLight(custom);
|
|
991
1119
|
}
|
|
992
1120
|
|
|
993
1121
|
// src/raw-to-dsl.ts
|
|
@@ -1005,12 +1133,19 @@ function rawCardToDsl(envelope) {
|
|
|
1005
1133
|
} catch {
|
|
1006
1134
|
return envelope;
|
|
1007
1135
|
}
|
|
1008
|
-
const ctx = {
|
|
1136
|
+
const ctx = makeCtx({
|
|
1009
1137
|
images: env.json_attachment?.images ?? {},
|
|
1010
1138
|
atUsers: env.json_attachment?.at_users ?? {}
|
|
1011
|
-
};
|
|
1139
|
+
});
|
|
1012
1140
|
return convertRoot(inner, ctx);
|
|
1013
1141
|
}
|
|
1142
|
+
function makeCtx(partial) {
|
|
1143
|
+
return {
|
|
1144
|
+
images: partial?.images ?? {},
|
|
1145
|
+
atUsers: partial?.atUsers ?? {},
|
|
1146
|
+
colors: createColorRegistry()
|
|
1147
|
+
};
|
|
1148
|
+
}
|
|
1014
1149
|
var RAW_ONLY_FIELDS = /* @__PURE__ */ new Set([
|
|
1015
1150
|
"new_body",
|
|
1016
1151
|
"source",
|
|
@@ -1098,7 +1233,7 @@ function convertRoot(root, ctx) {
|
|
|
1098
1233
|
out.config = convertConfig(isRecord2(root.config) ? root.config : {});
|
|
1099
1234
|
if (isRecord2(root.body)) out.body = convertBody2(root.body, ctx);
|
|
1100
1235
|
if (isRecord2(root.header)) out.header = convertHeader2(root.header, ctx);
|
|
1101
|
-
normalizeStoredCardColors(out);
|
|
1236
|
+
normalizeStoredCardColors(out, ctx.colors);
|
|
1102
1237
|
return out;
|
|
1103
1238
|
}
|
|
1104
1239
|
function convertConfig(_node) {
|
|
@@ -1200,7 +1335,7 @@ function unwrap(node, ctx) {
|
|
|
1200
1335
|
let value = isRecord2(cell) && "data" in cell ? cell.data : cell;
|
|
1201
1336
|
if (isRecord2(value) && value.tag === "markdown" && isRecord2(value.property)) {
|
|
1202
1337
|
const elements = Array.isArray(value.property.elements) ? value.property.elements : [];
|
|
1203
|
-
value = renderChildren(elements, ctx);
|
|
1338
|
+
value = renderChildren(elements, ctx).content;
|
|
1204
1339
|
}
|
|
1205
1340
|
r[k] = value;
|
|
1206
1341
|
}
|
|
@@ -1575,7 +1710,7 @@ function resolveAtUserId(prop, ctx) {
|
|
|
1575
1710
|
function rebuildMarkdown(property, ctx) {
|
|
1576
1711
|
const out = { tag: "markdown" };
|
|
1577
1712
|
const elements = Array.isArray(property.elements) ? property.elements : [];
|
|
1578
|
-
const content = renderChildren(elements, ctx);
|
|
1713
|
+
const { content } = renderChildren(elements, ctx);
|
|
1579
1714
|
if (content) out.content = content;
|
|
1580
1715
|
for (const [rawKey, rawValue] of Object.entries(property)) {
|
|
1581
1716
|
if (rawKey === "elements" || rawKey === "markdownElements" || rawKey === "originTag") continue;
|
|
@@ -1605,6 +1740,28 @@ function wrapEmphasis(text, bold, color) {
|
|
|
1605
1740
|
if (color) wrapped = `<font color='${color}'>${wrapped}</font>`;
|
|
1606
1741
|
return lead + wrapped + trail;
|
|
1607
1742
|
}
|
|
1743
|
+
function resolveInlineStyle(ts, ctx) {
|
|
1744
|
+
const bold = !!(ts && Array.isArray(ts.attributes) && ts.attributes.includes("bold"));
|
|
1745
|
+
const customPair = resolveTextStyleCustomColorPair(ts);
|
|
1746
|
+
if (customPair) {
|
|
1747
|
+
const entry = themePairToColorEntry(customPair);
|
|
1748
|
+
if (entry) {
|
|
1749
|
+
const alias = registerColorEntry(ctx.colors, entry, "cus-text");
|
|
1750
|
+
return { bold, color: alias, colorKind: "custom" };
|
|
1751
|
+
}
|
|
1752
|
+
}
|
|
1753
|
+
const rawColor = resolveTextStyleColor(ts);
|
|
1754
|
+
const color = rawColor === "default" ? void 0 : rawColor;
|
|
1755
|
+
if (!color) return { bold };
|
|
1756
|
+
if (isCustomHexColor(color)) {
|
|
1757
|
+
const rgba = color.startsWith("#") ? themePairToColorEntry({ lightMode: color, darkMode: color }) : { light_mode: color, dark_mode: color };
|
|
1758
|
+
if (rgba) {
|
|
1759
|
+
const alias = registerColorEntry(ctx.colors, rgba, "cus-text");
|
|
1760
|
+
return { bold, color: alias, colorKind: "custom" };
|
|
1761
|
+
}
|
|
1762
|
+
}
|
|
1763
|
+
return { bold, color, colorKind: "enum" };
|
|
1764
|
+
}
|
|
1608
1765
|
function renderChildren(children, ctx) {
|
|
1609
1766
|
let out = "";
|
|
1610
1767
|
let buffer = [];
|
|
@@ -1624,8 +1781,9 @@ function renderChildren(children, ctx) {
|
|
|
1624
1781
|
continue;
|
|
1625
1782
|
}
|
|
1626
1783
|
const head = group[0];
|
|
1627
|
-
if (head.bold === seg.bold && head.color === seg.color
|
|
1628
|
-
|
|
1784
|
+
if (head.bold === seg.bold && head.color === seg.color && head.colorKind === seg.colorKind) {
|
|
1785
|
+
group.push(seg);
|
|
1786
|
+
} else {
|
|
1629
1787
|
emitGroup();
|
|
1630
1788
|
group.push(seg);
|
|
1631
1789
|
}
|
|
@@ -1644,33 +1802,33 @@ function renderChildren(children, ctx) {
|
|
|
1644
1802
|
out += childToMarkdown(child, ctx);
|
|
1645
1803
|
}
|
|
1646
1804
|
flushBuffer();
|
|
1647
|
-
return out;
|
|
1805
|
+
return { content: out };
|
|
1648
1806
|
}
|
|
1649
1807
|
function childToInlineSegment(child, ctx) {
|
|
1650
1808
|
const tag = child.tag;
|
|
1651
1809
|
const prop = isRecord2(child.property) ? child.property : {};
|
|
1652
1810
|
const ts = isRecord2(prop.textStyle) ? prop.textStyle : void 0;
|
|
1653
|
-
const bold
|
|
1654
|
-
const rawColor = resolveTextStyleColor(ts);
|
|
1655
|
-
const color = rawColor === "default" ? void 0 : rawColor;
|
|
1811
|
+
const { bold, color, colorKind } = resolveInlineStyle(ts, ctx);
|
|
1656
1812
|
switch (tag) {
|
|
1657
1813
|
case "plain_text":
|
|
1658
1814
|
return {
|
|
1659
1815
|
content: typeof prop.content === "string" ? prop.content : "",
|
|
1660
1816
|
bold,
|
|
1661
|
-
color
|
|
1817
|
+
color,
|
|
1818
|
+
colorKind
|
|
1662
1819
|
};
|
|
1663
1820
|
case "code_span":
|
|
1664
1821
|
return {
|
|
1665
1822
|
content: `\`${typeof prop.content === "string" ? prop.content : ""}\``,
|
|
1666
1823
|
bold,
|
|
1667
|
-
color
|
|
1824
|
+
color,
|
|
1825
|
+
colorKind
|
|
1668
1826
|
};
|
|
1669
1827
|
case "link": {
|
|
1670
1828
|
const text = typeof prop.content === "string" ? prop.content : "";
|
|
1671
1829
|
const urlObj = isRecord2(prop.url) ? prop.url : void 0;
|
|
1672
1830
|
const url = urlObj && typeof urlObj.url === "string" ? urlObj.url : "";
|
|
1673
|
-
return { content: `[${text}](${url})`, bold, color };
|
|
1831
|
+
return { content: `[${text}](${url})`, bold, color, colorKind };
|
|
1674
1832
|
}
|
|
1675
1833
|
case "at_all":
|
|
1676
1834
|
return { content: "<at id=all></at>", bold, color };
|
|
@@ -1710,10 +1868,8 @@ function childToMarkdown(child, ctx) {
|
|
|
1710
1868
|
case "plain_text": {
|
|
1711
1869
|
const content = typeof prop.content === "string" ? prop.content : "";
|
|
1712
1870
|
const ts = isRecord2(prop.textStyle) ? prop.textStyle : void 0;
|
|
1713
|
-
const
|
|
1714
|
-
|
|
1715
|
-
const attrs = ts && Array.isArray(ts.attributes) ? ts.attributes : [];
|
|
1716
|
-
return wrapEmphasis(content, attrs.includes("bold"), color);
|
|
1871
|
+
const { bold, color } = resolveInlineStyle(ts, ctx);
|
|
1872
|
+
return wrapEmphasis(content, bold, color);
|
|
1717
1873
|
}
|
|
1718
1874
|
case "br":
|
|
1719
1875
|
return "\n";
|
|
@@ -1839,7 +1995,7 @@ ${"#".repeat(level)} ${body}
|
|
|
1839
1995
|
if (!data || data.tag !== "markdown") return "";
|
|
1840
1996
|
const cellProp = isRecord2(data.property) ? data.property : {};
|
|
1841
1997
|
const inner = Array.isArray(cellProp.elements) ? cellProp.elements : [];
|
|
1842
|
-
const text = renderChildren(inner, ctx);
|
|
1998
|
+
const { content: text } = renderChildren(inner, ctx);
|
|
1843
1999
|
return text.replace(/\|/g, "\\|").replace(/\n/g, " ");
|
|
1844
2000
|
});
|
|
1845
2001
|
return `| ${cells.join(" | ")} |`;
|
|
@@ -1962,10 +2118,10 @@ function rawToDsl(raw) {
|
|
|
1962
2118
|
}
|
|
1963
2119
|
}
|
|
1964
2120
|
const attachment = isRecord2(raw.json_attachment) ? raw.json_attachment : {};
|
|
1965
|
-
const ctx = {
|
|
2121
|
+
const ctx = makeCtx({
|
|
1966
2122
|
images: isRecord2(attachment.images) ? attachment.images : {},
|
|
1967
2123
|
atUsers: isRecord2(attachment.at_users) ? attachment.at_users : {}
|
|
1968
|
-
};
|
|
2124
|
+
});
|
|
1969
2125
|
return convertRoot(inner, ctx);
|
|
1970
2126
|
}
|
|
1971
2127
|
if (isRecord2(raw.card)) {
|
|
@@ -1973,10 +2129,10 @@ function rawToDsl(raw) {
|
|
|
1973
2129
|
if (typeof card.json_card === "string" || isRecord2(card.json_card)) {
|
|
1974
2130
|
return rawToDsl(card);
|
|
1975
2131
|
}
|
|
1976
|
-
return convertRoot(card,
|
|
2132
|
+
return convertRoot(card, makeCtx());
|
|
1977
2133
|
}
|
|
1978
2134
|
if ("body" in raw || "header" in raw || "schema" in raw) {
|
|
1979
|
-
return convertRoot(raw,
|
|
2135
|
+
return convertRoot(raw, makeCtx());
|
|
1980
2136
|
}
|
|
1981
2137
|
return raw;
|
|
1982
2138
|
}
|
|
@@ -1985,4 +2141,4 @@ function degradeUnknown(el) {
|
|
|
1985
2141
|
return { tag: "unknown", raw_tag: rawTag, fallback: el };
|
|
1986
2142
|
}
|
|
1987
2143
|
|
|
1988
|
-
export { degradeUnknown, dslToRaw, isRawCardEnvelope, normalizeStoredCardColors, rawCardToDsl, rawToDsl, readThemeColorLight, resolveCustomBackgroundLight, resolveTextStyleColor };
|
|
2144
|
+
export { createColorRegistry, degradeUnknown, dslToRaw, isCustomHexColor, isRawCardEnvelope, normalizeStoredCardColors, rawCardToDsl, rawToDsl, readThemeColorDark, readThemeColorLight, registerColorEntry, resolveCustomBackgroundLight, resolveTextStyleColor, resolveTextStyleCustomColorPair, themePairToColorEntry };
|
|
@@ -6,9 +6,20 @@ export type CustomColorEntry = {
|
|
|
6
6
|
light_mode: string;
|
|
7
7
|
dark_mode: string;
|
|
8
8
|
};
|
|
9
|
+
export type ColorRegistry = {
|
|
10
|
+
entries: Record<string, CustomColorEntry>;
|
|
11
|
+
keyToAlias: Map<string, string>;
|
|
12
|
+
bgSeq: number;
|
|
13
|
+
textSeq: number;
|
|
14
|
+
};
|
|
15
|
+
export declare function createColorRegistry(): ColorRegistry;
|
|
16
|
+
export declare function colorEntryKey(entry: CustomColorEntry): string;
|
|
17
|
+
export declare function registerColorEntry(registry: ColorRegistry, entry: CustomColorEntry, prefix: 'cus-bg' | 'cus-text'): string;
|
|
18
|
+
export declare function hexColorToRgba(hex: string): string | undefined;
|
|
9
19
|
/**
|
|
10
20
|
* 将飞书回读的 custom_background_style 还原为可再次发送的 background_style cus-N + config.style.color。
|
|
11
21
|
* 若 markdown 缺少 font_color,按 text_size / 加粗内容补 cus-accent / cus-muted(飞书回读会丢 font_color)。
|
|
22
|
+
* rawToDsl 可传入已登记的文字自定义色(preRegistered),与背景色一并写入 config.style.color。
|
|
12
23
|
*/
|
|
13
|
-
export declare function normalizeStoredCardColors(dsl: Record<string, unknown
|
|
24
|
+
export declare function normalizeStoredCardColors(dsl: Record<string, unknown>, preRegistered?: ColorRegistry): void;
|
|
14
25
|
//# sourceMappingURL=normalize-stored-colors.d.ts.map
|
|
@@ -1 +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;
|
|
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;AAEzE,MAAM,MAAM,aAAa,GAAG;IAC1B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;IAC1C,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,wBAAgB,mBAAmB,IAAI,aAAa,CAEnD;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,gBAAgB,GAAG,MAAM,CAE7D;AAED,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,aAAa,EACvB,KAAK,EAAE,gBAAgB,EACvB,MAAM,EAAE,QAAQ,GAAG,UAAU,GAC5B,MAAM,CAUR;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAgB9D;AAiBD;;;;GAIG;AACH,wBAAgB,yBAAyB,CACvC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC5B,aAAa,CAAC,EAAE,aAAa,GAC5B,IAAI,CAmGN"}
|
package/dist/raw-to-dsl.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"raw-to-dsl.d.ts","sourceRoot":"","sources":["../src/raw-to-dsl.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;
|
|
1
|
+
{"version":3,"file":"raw-to-dsl.d.ts","sourceRoot":"","sources":["../src/raw-to-dsl.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AAwBH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAIzD;AAED,wBAAgB,YAAY,CAAC,QAAQ,EAAE,OAAO,GAAG,OAAO,CAcvD;AAojDD;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CA8C9C;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAGnF"}
|