bridgerte 0.9.3 → 0.9.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.
Files changed (47) hide show
  1. package/README.md +892 -861
  2. package/dist/bridge.cjs.map +1 -1
  3. package/dist/bridge.d.ts +1 -3
  4. package/dist/bridge.js.map +1 -1
  5. package/dist/core.cjs +1 -1
  6. package/dist/core.cjs.map +1 -1
  7. package/dist/core.d.ts +9 -3
  8. package/dist/core.js +44 -54
  9. package/dist/core.js.map +1 -1
  10. package/dist/dom.cjs +1 -1
  11. package/dist/dom.d.ts +9 -3
  12. package/dist/dom.js +6 -5
  13. package/dist/index-BWi3d-Zp.js +314 -0
  14. package/dist/index-BWi3d-Zp.js.map +1 -0
  15. package/dist/index-B_g23O7q.cjs +4 -0
  16. package/dist/index-B_g23O7q.cjs.map +1 -0
  17. package/dist/index-CuNKUHed.js.map +1 -1
  18. package/dist/index-DF8OhKI4.cjs +2 -0
  19. package/dist/index-DF8OhKI4.cjs.map +1 -0
  20. package/dist/{index-BwZ0II4h.js → index-DyCMSFrm.js} +1135 -1141
  21. package/dist/index-DyCMSFrm.js.map +1 -0
  22. package/dist/index-GaS65GL0.cjs.map +1 -1
  23. package/dist/index-H5V0EMkq.cjs +36 -0
  24. package/dist/index-H5V0EMkq.cjs.map +1 -0
  25. package/dist/index-sbZNOcCB.js +54 -0
  26. package/dist/index-sbZNOcCB.js.map +1 -0
  27. package/dist/index.cjs +1 -1
  28. package/dist/index.d.ts +17 -3
  29. package/dist/index.js +24 -21
  30. package/dist/index.js.map +1 -1
  31. package/dist/native-spec.cjs +1 -1
  32. package/dist/native-spec.cjs.map +1 -1
  33. package/dist/native-spec.d.ts +1 -3
  34. package/dist/native-spec.js +73 -119
  35. package/dist/native-spec.js.map +1 -1
  36. package/dist/style.css +1 -1
  37. package/dist/webview.cjs +1 -1
  38. package/dist/webview.d.ts +1 -3
  39. package/dist/webview.js +1 -1
  40. package/package.json +1 -1
  41. package/dist/index-BaOlPu8L.cjs +0 -4
  42. package/dist/index-BaOlPu8L.cjs.map +0 -1
  43. package/dist/index-BwZ0II4h.js.map +0 -1
  44. package/dist/index-bN5Hs6-3.js +0 -299
  45. package/dist/index-bN5Hs6-3.js.map +0 -1
  46. package/dist/index-hd9Zi2DV.cjs +0 -36
  47. package/dist/index-hd9Zi2DV.cjs.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"bridge.cjs","sources":["../../bridge/src/index.ts"],"sourcesContent":["import type { BridgeEventTiming, BridgeMessage } from './type';\n\nexport type * from './type';\n\n/**\n * bridge 高频事件的默认节流策略。\n *\n * 这里先固定协议默认值,真正的 WebView runtime 会在发送消息时使用这些数值。\n */\nexport const BRIDGE_CONTENT_CHANGE_DEBOUNCE_MS = 120;\nexport const BRIDGE_HEIGHT_CHANGE_THROTTLE_MS = 100;\n\nexport const defaultBridgeEventTiming: BridgeEventTiming = {\n contentChangeDebounceMs: BRIDGE_CONTENT_CHANGE_DEBOUNCE_MS,\n heightChangeThrottleMs: BRIDGE_HEIGHT_CHANGE_THROTTLE_MS,\n commandStateChangeDedupe: true\n};\n\n/**\n * bridge 当前支持的全部外层消息类型。\n *\n * `isBridgeMessage()` 只信任这个白名单,避免把未知 `editor.*` 消息误判为合法协议。\n */\nconst bridgeMessageTypes = new Set<BridgeMessage['type']>([\n 'editor.init',\n 'editor.executeCommand',\n 'editor.setContent',\n 'editor.setReadonly',\n 'editor.requestContent',\n 'editor.payloadPanelResolved',\n 'editor.payloadPanelCanceled',\n 'editor.uploadResolved',\n 'editor.uploadRejected',\n 'editor.ready',\n 'editor.content',\n 'editor.contentChange',\n 'editor.selectionChange',\n 'editor.commandStateChange',\n 'editor.payloadPanelRequest',\n 'editor.uploadRequest',\n 'editor.heightChange',\n 'editor.error'\n]);\n\n/**\n * bridge 消息的已知类型守卫。\n *\n * 这里只校验消息外层类型,深层 payload 校验留给具体消息处理器。\n * 这样能在轻量运行时判断和完整业务校验之间保持边界清楚。\n */\nexport function isBridgeMessage(value: unknown): value is BridgeMessage {\n if (typeof value !== 'object' || value === null) {\n return false;\n }\n\n const candidate = value as { type?: unknown };\n return typeof candidate.type === 'string'\n && bridgeMessageTypes.has(candidate.type as BridgeMessage['type']);\n}\n"],"names":["BRIDGE_CONTENT_CHANGE_DEBOUNCE_MS","BRIDGE_HEIGHT_CHANGE_THROTTLE_MS","defaultBridgeEventTiming","bridgeMessageTypes","isBridgeMessage","value","candidate"],"mappings":"gFASO,MAAMA,EAAoC,IACpCC,EAAmC,IAEnCC,EAA8C,CACzD,wBAAyBF,EACzB,uBAAwBC,EACxB,yBAA0B,EAC5B,EAOME,MAAyB,IAA2B,CACxD,cACA,wBACA,oBACA,qBACA,wBACA,8BACA,8BACA,wBACA,wBACA,eACA,iBACA,uBACA,yBACA,4BACA,6BACA,uBACA,sBACA,cACF,CAAC,EAQM,SAASC,EAAgBC,EAAwC,CACtE,GAAI,OAAOA,GAAU,UAAYA,IAAU,KACzC,MAAO,GAGT,MAAMC,EAAYD,EAClB,OAAO,OAAOC,EAAU,MAAS,UAC5BH,EAAmB,IAAIG,EAAU,IAA6B,CACrE"}
