utils.ts 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. import { Node, NodeType, ResolvedPos } from 'prosemirror-model'
  2. import { EditorState, Selection } from 'prosemirror-state'
  3. import { EditorView } from 'prosemirror-view'
  4. const equalNodeType = (nodeType: NodeType, node: Node) => {
  5. return Array.isArray(nodeType) && nodeType.indexOf(node.type) > -1 || node.type === nodeType
  6. }
  7. const findParentNodeClosestToPos = ($pos: ResolvedPos, predicate: (node: Node) => boolean) => {
  8. for(let i = $pos.depth; i > 0; i--) {
  9. const node = $pos.node(i)
  10. if(predicate(node)) {
  11. return {
  12. pos: i > 0 ? $pos.before(i) : 0,
  13. start: $pos.start(i),
  14. depth: i,
  15. node,
  16. }
  17. }
  18. }
  19. }
  20. export const findParentNode = (predicate: (node: Node) => boolean) => {
  21. return (_ref: Selection) => findParentNodeClosestToPos(_ref.$from, predicate)
  22. }
  23. export const findParentNodeOfType = (nodeType: NodeType) => {
  24. return (selection: Selection) => {
  25. return findParentNode((node: Node) => {
  26. return equalNodeType(nodeType, node)
  27. })(selection)
  28. }
  29. }
  30. export const isActiveOfParentNodeType = (nodeType: string, state: EditorState) => {
  31. const node = state.schema.nodes[nodeType]
  32. return !!findParentNodeOfType(node)(state.selection)
  33. }
  34. export const getMarkAttrs = (view: EditorView) => {
  35. const { selection, doc } = view.state
  36. const { from } = selection
  37. const node = doc.nodeAt(from)
  38. return node?.marks || []
  39. }
  40. export const getAttrValue = (view: EditorView, markType: string, attr: string) => {
  41. const marks = getMarkAttrs(view)
  42. for(const mark of marks) {
  43. if(mark.type.name === markType && mark.attrs[attr]) return mark.attrs[attr]
  44. }
  45. return null
  46. }
  47. export const isActiveMark = (view: EditorView, markType: string) => {
  48. const marks = getMarkAttrs(view)
  49. for(const mark of marks) {
  50. if(mark.type.name === markType) return true
  51. }
  52. return false
  53. }
  54. export const getAttrValueInSelection = (view: EditorView, attr: string) => {
  55. const { selection, doc } = view.state
  56. const { from, to } = selection
  57. let keepChecking = true
  58. let value = ''
  59. doc.nodesBetween(from, to, node => {
  60. if(keepChecking && node.attrs[attr]) {
  61. keepChecking = false
  62. value = node.attrs[attr]
  63. }
  64. return keepChecking
  65. })
  66. return value
  67. }
  68. export const getTextAttrs = (view: EditorView) => {
  69. const isBold = isActiveMark(view, 'strong')
  70. const isEm = isActiveMark(view, 'em')
  71. const isUnderline = isActiveMark(view, 'underline')
  72. const isStrikethrough = isActiveMark(view, 'strikethrough')
  73. const isSuperscript = isActiveMark(view, 'superscript')
  74. const isSubscript = isActiveMark(view, 'subscript')
  75. const isCode = isActiveMark(view, 'code')
  76. const color = getAttrValue(view, 'forecolor', 'color') || '#000'
  77. const backcolor = getAttrValue(view, 'backcolor', 'backcolor') || '#000'
  78. const fontsize = getAttrValue(view, 'fontsize', 'fontsize') || '12px'
  79. const fontname = getAttrValue(view, 'fontname', 'fontname') || '微软雅黑'
  80. const align = getAttrValueInSelection(view, 'align')
  81. const isBulletList = isActiveOfParentNodeType('bullet_list', view.state)
  82. const isOrderedList = isActiveOfParentNodeType('ordered_list', view.state)
  83. const isBlockquote = isActiveOfParentNodeType('blockquote', view.state)
  84. return {
  85. bold: isBold,
  86. em: isEm,
  87. underline: isUnderline,
  88. strikethrough: isStrikethrough,
  89. superscript: isSuperscript,
  90. subscript: isSubscript,
  91. code: isCode,
  92. color: color,
  93. backcolor: backcolor,
  94. fontsize: fontsize,
  95. fontname: fontname,
  96. align: align,
  97. bulletList: isBulletList,
  98. orderedList: isOrderedList,
  99. blockquote: isBlockquote,
  100. }
  101. }
  102. export type TextAttrs = ReturnType<typeof getTextAttrs>