marks.ts 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  1. import { marks } from 'prosemirror-schema-basic'
  2. import type { MarkSpec } from 'prosemirror-model'
  3. // ===== 原有定义 =====
  4. const subscript: MarkSpec = {
  5. excludes: 'subscript',
  6. parseDOM: [
  7. { tag: 'sub' },
  8. {
  9. style: 'vertical-align',
  10. getAttrs: value => value === 'sub' && null
  11. },
  12. ],
  13. toDOM: () => ['sub', 0],
  14. }
  15. const superscript: MarkSpec = {
  16. excludes: 'superscript',
  17. parseDOM: [
  18. { tag: 'sup' },
  19. {
  20. style: 'vertical-align',
  21. getAttrs: value => value === 'super' && null
  22. },
  23. ],
  24. toDOM: () => ['sup', 0],
  25. }
  26. const strikethrough: MarkSpec = {
  27. parseDOM: [
  28. { tag: 'strike' },
  29. {
  30. style: 'text-decoration',
  31. getAttrs: value => value === 'line-through' && null
  32. },
  33. {
  34. style: 'text-decoration-line',
  35. getAttrs: value => value === 'line-through' && null
  36. },
  37. ],
  38. toDOM: () => ['span', { style: 'text-decoration-line: line-through;' }, 0],
  39. }
  40. const underline: MarkSpec = {
  41. parseDOM: [
  42. { tag: 'u' },
  43. {
  44. style: 'text-decoration',
  45. getAttrs: value => value === 'underline' && null
  46. },
  47. {
  48. style: 'text-decoration-line',
  49. getAttrs: value => value === 'underline' && null
  50. },
  51. ],
  52. toDOM: () => ['span', { style: 'text-decoration: underline;' }, 0],
  53. }
  54. const forecolor: MarkSpec = {
  55. attrs: { color: {} },
  56. inline: true,
  57. group: 'inline',
  58. parseDOM: [
  59. {
  60. style: 'color',
  61. getAttrs: color => color ? { color } : {}
  62. },
  63. ],
  64. toDOM: mark => {
  65. const { color } = mark.attrs
  66. let style = ''
  67. if (color) style += `color: ${color};`
  68. return ['span', { style }, 0]
  69. },
  70. }
  71. const backcolor: MarkSpec = {
  72. attrs: { backcolor: {} },
  73. inline: true,
  74. group: 'inline',
  75. parseDOM: [
  76. {
  77. style: 'background-color',
  78. getAttrs: backcolor => backcolor ? { backcolor } : {}
  79. },
  80. ],
  81. toDOM: mark => {
  82. const { backcolor } = mark.attrs
  83. let style = ''
  84. if (backcolor) style += `background-color: ${backcolor};`
  85. return ['span', { style }, 0]
  86. },
  87. }
  88. const fontsize: MarkSpec = {
  89. attrs: { fontsize: {} },
  90. inline: true,
  91. group: 'inline',
  92. parseDOM: [
  93. {
  94. style: 'font-size',
  95. getAttrs: fontsize => fontsize ? { fontsize } : {}
  96. },
  97. ],
  98. toDOM: mark => {
  99. const { fontsize } = mark.attrs
  100. let style = ''
  101. if (fontsize) style += `font-size: ${fontsize};`
  102. return ['span', { style }, 0]
  103. },
  104. }
  105. const fontname: MarkSpec = {
  106. attrs: { fontname: {} },
  107. inline: true,
  108. group: 'inline',
  109. parseDOM: [
  110. {
  111. style: 'font-family',
  112. getAttrs: fontname => {
  113. return { fontname: fontname && typeof fontname === 'string' ? fontname.replace(/["']/g, '') : '' }
  114. }
  115. },
  116. ],
  117. toDOM: mark => {
  118. const { fontname } = mark.attrs
  119. let style = ''
  120. if (fontname) style += `font-family: ${fontname};`
  121. return ['span', { style }, 0]
  122. },
  123. }
  124. const link: MarkSpec = {
  125. attrs: {
  126. href: {},
  127. title: { default: null },
  128. target: { default: '_blank' },
  129. },
  130. inclusive: false,
  131. parseDOM: [
  132. {
  133. tag: 'a[href]',
  134. getAttrs: dom => {
  135. const href = (dom as HTMLElement).getAttribute('href')
  136. const title = (dom as HTMLElement).getAttribute('title')
  137. return { href, title }
  138. }
  139. },
  140. ],
  141. toDOM: node => ['a', node.attrs, 0],
  142. }
  143. const mark: MarkSpec = {
  144. attrs: { index: { default: null } },
  145. parseDOM: [
  146. {
  147. tag: 'mark',
  148. getAttrs: dom => {
  149. const index = (dom as HTMLElement).dataset.index
  150. return { index }
  151. }
  152. },
  153. ],
  154. toDOM: node => ['mark', { 'data-index': node.attrs.index }, 0],
  155. }
  156. // ===== 新增 marks =====
  157. // 通用 font-weight(如 100, 200, bold, bolder 等)
  158. const fontWeight: MarkSpec = {
  159. attrs: { fontWeight: {} },
  160. inline: true,
  161. group: 'inline',
  162. parseDOM: [
  163. {
  164. style: 'font-weight',
  165. getAttrs: value => value ? { fontWeight: value } : {}
  166. }
  167. ],
  168. toDOM: mark => {
  169. const { fontWeight } = mark.attrs
  170. let style = ''
  171. if (fontWeight) style += `font-weight: ${fontWeight};`
  172. return ['span', { style }, 0]
  173. }
  174. }
  175. // 通用 font-style(如 italic, oblique, normal)
  176. const fontStyle: MarkSpec = {
  177. attrs: { fontStyle: {} },
  178. inline: true,
  179. group: 'inline',
  180. parseDOM: [
  181. {
  182. style: 'font-style',
  183. getAttrs: value => value ? { fontStyle: value } : {}
  184. }
  185. ],
  186. toDOM: mark => {
  187. const { fontStyle } = mark.attrs
  188. let style = ''
  189. if (fontStyle) style += `font-style: ${fontStyle};`
  190. return ['span', { style }, 0]
  191. }
  192. }
  193. // 通用 text-decoration(可包含 underline, overline, line-through 等组合)
  194. const textDecoration: MarkSpec = {
  195. attrs: { textDecoration: {} },
  196. inline: true,
  197. group: 'inline',
  198. parseDOM: [
  199. {
  200. style: 'text-decoration',
  201. getAttrs: value => value ? { textDecoration: value } : {}
  202. },
  203. {
  204. style: 'text-decoration-line',
  205. getAttrs: value => value ? { textDecoration: value } : {}
  206. }
  207. ],
  208. toDOM: mark => {
  209. const { textDecoration } = mark.attrs
  210. let style = ''
  211. if (textDecoration) style += `text-decoration: ${textDecoration};`
  212. return ['span', { style }, 0]
  213. }
  214. }
  215. // 通用 vertical-align(支持 baseline, sub, super, top, middle, bottom, 长度值等)
  216. const verticalAlign: MarkSpec = {
  217. attrs: { verticalAlign: {} },
  218. inline: true,
  219. group: 'inline',
  220. parseDOM: [
  221. {
  222. style: 'vertical-align',
  223. getAttrs: value => value ? { verticalAlign: value } : {}
  224. }
  225. ],
  226. toDOM: mark => {
  227. const { verticalAlign } = mark.attrs
  228. let style = ''
  229. if (verticalAlign) style += `vertical-align: ${verticalAlign};`
  230. return ['span', { style }, 0]
  231. }
  232. }
  233. // letter-spacing
  234. const letterSpacing: MarkSpec = {
  235. attrs: { letterSpacing: {} },
  236. inline: true,
  237. group: 'inline',
  238. parseDOM: [
  239. {
  240. style: 'letter-spacing',
  241. getAttrs: value => value ? { letterSpacing: value } : {}
  242. }
  243. ],
  244. toDOM: mark => {
  245. const { letterSpacing } = mark.attrs
  246. let style = ''
  247. if (letterSpacing) style += `letter-spacing: ${letterSpacing};`
  248. return ['span', { style }, 0]
  249. }
  250. }
  251. // text-shadow
  252. const textShadow: MarkSpec = {
  253. attrs: { textShadow: {} },
  254. inline: true,
  255. group: 'inline',
  256. parseDOM: [
  257. {
  258. style: 'text-shadow',
  259. getAttrs: value => value ? { textShadow: value } : {}
  260. }
  261. ],
  262. toDOM: mark => {
  263. const { textShadow } = mark.attrs
  264. let style = ''
  265. if (textShadow) style += `text-shadow: ${textShadow};`
  266. return ['span', { style }, 0]
  267. }
  268. }
  269. // 从 prosemirror-schema-basic 获取的默认 marks
  270. const { em, strong, code } = marks
  271. export default {
  272. em,
  273. strong,
  274. code,
  275. fontsize,
  276. fontname,
  277. forecolor,
  278. backcolor,
  279. subscript,
  280. superscript,
  281. strikethrough,
  282. underline,
  283. link,
  284. mark,
  285. // 新增
  286. fontWeight,
  287. fontStyle,
  288. textDecoration,
  289. verticalAlign,
  290. letterSpacing,
  291. textShadow,
  292. }