1
+ {"version":3,"file":"bridge.cjs","sources":["../../bridge/src/index.ts"],"sourcesContent":["import type { BridgeEventTiming, BridgeMessage } from './type';\r\n\r\nexport type * from './type';\r\n\r\n/**\r\n * bridge 高频事件的默认节流策略。\r\n *\r\n * 这里先固定协议默认值,真正的 WebView runtime 会在发送消息时使用这些数值。\r\n */\r\nexport const BRIDGE_CONTENT_CHANGE_DEBOUNCE_MS = 120;\r\nexport const BRIDGE_HEIGHT_CHANGE_THROTTLE_MS = 100;\r\n\r\nexport const defaultBridgeEventTiming: BridgeEventTiming = {\r\n contentChangeDebounceMs: BRIDGE_CONTENT_CHANGE_DEBOUNCE_MS,\r\n heightChangeThrottleMs: BRIDGE_HEIGHT_CHANGE_THROTTLE_MS,\r\n commandStateChangeDedupe: true\r\n};\r\n\r\n/**\r\n * bridge 当前支持的全部外层消息类型。\r\n *\r\n * `isBridgeMessage()` 只信任这个白名单,避免把未知 `editor.*` 消息误判为合法协议。\r\n */\r\nconst bridgeMessageTypes = new Set<BridgeMessage['type']>([\r\n 'editor.init',\r\n 'editor.executeCommand',\r\n 'editor.setContent',\r\n 'editor.setReadonly',\r\n 'editor.requestContent',\r\n 'editor.payloadPanelResolved',\r\n 'editor.payloadPanelCanceled',\r\n 'editor.uploadResolved',\r\n 'editor.uploadRejected',\r\n 'editor.ready',\r\n 'editor.content',\r\n 'editor.contentChange',\r\n 'editor.selectionChange',\r\n 'editor.commandStateChange',\r\n 'editor.payloadPanelRequest',\r\n 'editor.uploadRequest',\r\n 'editor.heightChange',\r\n 'editor.error'\r\n]);\r\n\r\n/**\r\n * bridge 消息的已知类型守卫。\r\n *\r\n * 这里只校验消息外层类型,深层 payload 校验留给具体消息处理器。\r\n * 这样能在轻量运行时判断和完整业务校验之间保持边界清楚。\r\n */\r\nexport function isBridgeMessage(value: unknown): value is BridgeMessage {\r\n if (typeof value !== 'object' || value === null) {\r\n return false;\r\n }\r\n\r\n const candidate = value as { type?: unknown };\r\n return typeof candidate.type === 'string'\r\n && bridgeMessageTypes.has(candidate.type as BridgeMessage['type']);\r\n}\r\n"],"names":["BRIDGE_CONTENT_CHANGE_DEBOUNCE_MS","BRIDGE_HEIGHT_CHANGE_THROTTLE_MS","defaultBridgeEventTiming","bridgeMessageTypes","isBridgeMessage","value","candidate"],"mappings":"gFASO,MAAMA,EAAoC,IACpCC,EAAmC,IAEnCC,EAA8C,CACzD,wBAAyBF,EACzB,uBAAwBC,EACxB,yBAA0B,EAC5B,EAOME,MAAyB,IAA2B,CACxD,cACA,wBACA,oBACA,qBACA,wBACA,8BACA,8BACA,wBACA,wBACA,eACA,iBACA,uBACA,yBACA,4BACA,6BACA,uBACA,sBACA,cACF,CAAC,EAQM,SAASC,EAAgBC,EAAwC,CACtE,GAAI,OAAOA,GAAU,UAAYA,IAAU,KACzC,MAAO,GAGT,MAAMC,EAAYD,EAClB,OAAO,OAAOC,EAAU,MAAS,UAC5BH,EAAmB,IAAIG,EAAU,IAA6B,CACrE"}
package/dist/bridge.d.ts CHANGED
@@ -182,7 +182,7 @@ export type ToolbarGroupConfig = {
182
182
  /**
183
183
  * toolbar JSON 配置项。
184
184
  *
185
- * 字符串使用 `MenuItem.id`;特殊字符串 `|` 表示分割线,视觉保持和默认 group 分隔一致。
185
+ * 字符串使用 `MenuItem.id`;特殊字符串 `|` 表示分割线,收纳菜单用对象配置显式声明。
186
186
  */
187
187
  export type ToolbarKey = string | ToolbarGroupConfig;
188
188
  /**
@@ -513,7 +513,6 @@ export type SlashCommandItem = {
513
513
  icon?: string;
514
514
  description?: string;
515
515
  keywords?: string[];
516
- group?: string;
517
516
  requiresPayload?: boolean;
518
517
  payloadPanel?: PayloadPanelSchema;
519
518
  };
@@ -579,7 +578,6 @@ export type MenuItem = {
579
578
  command: EditorCommand;
580
579
  label: string;
581
580
  icon: string;
582
- group: 'text' | 'style' | 'block' | 'list' | 'align' | 'insert' | 'media' | 'table' | 'history' | 'view';
583
581
  requiresPayload?: boolean;
584
582
  payloadPanel?: PayloadPanelSchema;
585
583
  children?: MenuItem[];
@@ -1 +1 @@
1
- {"version":3,"file":"bridge.js","sources":["../../bridge/src/index.ts"],"sourcesContent":["import type { BridgeEventTiming, BridgeMessage } from './type';\n\nexport type * from './type';\n\n/**\n * bridge 高频事件的默认节流策略。\n *\n * 这里先固定协议默认值,真正的 WebView runtime 会在发送消息时使用这些数值。\n */\nexport const BRIDGE_CONTENT_CHANGE_DEBOUNCE_MS = 120;\nexport const BRIDGE_HEIGHT_CHANGE_THROTTLE_MS = 100;\n\nexport const defaultBridgeEventTiming: BridgeEventTiming = {\n contentChangeDebounceMs: BRIDGE_CONTENT_CHANGE_DEBOUNCE_MS,\n heightChangeThrottleMs: BRIDGE_HEIGHT_CHANGE_THROTTLE_MS,\n commandStateChangeDedupe: true\n};\n\n/**\n * bridge 当前支持的全部外层消息类型。\n *\n * `isBridgeMessage()` 只信任这个白名单,避免把未知 `editor.*` 消息误判为合法协议。\n */\nconst bridgeMessageTypes = new Set<BridgeMessage['type']>([\n 'editor.init',\n 'editor.executeCommand',\n 'editor.setContent',\n 'editor.setReadonly',\n 'editor.requestContent',\n 'editor.payloadPanelResolved',\n 'editor.payloadPanelCanceled',\n 'editor.uploadResolved',\n 'editor.uploadRejected',\n 'editor.ready',\n 'editor.content',\n 'editor.contentChange',\n 'editor.selectionChange',\n 'editor.commandStateChange',\n 'editor.payloadPanelRequest',\n 'editor.uploadRequest',\n 'editor.heightChange',\n 'editor.error'\n]);\n\n/**\n * bridge 消息的已知类型守卫。\n *\n * 这里只校验消息外层类型,深层 payload 校验留给具体消息处理器。\n * 这样能在轻量运行时判断和完整业务校验之间保持边界清楚。\n */\nexport function isBridgeMessage(value: unknown): value is BridgeMessage {\n if (typeof value !== 'object' || value === null) {\n return false;\n }\n\n const candidate = value as { type?: unknown };\n return typeof candidate.type === 'string'\n && bridgeMessageTypes.has(candidate.type as BridgeMessage['type']);\n}\n"],"names":["BRIDGE_CONTENT_CHANGE_DEBOUNCE_MS","BRIDGE_HEIGHT_CHANGE_THROTTLE_MS","defaultBridgeEventTiming","bridgeMessageTypes","isBridgeMessage","value","candidate"],"mappings":"AASO,MAAMA,IAAoC,KACpCC,IAAmC,KAEnCC,IAA8C;AAAA,EACzD,yBAAyB;AAAA,EACzB,wBAAwB;AAAA,EACxB,0BAA0B;AAC5B,GAOMC,wBAAyB,IAA2B;AAAA,EACxD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAQM,SAASC,EAAgBC,GAAwC;AACtE,MAAI,OAAOA,KAAU,YAAYA,MAAU;AACzC,WAAO;AAGT,QAAMC,IAAYD;AAClB,SAAO,OAAOC,EAAU,QAAS,YAC5BH,EAAmB,IAAIG,EAAU,IAA6B;AACrE;"}
1
+ {"version":3,"file":"bridge.js","sources":["../../bridge/src/index.ts"],"sourcesContent":["import type { BridgeEventTiming, BridgeMessage } from './type';\r\n\r\nexport type * from './type';\r\n\r\n/**\r\n * bridge 高频事件的默认节流策略。\r\n *\r\n * 这里先固定协议默认值,真正的 WebView runtime 会在发送消息时使用这些数值。\r\n */\r\nexport const BRIDGE_CONTENT_CHANGE_DEBOUNCE_MS = 120;\r\nexport const BRIDGE_HEIGHT_CHANGE_THROTTLE_MS = 100;\r\n\r\nexport const defaultBridgeEventTiming: BridgeEventTiming = {\r\n contentChangeDebounceMs: BRIDGE_CONTENT_CHANGE_DEBOUNCE_MS,\r\n heightChangeThrottleMs: BRIDGE_HEIGHT_CHANGE_THROTTLE_MS,\r\n commandStateChangeDedupe: true\r\n};\r\n\r\n/**\r\n * bridge 当前支持的全部外层消息类型。\r\n *\r\n * `isBridgeMessage()` 只信任这个白名单,避免把未知 `editor.*` 消息误判为合法协议。\r\n */\r\nconst bridgeMessageTypes = new Set<BridgeMessage['type']>([\r\n 'editor.init',\r\n 'editor.executeCommand',\r\n 'editor.setContent',\r\n 'editor.setReadonly',\r\n 'editor.requestContent',\r\n 'editor.payloadPanelResolved',\r\n 'editor.payloadPanelCanceled',\r\n 'editor.uploadResolved',\r\n 'editor.uploadRejected',\r\n 'editor.ready',\r\n 'editor.content',\r\n 'editor.contentChange',\r\n 'editor.selectionChange',\r\n 'editor.commandStateChange',\r\n 'editor.payloadPanelRequest',\r\n 'editor.uploadRequest',\r\n 'editor.heightChange',\r\n 'editor.error'\r\n]);\r\n\r\n/**\r\n * bridge 消息的已知类型守卫。\r\n *\r\n * 这里只校验消息外层类型,深层 payload 校验留给具体消息处理器。\r\n * 这样能在轻量运行时判断和完整业务校验之间保持边界清楚。\r\n */\r\nexport function isBridgeMessage(value: unknown): value is BridgeMessage {\r\n if (typeof value !== 'object' || value === null) {\r\n return false;\r\n }\r\n\r\n const candidate = value as { type?: unknown };\r\n return typeof candidate.type === 'string'\r\n && bridgeMessageTypes.has(candidate.type as BridgeMessage['type']);\r\n}\r\n"],"names":["BRIDGE_CONTENT_CHANGE_DEBOUNCE_MS","BRIDGE_HEIGHT_CHANGE_THROTTLE_MS","defaultBridgeEventTiming","bridgeMessageTypes","isBridgeMessage","value","candidate"],"mappings":"AASO,MAAMA,IAAoC,KACpCC,IAAmC,KAEnCC,IAA8C;AAAA,EACzD,yBAAyB;AAAA,EACzB,wBAAwB;AAAA,EACxB,0BAA0B;AAC5B,GAOMC,wBAAyB,IAA2B;AAAA,EACxD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAQM,SAASC,EAAgBC,GAAwC;AACtE,MAAI,OAAOA,KAAU,YAAYA,MAAU;AACzC,WAAO;AAGT,QAAMC,IAAYD;AAClB,SAAO,OAAOC,EAAU,QAAS,YAC5BH,EAAmB,IAAIG,EAAU,IAA6B;AACrE;"}
package/dist/core.cjs CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const o=require("./index-GaS65GL0.cjs"),O=e=>e!==void 0&&Object.keys(e).length>0,T=(e,t)=>{var E,R;const a=(E=t.options)!=null&&E.length?t.options:e,r=new Map(a.map(s=>[s.value,s])),u=(R=t.includeValues)!=null&&R.length?t.includeValues.flatMap(s=>{const l=r.get(s);return l?[l]:[]}):a,S=new Set(t.excludeValues??[]),p=u.filter(s=>!S.has(s.value)).map(s=>{var l,_;return{...s,label:((l=t.optionLabels)==null?void 0:l[s.value])??s.label,value:((_=t.optionValues)==null?void 0:_[s.value])??s.value}});return p.length>0?p:a},n=(e,t)=>({label:t.label??e.label,defaultValue:t.defaultValue??e.defaultValue,placeholder:t.placeholder??e.placeholder}),m=(e,t)=>!t||!O(t)?e:e.type==="select"?{...e,...n(e,t),options:T(e.options,t)}:e.type==="color"?{...e,...n(e,t),options:T(e.options??[],t)}:e.type==="number"?{...e,...n(e,t),min:t.min??e.min,max:t.max??e.max,step:t.step??e.step}:{...e,...n(e,t)},v=(e,t)=>{const a=t==null?void 0:t[e.id];return!a||!O(a)?e:{...e,title:a.title??e.title,description:a.description??e.description,fields:e.fields.map(r=>{var u;return m(r,(u=a.fields)==null?void 0:u[r.name])})}};exports.BRIDGERTE_CONTENT_VERSION=o.BRIDGERTE_CONTENT_VERSION;exports.BRIDGERTE_TABLE_INSERT_MAX_COLS=o.BRIDGERTE_TABLE_INSERT_MAX_COLS;exports.BRIDGERTE_TABLE_INSERT_MAX_ROWS=o.BRIDGERTE_TABLE_INSERT_MAX_ROWS;exports.resolvePayloadPanelSchema=v;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const a=require("./index-GaS65GL0.cjs"),l=require("./index-DF8OhKI4.cjs"),s=/[\u200B-\u200D\uFEFF]/g,o=/<[^>]*>/g,u=/&(?:nbsp|#160|#x0*a0);/gi,E=/&(?:[a-z\d]+|#\d+|#x[\da-f]+);/gi,m=["img","video","audio","iframe","table","pre","code","hr","figure","canvas","svg","math"],f=new Set(["bridgerte-divider","bridgerte-media","bridgerte-mention","code","horizontalrule","image","table","video"]),c=new RegExp(`<(${m.join("|")})(?=[\\s>/])`,"i"),n=e=>!!(e!=null&&e.replace(s,"").trim()),T=e=>{const t=e??"";if(!n(t))return!1;if(c.test(t))return!0;const r=t.replace(o," ").replace(u," ").replace(E,"x");return n(r)},i=e=>{var t;return e?n(e.text)||f.has(e.type)?!0:!!((t=e.children)!=null&&t.some(i)):!1},d=e=>{var t,r;return e?!(n(e.plainText)||(t=e.assets)!=null&&t.length||i((r=e.json)==null?void 0:r.root)||T(e.html)):!0};exports.BRIDGERTE_CONTENT_VERSION=a.BRIDGERTE_CONTENT_VERSION;exports.BRIDGERTE_TABLE_INSERT_MAX_COLS=a.BRIDGERTE_TABLE_INSERT_MAX_COLS;exports.BRIDGERTE_TABLE_INSERT_MAX_ROWS=a.BRIDGERTE_TABLE_INSERT_MAX_ROWS;exports.resolvePayloadPanelSchema=l.resolvePayloadPanelSchema;exports.isEditorContentEmpty=d;
2
2
  //# sourceMappingURL=core.cjs.map
package/dist/core.cjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"core.cjs","sources":["../../core/src/payloadPanel/index.ts"],"sourcesContent":["import type {\n PayloadPanelConfig,\n PayloadPanelField,\n PayloadPanelFieldConfig,\n PayloadPanelOption,\n PayloadPanelSchema\n} from './type';\n\nexport type * from './type';\n\nconst hasOwnConfigKeys = (config: object | undefined) => (\n config !== undefined && Object.keys(config).length > 0\n);\n\nconst resolveOptionList = (\n options: PayloadPanelOption[],\n config: PayloadPanelFieldConfig\n) => {\n const baseOptions = config.options?.length ? config.options : options;\n const optionByValue = new Map(baseOptions.map((option) => [option.value, option]));\n const includedOptions = config.includeValues?.length\n ? config.includeValues.flatMap((value) => {\n const option = optionByValue.get(value);\n\n return option ? [option] : [];\n })\n : baseOptions;\n const excludeValues = new Set(config.excludeValues ?? []);\n const filteredOptions = includedOptions.filter((option) => !excludeValues.has(option.value));\n const nextOptions = filteredOptions.map((option) => ({\n ...option,\n label: config.optionLabels?.[option.value] ?? option.label,\n value: config.optionValues?.[option.value] ?? option.value\n }));\n\n /*\n * 配置写错时不返回空候选,避免默认 DOM 面板、自绘 request 和原生菜单拿到\n * 无法操作的空列表;业务真要完全隐藏菜单应通过菜单 config 排除入口。\n */\n return nextOptions.length > 0 ? nextOptions : baseOptions;\n};\n\nconst resolveFieldBaseOverride = (\n field: PayloadPanelField,\n config: PayloadPanelFieldConfig\n) => ({\n label: config.label ?? field.label,\n defaultValue: config.defaultValue ?? field.defaultValue,\n placeholder: config.placeholder ?? field.placeholder\n});\n\nconst resolvePayloadPanelField = (\n field: PayloadPanelField,\n config: PayloadPanelFieldConfig | undefined\n): PayloadPanelField => {\n if (!config || !hasOwnConfigKeys(config)) return field;\n\n if (field.type === 'select') {\n return {\n ...field,\n ...resolveFieldBaseOverride(field, config),\n options: resolveOptionList(field.options, config)\n };\n }\n\n if (field.type === 'color') {\n return {\n ...field,\n ...resolveFieldBaseOverride(field, config),\n options: resolveOptionList(field.options ?? [], config)\n };\n }\n\n if (field.type === 'number') {\n return {\n ...field,\n ...resolveFieldBaseOverride(field, config),\n min: config.min ?? field.min,\n max: config.max ?? field.max,\n step: config.step ?? field.step\n };\n }\n\n return {\n ...field,\n ...resolveFieldBaseOverride(field, config)\n };\n};\n\n/**\n * 解析参数面板 schema。\n *\n * 这个纯函数只处理 schema 数据,不理解 DOM、Lexical 或具体命令;toolbar、hoverbar、\n * code block header 和 WebView host request 都应先走这里,保证默认 UI 和业务自绘同源。\n */\nexport const resolvePayloadPanelSchema = (\n panel: PayloadPanelSchema,\n config?: PayloadPanelConfig\n): PayloadPanelSchema => {\n const panelConfig = config?.[panel.id];\n\n if (!panelConfig || !hasOwnConfigKeys(panelConfig)) return panel;\n\n return {\n ...panel,\n title: panelConfig.title ?? panel.title,\n description: panelConfig.description ?? panel.description,\n fields: panel.fields.map((field) => resolvePayloadPanelField(\n field,\n panelConfig.fields?.[field.name]\n ))\n };\n};\n"],"names":["hasOwnConfigKeys","config","resolveOptionList","options","baseOptions","_a","optionByValue","option","includedOptions","_b","value","excludeValues","nextOptions","resolveFieldBaseOverride","field","resolvePayloadPanelField","resolvePayloadPanelSchema","panel","panelConfig"],"mappings":"wHAUMA,EAAoBC,GACxBA,IAAW,QAAa,OAAO,KAAKA,CAAM,EAAE,OAAS,EAGjDC,EAAoB,CACxBC,EACAF,IACG,SACH,MAAMG,GAAcC,EAAAJ,EAAO,UAAP,MAAAI,EAAgB,OAASJ,EAAO,QAAUE,EACxDG,EAAgB,IAAI,IAAIF,EAAY,IAAKG,GAAW,CAACA,EAAO,MAAOA,CAAM,CAAC,CAAC,EAC3EC,GAAkBC,EAAAR,EAAO,gBAAP,MAAAQ,EAAsB,OAC1CR,EAAO,cAAc,QAASS,GAAU,CACxC,MAAMH,EAASD,EAAc,IAAII,CAAK,EAEtC,OAAOH,EAAS,CAACA,CAAM,EAAI,CAAA,CAC7B,CAAC,EACCH,EACEO,EAAgB,IAAI,IAAIV,EAAO,eAAiB,CAAA,CAAE,EAElDW,EADkBJ,EAAgB,OAAQD,GAAW,CAACI,EAAc,IAAIJ,EAAO,KAAK,CAAC,EACvD,IAAKA,GAAA,SAAY,OACnD,GAAGA,EACH,QAAOF,EAAAJ,EAAO,eAAP,YAAAI,EAAsBE,EAAO,SAAUA,EAAO,MACrD,QAAOE,EAAAR,EAAO,eAAP,YAAAQ,EAAsBF,EAAO,SAAUA,EAAO,KAAA,EACrD,EAMF,OAAOK,EAAY,OAAS,EAAIA,EAAcR,CAChD,EAEMS,EAA2B,CAC/BC,EACAb,KACI,CACJ,MAAOA,EAAO,OAASa,EAAM,MAC7B,aAAcb,EAAO,cAAgBa,EAAM,aAC3C,YAAab,EAAO,aAAea,EAAM,WAC3C,GAEMC,EAA2B,CAC/BD,EACAb,IAEI,CAACA,GAAU,CAACD,EAAiBC,CAAM,EAAUa,EAE7CA,EAAM,OAAS,SACV,CACL,GAAGA,EACH,GAAGD,EAAyBC,EAAOb,CAAM,EACzC,QAASC,EAAkBY,EAAM,QAASb,CAAM,CAAA,EAIhDa,EAAM,OAAS,QACV,CACL,GAAGA,EACH,GAAGD,EAAyBC,EAAOb,CAAM,EACzC,QAASC,EAAkBY,EAAM,SAAW,CAAA,EAAIb,CAAM,CAAA,EAItDa,EAAM,OAAS,SACV,CACL,GAAGA,EACH,GAAGD,EAAyBC,EAAOb,CAAM,EACzC,IAAKA,EAAO,KAAOa,EAAM,IACzB,IAAKb,EAAO,KAAOa,EAAM,IACzB,KAAMb,EAAO,MAAQa,EAAM,IAAA,EAIxB,CACL,GAAGA,EACH,GAAGD,EAAyBC,EAAOb,CAAM,CAAA,EAUhCe,EAA4B,CACvCC,EACAhB,IACuB,CACvB,MAAMiB,EAAcjB,GAAA,YAAAA,EAASgB,EAAM,IAEnC,MAAI,CAACC,GAAe,CAAClB,EAAiBkB,CAAW,EAAUD,EAEpD,CACL,GAAGA,EACH,MAAOC,EAAY,OAASD,EAAM,MAClC,YAAaC,EAAY,aAAeD,EAAM,YAC9C,OAAQA,EAAM,OAAO,IAAKH,GAAA,OAAU,OAAAC,EAClCD,GACAT,EAAAa,EAAY,SAAZ,YAAAb,EAAqBS,EAAM,KAAI,EAChC,CAAA,CAEL"}
1
+ {"version":3,"file":"core.cjs","sources":["../../core/src/content/index.ts"],"sourcesContent":["import type { EditorContent, EditorContentNode } from './type';\n\nconst invisibleTextPattern = /[\\u200B-\\u200D\\uFEFF]/g;\nconst htmlTagPattern = /<[^>]*>/g;\nconst blankHtmlEntityPattern = /&(?:nbsp|#160|#x0*a0);/gi;\nconst htmlEntityPattern = /&(?:[a-z\\d]+|#\\d+|#x[\\da-f]+);/gi;\nconst meaningfulHtmlElementNames = [\n 'img',\n 'video',\n 'audio',\n 'iframe',\n 'table',\n 'pre',\n 'code',\n 'hr',\n 'figure',\n 'canvas',\n 'svg',\n 'math'\n];\n\n/*\n * 这些节点即使当前没有普通文本,也代表用户主动插入了结构内容。\n * 后续新增非文本内容节点时优先补进这张表;纯段落、列表容器这类结构继续靠子节点判断。\n */\nconst meaningfulStructuredNodeTypes = new Set([\n 'bridgerte-divider',\n 'bridgerte-media',\n 'bridgerte-mention',\n 'code',\n 'horizontalrule',\n 'image',\n 'table',\n 'video'\n]);\n\nconst meaningfulHtmlElementPattern = new RegExp(\n `<(${meaningfulHtmlElementNames.join('|')})(?=[\\\\s>/])`,\n 'i'\n);\n\nconst hasMeaningfulText = (text: string | undefined): boolean => (\n Boolean(text?.replace(invisibleTextPattern, '').trim())\n);\n\nconst hasMeaningfulHtmlFallback = (html: string | undefined): boolean => {\n const htmlValue = html ?? '';\n\n if (!hasMeaningfulText(htmlValue)) return false;\n if (meaningfulHtmlElementPattern.test(htmlValue)) return true;\n\n /*\n * core 不能依赖 DOMParser,这里只做轻量兜底:去掉标签和空白实体后,\n * 其余实体按可见字符处理。需要完整 HTML 语义时使用 DOM 包的解析工具。\n */\n const textLikeContent = htmlValue\n .replace(htmlTagPattern, ' ')\n .replace(blankHtmlEntityPattern, ' ')\n .replace(htmlEntityPattern, 'x');\n\n return hasMeaningfulText(textLikeContent);\n};\n\nconst hasMeaningfulContentNode = (node: EditorContentNode | undefined): boolean => {\n if (!node) return false;\n if (hasMeaningfulText(node.text)) return true;\n if (meaningfulStructuredNodeTypes.has(node.type)) return true;\n\n return Boolean(node.children?.some(hasMeaningfulContentNode));\n};\n\n/**\n * 判断 BridgeRTE 内容快照是否为空。\n *\n * 函数只读取已生成的 `EditorContent` 字段,不触发 DOM 解析或编辑器序列化;调用方应在保存、\n * 提交或离开确认这类低频动作里配合 `editor.getContent()` 使用。\n */\nexport const isEditorContentEmpty = (\n content: Partial<EditorContent> | null | undefined\n): boolean => {\n if (!content) return true;\n if (hasMeaningfulText(content.plainText)) return false;\n if (content.assets?.length) return false;\n if (hasMeaningfulContentNode(content.json?.root)) return false;\n if (hasMeaningfulHtmlFallback(content.html)) return false;\n\n return true;\n};\n"],"names":["invisibleTextPattern","htmlTagPattern","blankHtmlEntityPattern","htmlEntityPattern","meaningfulHtmlElementNames","meaningfulStructuredNodeTypes","meaningfulHtmlElementPattern","hasMeaningfulText","text","hasMeaningfulHtmlFallback","html","htmlValue","textLikeContent","hasMeaningfulContentNode","node","_a","isEditorContentEmpty","content","_b"],"mappings":"0JAEMA,EAAuB,yBACvBC,EAAiB,WACjBC,EAAyB,2BACzBC,EAAoB,mCACpBC,EAA6B,CACjC,MACA,QACA,QACA,SACA,QACA,MACA,OACA,KACA,SACA,SACA,MACA,MACF,EAMMC,MAAoC,IAAI,CAC5C,oBACA,kBACA,oBACA,OACA,iBACA,QACA,QACA,OACF,CAAC,EAEKC,EAA+B,IAAI,OACvC,KAAKF,EAA2B,KAAK,GAAG,CAAC,eACzC,GACF,EAEMG,EAAqBC,GACzB,GAAQA,GAAA,MAAAA,EAAM,QAAQR,EAAsB,IAAI,QAG5CS,EAA6BC,GAAsC,CACvE,MAAMC,EAAYD,GAAQ,GAE1B,GAAI,CAACH,EAAkBI,CAAS,EAAG,MAAO,GAC1C,GAAIL,EAA6B,KAAKK,CAAS,EAAG,MAAO,GAMzD,MAAMC,EAAkBD,EACrB,QAAQV,EAAgB,GAAG,EAC3B,QAAQC,EAAwB,GAAG,EACnC,QAAQC,EAAmB,GAAG,EAEjC,OAAOI,EAAkBK,CAAe,CAC1C,EAEMC,EAA4BC,GAAiD,OACjF,OAAKA,EACDP,EAAkBO,EAAK,IAAI,GAC3BT,EAA8B,IAAIS,EAAK,IAAI,EAAU,GAElD,IAAQC,EAAAD,EAAK,WAAL,MAAAC,EAAe,KAAKF,IAJjB,EAKpB,EAQaG,EACXC,GACY,SACZ,OAAKA,EACD,EAAAV,EAAkBU,EAAQ,SAAS,IACnCF,EAAAE,EAAQ,SAAR,MAAAF,EAAgB,QAChBF,GAAyBK,EAAAD,EAAQ,OAAR,YAAAC,EAAc,IAAI,GAC3CT,EAA0BQ,EAAQ,IAAI,GAJrB,EAOvB"}
package/dist/core.d.ts CHANGED
@@ -182,7 +182,7 @@ export type ToolbarGroupConfig = {
182
182
  /**
183
183
  * toolbar JSON 配置项。
184
184
  *
185
- * 字符串使用 `MenuItem.id`;特殊字符串 `|` 表示分割线,视觉保持和默认 group 分隔一致。
185
+ * 字符串使用 `MenuItem.id`;特殊字符串 `|` 表示分割线,收纳菜单用对象配置显式声明。
186
186
  */
187
187
  export type ToolbarKey = string | ToolbarGroupConfig;
188
188
  /**
@@ -513,7 +513,6 @@ export type SlashCommandItem = {
513
513
  icon?: string;
514
514
  description?: string;
515
515
  keywords?: string[];
516
- group?: string;
517
516
  requiresPayload?: boolean;
518
517
  payloadPanel?: PayloadPanelSchema;
519
518
  };
@@ -579,7 +578,6 @@ export type MenuItem = {
579
578
  command: EditorCommand;
580
579
  label: string;
581
580
  icon: string;
582
- group: 'text' | 'style' | 'block' | 'list' | 'align' | 'insert' | 'media' | 'table' | 'history' | 'view';
583
581
  requiresPayload?: boolean;
584
582
  payloadPanel?: PayloadPanelSchema;
585
583
  children?: MenuItem[];
@@ -912,3 +910,11 @@ export declare const BRIDGERTE_CONTENT_VERSION = "0.1.0";
912
910
  export declare const BRIDGERTE_TABLE_INSERT_MAX_ROWS = 20;
913
911
  export declare const BRIDGERTE_TABLE_INSERT_MAX_COLS = 20;
914
912
 
913
+ /**
914
+ * 判断 BridgeRTE 内容快照是否为空。
915
+ *
916
+ * 函数只读取已生成的 `EditorContent` 字段,不触发 DOM 解析或编辑器序列化;调用方应在保存、
917
+ * 提交或离开确认这类低频动作里配合 `editor.getContent()` 使用。
918
+ */
919
+ export declare const isEditorContentEmpty: (content: Partial<EditorContent> | null | undefined) => boolean;
920
+
package/dist/core.js CHANGED
@@ -1,58 +1,48 @@
1
- import { B as d, a as x, b as y } from "./index-CuNKUHed.js";
2
- const E = (e) => e !== void 0 && Object.keys(e).length > 0, v = (e, t) => {
3
- var p, m;
4
- const a = (p = t.options) != null && p.length ? t.options : e, r = new Map(a.map((s) => [s.value, s])), u = (m = t.includeValues) != null && m.length ? t.includeValues.flatMap((s) => {
5
- const l = r.get(s);
6
- return l ? [l] : [];
7
- }) : a, b = new Set(t.excludeValues ?? []), o = u.filter((s) => !b.has(s.value)).map((s) => {
8
- var l, O;
9
- return {
10
- ...s,
11
- label: ((l = t.optionLabels) == null ? void 0 : l[s.value]) ?? s.label,
12
- value: ((O = t.optionValues) == null ? void 0 : O[s.value]) ?? s.value
13
- };
14
- });
15
- return o.length > 0 ? o : a;
16
- }, n = (e, t) => ({
17
- label: t.label ?? e.label,
18
- defaultValue: t.defaultValue ?? e.defaultValue,
19
- placeholder: t.placeholder ?? e.placeholder
20
- }), h = (e, t) => !t || !E(t) ? e : e.type === "select" ? {
21
- ...e,
22
- ...n(e, t),
23
- options: v(e.options, t)
24
- } : e.type === "color" ? {
25
- ...e,
26
- ...n(e, t),
27
- options: v(e.options ?? [], t)
28
- } : e.type === "number" ? {
29
- ...e,
30
- ...n(e, t),
31
- min: t.min ?? e.min,
32
- max: t.max ?? e.max,
33
- step: t.step ?? e.step
34
- } : {
35
- ...e,
36
- ...n(e, t)
37
- }, V = (e, t) => {
38
- const a = t == null ? void 0 : t[e.id];
39
- return !a || !E(a) ? e : {
40
- ...e,
41
- title: a.title ?? e.title,
42
- description: a.description ?? e.description,
43
- fields: e.fields.map((r) => {
44
- var u;
45
- return h(
46
- r,
47
- (u = a.fields) == null ? void 0 : u[r.name]
48
- );
49
- })
50
- };
1
+ import { B as h, a as p, b as T } from "./index-CuNKUHed.js";
2
+ import { r as b } from "./index-sbZNOcCB.js";
3
+ const i = /[\u200B-\u200D\uFEFF]/g, l = /<[^>]*>/g, s = /&(?:nbsp|#160|#x0*a0);/gi, o = /&(?:[a-z\d]+|#\d+|#x[\da-f]+);/gi, u = [
4
+ "img",
5
+ "video",
6
+ "audio",
7
+ "iframe",
8
+ "table",
9
+ "pre",
10
+ "code",
11
+ "hr",
12
+ "figure",
13
+ "canvas",
14
+ "svg",
15
+ "math"
16
+ ], f = /* @__PURE__ */ new Set([
17
+ "bridgerte-divider",
18
+ "bridgerte-media",
19
+ "bridgerte-mention",
20
+ "code",
21
+ "horizontalrule",
22
+ "image",
23
+ "table",
24
+ "video"
25
+ ]), m = new RegExp(
26
+ `<(${u.join("|")})(?=[\\s>/])`,
27
+ "i"
28
+ ), n = (e) => !!(e != null && e.replace(i, "").trim()), c = (e) => {
29
+ const t = e ?? "";
30
+ if (!n(t)) return !1;
31
+ if (m.test(t)) return !0;
32
+ const r = t.replace(l, " ").replace(s, " ").replace(o, "x");
33
+ return n(r);
34
+ }, a = (e) => {
35
+ var t;
36
+ return e ? n(e.text) || f.has(e.type) ? !0 : !!((t = e.children) != null && t.some(a)) : !1;
37
+ }, g = (e) => {
38
+ var t, r;
39
+ return e ? !(n(e.plainText) || (t = e.assets) != null && t.length || a((r = e.json) == null ? void 0 : r.root) || c(e.html)) : !0;
51
40
  };
52
41
  export {
53
- d as BRIDGERTE_CONTENT_VERSION,
54
- x as BRIDGERTE_TABLE_INSERT_MAX_COLS,
55
- y as BRIDGERTE_TABLE_INSERT_MAX_ROWS,
56
- V as resolvePayloadPanelSchema
42
+ h as BRIDGERTE_CONTENT_VERSION,
43
+ p as BRIDGERTE_TABLE_INSERT_MAX_COLS,
44
+ T as BRIDGERTE_TABLE_INSERT_MAX_ROWS,
45
+ g as isEditorContentEmpty,
46
+ b as resolvePayloadPanelSchema
57
47
  };
58
48
  //# sourceMappingURL=core.js.map
package/dist/core.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"core.js","sources":["../../core/src/payloadPanel/index.ts"],"sourcesContent":["import type {\n PayloadPanelConfig,\n PayloadPanelField,\n PayloadPanelFieldConfig,\n PayloadPanelOption,\n PayloadPanelSchema\n} from './type';\n\nexport type * from './type';\n\nconst hasOwnConfigKeys = (config: object | undefined) => (\n config !== undefined && Object.keys(config).length > 0\n);\n\nconst resolveOptionList = (\n options: PayloadPanelOption[],\n config: PayloadPanelFieldConfig\n) => {\n const baseOptions = config.options?.length ? config.options : options;\n const optionByValue = new Map(baseOptions.map((option) => [option.value, option]));\n const includedOptions = config.includeValues?.length\n ? config.includeValues.flatMap((value) => {\n const option = optionByValue.get(value);\n\n return option ? [option] : [];\n })\n : baseOptions;\n const excludeValues = new Set(config.excludeValues ?? []);\n const filteredOptions = includedOptions.filter((option) => !excludeValues.has(option.value));\n const nextOptions = filteredOptions.map((option) => ({\n ...option,\n label: config.optionLabels?.[option.value] ?? option.label,\n value: config.optionValues?.[option.value] ?? option.value\n }));\n\n /*\n * 配置写错时不返回空候选,避免默认 DOM 面板、自绘 request 和原生菜单拿到\n * 无法操作的空列表;业务真要完全隐藏菜单应通过菜单 config 排除入口。\n */\n return nextOptions.length > 0 ? nextOptions : baseOptions;\n};\n\nconst resolveFieldBaseOverride = (\n field: PayloadPanelField,\n config: PayloadPanelFieldConfig\n) => ({\n label: config.label ?? field.label,\n defaultValue: config.defaultValue ?? field.defaultValue,\n placeholder: config.placeholder ?? field.placeholder\n});\n\nconst resolvePayloadPanelField = (\n field: PayloadPanelField,\n config: PayloadPanelFieldConfig | undefined\n): PayloadPanelField => {\n if (!config || !hasOwnConfigKeys(config)) return field;\n\n if (field.type === 'select') {\n return {\n ...field,\n ...resolveFieldBaseOverride(field, config),\n options: resolveOptionList(field.options, config)\n };\n }\n\n if (field.type === 'color') {\n return {\n ...field,\n ...resolveFieldBaseOverride(field, config),\n options: resolveOptionList(field.options ?? [], config)\n };\n }\n\n if (field.type === 'number') {\n return {\n ...field,\n ...resolveFieldBaseOverride(field, config),\n min: config.min ?? field.min,\n max: config.max ?? field.max,\n step: config.step ?? field.step\n };\n }\n\n return {\n ...field,\n ...resolveFieldBaseOverride(field, config)\n };\n};\n\n/**\n * 解析参数面板 schema。\n *\n * 这个纯函数只处理 schema 数据,不理解 DOM、Lexical 或具体命令;toolbar、hoverbar、\n * code block header 和 WebView host request 都应先走这里,保证默认 UI 和业务自绘同源。\n */\nexport const resolvePayloadPanelSchema = (\n panel: PayloadPanelSchema,\n config?: PayloadPanelConfig\n): PayloadPanelSchema => {\n const panelConfig = config?.[panel.id];\n\n if (!panelConfig || !hasOwnConfigKeys(panelConfig)) return panel;\n\n return {\n ...panel,\n title: panelConfig.title ?? panel.title,\n description: panelConfig.description ?? panel.description,\n fields: panel.fields.map((field) => resolvePayloadPanelField(\n field,\n panelConfig.fields?.[field.name]\n ))\n };\n};\n"],"names":["hasOwnConfigKeys","config","resolveOptionList","options","baseOptions","_a","optionByValue","option","includedOptions","_b","value","excludeValues","nextOptions","resolveFieldBaseOverride","field","resolvePayloadPanelField","resolvePayloadPanelSchema","panel","panelConfig"],"mappings":";AAUA,MAAMA,IAAmB,CAACC,MACxBA,MAAW,UAAa,OAAO,KAAKA,CAAM,EAAE,SAAS,GAGjDC,IAAoB,CACxBC,GACAF,MACG;;AACH,QAAMG,KAAcC,IAAAJ,EAAO,YAAP,QAAAI,EAAgB,SAASJ,EAAO,UAAUE,GACxDG,IAAgB,IAAI,IAAIF,EAAY,IAAI,CAACG,MAAW,CAACA,EAAO,OAAOA,CAAM,CAAC,CAAC,GAC3EC,KAAkBC,IAAAR,EAAO,kBAAP,QAAAQ,EAAsB,SAC1CR,EAAO,cAAc,QAAQ,CAACS,MAAU;AACxC,UAAMH,IAASD,EAAc,IAAII,CAAK;AAEtC,WAAOH,IAAS,CAACA,CAAM,IAAI,CAAA;AAAA,EAC7B,CAAC,IACCH,GACEO,IAAgB,IAAI,IAAIV,EAAO,iBAAiB,CAAA,CAAE,GAElDW,IADkBJ,EAAgB,OAAO,CAACD,MAAW,CAACI,EAAc,IAAIJ,EAAO,KAAK,CAAC,EACvD,IAAI,CAACA,MAAA;;AAAY;AAAA,MACnD,GAAGA;AAAA,MACH,SAAOF,IAAAJ,EAAO,iBAAP,gBAAAI,EAAsBE,EAAO,WAAUA,EAAO;AAAA,MACrD,SAAOE,IAAAR,EAAO,iBAAP,gBAAAQ,EAAsBF,EAAO,WAAUA,EAAO;AAAA,IAAA;AAAA,GACrD;AAMF,SAAOK,EAAY,SAAS,IAAIA,IAAcR;AAChD,GAEMS,IAA2B,CAC/BC,GACAb,OACI;AAAA,EACJ,OAAOA,EAAO,SAASa,EAAM;AAAA,EAC7B,cAAcb,EAAO,gBAAgBa,EAAM;AAAA,EAC3C,aAAab,EAAO,eAAea,EAAM;AAC3C,IAEMC,IAA2B,CAC/BD,GACAb,MAEI,CAACA,KAAU,CAACD,EAAiBC,CAAM,IAAUa,IAE7CA,EAAM,SAAS,WACV;AAAA,EACL,GAAGA;AAAA,EACH,GAAGD,EAAyBC,GAAOb,CAAM;AAAA,EACzC,SAASC,EAAkBY,EAAM,SAASb,CAAM;AAAA,IAIhDa,EAAM,SAAS,UACV;AAAA,EACL,GAAGA;AAAA,EACH,GAAGD,EAAyBC,GAAOb,CAAM;AAAA,EACzC,SAASC,EAAkBY,EAAM,WAAW,CAAA,GAAIb,CAAM;AAAA,IAItDa,EAAM,SAAS,WACV;AAAA,EACL,GAAGA;AAAA,EACH,GAAGD,EAAyBC,GAAOb,CAAM;AAAA,EACzC,KAAKA,EAAO,OAAOa,EAAM;AAAA,EACzB,KAAKb,EAAO,OAAOa,EAAM;AAAA,EACzB,MAAMb,EAAO,QAAQa,EAAM;AAAA,IAIxB;AAAA,EACL,GAAGA;AAAA,EACH,GAAGD,EAAyBC,GAAOb,CAAM;AAAA,GAUhCe,IAA4B,CACvCC,GACAhB,MACuB;AACvB,QAAMiB,IAAcjB,KAAA,gBAAAA,EAASgB,EAAM;AAEnC,SAAI,CAACC,KAAe,CAAClB,EAAiBkB,CAAW,IAAUD,IAEpD;AAAA,IACL,GAAGA;AAAA,IACH,OAAOC,EAAY,SAASD,EAAM;AAAA,IAClC,aAAaC,EAAY,eAAeD,EAAM;AAAA,IAC9C,QAAQA,EAAM,OAAO,IAAI,CAACH,MAAA;;AAAU,aAAAC;AAAA,QAClCD;AAAA,SACAT,IAAAa,EAAY,WAAZ,gBAAAb,EAAqBS,EAAM;AAAA,MAAI;AAAA,KAChC;AAAA,EAAA;AAEL;"}
1
+ {"version":3,"file":"core.js","sources":["../../core/src/content/index.ts"],"sourcesContent":["import type { EditorContent, EditorContentNode } from './type';\n\nconst invisibleTextPattern = /[\\u200B-\\u200D\\uFEFF]/g;\nconst htmlTagPattern = /<[^>]*>/g;\nconst blankHtmlEntityPattern = /&(?:nbsp|#160|#x0*a0);/gi;\nconst htmlEntityPattern = /&(?:[a-z\\d]+|#\\d+|#x[\\da-f]+);/gi;\nconst meaningfulHtmlElementNames = [\n 'img',\n 'video',\n 'audio',\n 'iframe',\n 'table',\n 'pre',\n 'code',\n 'hr',\n 'figure',\n 'canvas',\n 'svg',\n 'math'\n];\n\n/*\n * 这些节点即使当前没有普通文本,也代表用户主动插入了结构内容。\n * 后续新增非文本内容节点时优先补进这张表;纯段落、列表容器这类结构继续靠子节点判断。\n */\nconst meaningfulStructuredNodeTypes = new Set([\n 'bridgerte-divider',\n 'bridgerte-media',\n 'bridgerte-mention',\n 'code',\n 'horizontalrule',\n 'image',\n 'table',\n 'video'\n]);\n\nconst meaningfulHtmlElementPattern = new RegExp(\n `<(${meaningfulHtmlElementNames.join('|')})(?=[\\\\s>/])`,\n 'i'\n);\n\nconst hasMeaningfulText = (text: string | undefined): boolean => (\n Boolean(text?.replace(invisibleTextPattern, '').trim())\n);\n\nconst hasMeaningfulHtmlFallback = (html: string | undefined): boolean => {\n const htmlValue = html ?? '';\n\n if (!hasMeaningfulText(htmlValue)) return false;\n if (meaningfulHtmlElementPattern.test(htmlValue)) return true;\n\n /*\n * core 不能依赖 DOMParser,这里只做轻量兜底:去掉标签和空白实体后,\n * 其余实体按可见字符处理。需要完整 HTML 语义时使用 DOM 包的解析工具。\n */\n const textLikeContent = htmlValue\n .replace(htmlTagPattern, ' ')\n .replace(blankHtmlEntityPattern, ' ')\n .replace(htmlEntityPattern, 'x');\n\n return hasMeaningfulText(textLikeContent);\n};\n\nconst hasMeaningfulContentNode = (node: EditorContentNode | undefined): boolean => {\n if (!node) return false;\n if (hasMeaningfulText(node.text)) return true;\n if (meaningfulStructuredNodeTypes.has(node.type)) return true;\n\n return Boolean(node.children?.some(hasMeaningfulContentNode));\n};\n\n/**\n * 判断 BridgeRTE 内容快照是否为空。\n *\n * 函数只读取已生成的 `EditorContent` 字段,不触发 DOM 解析或编辑器序列化;调用方应在保存、\n * 提交或离开确认这类低频动作里配合 `editor.getContent()` 使用。\n */\nexport const isEditorContentEmpty = (\n content: Partial<EditorContent> | null | undefined\n): boolean => {\n if (!content) return true;\n if (hasMeaningfulText(content.plainText)) return false;\n if (content.assets?.length) return false;\n if (hasMeaningfulContentNode(content.json?.root)) return false;\n if (hasMeaningfulHtmlFallback(content.html)) return false;\n\n return true;\n};\n"],"names":["invisibleTextPattern","htmlTagPattern","blankHtmlEntityPattern","htmlEntityPattern","meaningfulHtmlElementNames","meaningfulStructuredNodeTypes","meaningfulHtmlElementPattern","hasMeaningfulText","text","hasMeaningfulHtmlFallback","html","htmlValue","textLikeContent","hasMeaningfulContentNode","node","_a","isEditorContentEmpty","content","_b"],"mappings":";;AAEA,MAAMA,IAAuB,0BACvBC,IAAiB,YACjBC,IAAyB,4BACzBC,IAAoB,oCACpBC,IAA6B;AAAA,EACjC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAMMC,wBAAoC,IAAI;AAAA,EAC5C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC,GAEKC,IAA+B,IAAI;AAAA,EACvC,KAAKF,EAA2B,KAAK,GAAG,CAAC;AAAA,EACzC;AACF,GAEMG,IAAoB,CAACC,MACzB,GAAQA,KAAA,QAAAA,EAAM,QAAQR,GAAsB,IAAI,SAG5CS,IAA4B,CAACC,MAAsC;AACvE,QAAMC,IAAYD,KAAQ;AAE1B,MAAI,CAACH,EAAkBI,CAAS,EAAG,QAAO;AAC1C,MAAIL,EAA6B,KAAKK,CAAS,EAAG,QAAO;AAMzD,QAAMC,IAAkBD,EACrB,QAAQV,GAAgB,GAAG,EAC3B,QAAQC,GAAwB,GAAG,EACnC,QAAQC,GAAmB,GAAG;AAEjC,SAAOI,EAAkBK,CAAe;AAC1C,GAEMC,IAA2B,CAACC,MAAiD;;AACjF,SAAKA,IACDP,EAAkBO,EAAK,IAAI,KAC3BT,EAA8B,IAAIS,EAAK,IAAI,IAAU,KAElD,IAAQC,IAAAD,EAAK,aAAL,QAAAC,EAAe,KAAKF,MAJjB;AAKpB,GAQaG,IAAuB,CAClCC,MACY;;AACZ,SAAKA,IACD,EAAAV,EAAkBU,EAAQ,SAAS,MACnCF,IAAAE,EAAQ,WAAR,QAAAF,EAAgB,UAChBF,GAAyBK,IAAAD,EAAQ,SAAR,gBAAAC,EAAc,IAAI,KAC3CT,EAA0BQ,EAAQ,IAAI,KAJrB;AAOvB;"}
package/dist/dom.cjs CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./index-BaOlPu8L.cjs"),t=require("./index-hd9Zi2DV.cjs");exports.createFloatingLayer=e.createFloatingLayer;exports.createRichTextEditor=e.createRichTextEditor;exports.createWebViewBridgeRuntime=e.createWebViewBridgeRuntime;exports.createRichTextToolbar=t.createRichTextToolbar;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./index-B_g23O7q.cjs"),t=require("./index-H5V0EMkq.cjs");exports.createFloatingLayer=e.createFloatingLayer;exports.createRichTextEditor=e.createRichTextEditor;exports.createWebViewBridgeRuntime=e.createWebViewBridgeRuntime;exports.createRichTextToolbar=t.createRichTextToolbar;exports.hasMeaningfulHtmlContent=t.hasMeaningfulHtmlContent;
2
2
  //# sourceMappingURL=dom.cjs.map
package/dist/dom.d.ts CHANGED
@@ -182,7 +182,7 @@ export type ToolbarGroupConfig = {
182
182
  /**
183
183
  * toolbar JSON 配置项。
184
184
  *
185
- * 字符串使用 `MenuItem.id`;特殊字符串 `|` 表示分割线,视觉保持和默认 group 分隔一致。
185
+ * 字符串使用 `MenuItem.id`;特殊字符串 `|` 表示分割线,收纳菜单用对象配置显式声明。
186
186
  */
187
187
  export type ToolbarKey = string | ToolbarGroupConfig;
188
188
  /**
@@ -513,7 +513,6 @@ export type SlashCommandItem = {
513
513
  icon?: string;
514
514
  description?: string;
515
515
  keywords?: string[];
516
- group?: string;
517
516
  requiresPayload?: boolean;
518
517
  payloadPanel?: PayloadPanelSchema;
519
518
  };
@@ -579,7 +578,6 @@ export type MenuItem = {
579
578
  command: EditorCommand;
580
579
  label: string;
581
580
  icon: string;
582
- group: 'text' | 'style' | 'block' | 'list' | 'align' | 'insert' | 'media' | 'table' | 'history' | 'view';
583
581
  requiresPayload?: boolean;
584
582
  payloadPanel?: PayloadPanelSchema;
585
583
  children?: MenuItem[];
@@ -1018,3 +1016,11 @@ export declare function createFloatingLayer(reference: HTMLElement, floating: HT
1018
1016
  */
1019
1017
  export declare function createRichTextEditor(container: HTMLElement, options?: RichTextEditorOptions): EditorAPI;
1020
1018
 
1019
+ /**
1020
+ * 判断一段 HTML 片段是否包含可保存的富文本内容。
1021
+ *
1022
+ * 这个工具会使用浏览器 template 解析 HTML,适合只拿到 HTML 字符串的业务表单;如果已经持有
1023
+ * `EditorContent`,优先使用 core 的 `isEditorContentEmpty()`,避免额外 DOM parse。
1024
+ */
1025
+ export declare const hasMeaningfulHtmlContent: (html: string) => boolean;
1026
+
package/dist/dom.js CHANGED
@@ -1,9 +1,10 @@
1
- import { c as r, a as t, b as c } from "./index-BwZ0II4h.js";
2
- import { c as i } from "./index-bN5Hs6-3.js";
1
+ import { c as t, a as r, b as o } from "./index-DyCMSFrm.js";
2
+ import { c as i, h as n } from "./index-BWi3d-Zp.js";
3
3
  export {
4
- r as createFloatingLayer,
5
- t as createRichTextEditor,
4
+ t as createFloatingLayer,
5
+ r as createRichTextEditor,
6
6
  i as createRichTextToolbar,
7
- c as createWebViewBridgeRuntime
7
+ o as createWebViewBridgeRuntime,
8
+ n as hasMeaningfulHtmlContent
8
9
  };
9
10
  //# sourceMappingURL=dom.js.map