usePasteTextClipboardData.ts 3.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. import { storeToRefs } from 'pinia'
  2. import { useKeyboardStore } from '@/store'
  3. import { pasteCustomClipboardString } from '@/utils/clipboard'
  4. import { parseText2Paragraphs } from '@/utils/textParser'
  5. import { getImageDataURL, isSVGString, svg2File } from '@/utils/image'
  6. import { isValidURL } from '@/utils/common'
  7. import useCreateElement from '@/hooks/useCreateElement'
  8. import useAddSlidesOrElements from '@/hooks/useAddSlidesOrElements'
  9. interface PasteTextClipboardDataOptions {
  10. onlySlide?: boolean
  11. onlyElements?: boolean
  12. }
  13. /**
  14. * 判断图片URL字符串
  15. *
  16. * !!!注意,你需要判断允许哪些来源的图片地址被匹配,然后自行编写正则表达式
  17. * !!!必须确保图片来源都是合法、可靠、可控、无访问限制的
  18. */
  19. const isValidImgURL = (url: string) => {
  20. const pexels = /^https?:\/\/(?:[a-zA-Z0-9-]+\.)*pexels\.com\/[^\s]+\.(?:jpg|jpeg|png|svg|webp)(?:\?.*)?$/i.test(url)
  21. const pptist = /^https?:\/\/(?:[a-zA-Z0-9-]+\.)*pptist\.cn\/[^\s]+\.(?:jpg|jpeg|png|svg|webp)(?:\?.*)?$/i.test(url)
  22. return pexels || pptist
  23. }
  24. export default () => {
  25. const { shiftKeyState } = storeToRefs(useKeyboardStore())
  26. const { createTextElement, createImageElement } = useCreateElement()
  27. const { addElementsFromData, addSlidesFromData } = useAddSlidesOrElements()
  28. /**
  29. * 粘贴普通文本:创建为新的文本元素
  30. * @param text 文本
  31. */
  32. const createTextElementFromClipboard = (text: string) => {
  33. createTextElement({
  34. left: 0,
  35. top: 0,
  36. width: 600,
  37. height: 50,
  38. }, { content: text })
  39. }
  40. /**
  41. * 解析剪贴板内容,根据解析结果选择合适的粘贴方式
  42. * @param text 剪贴板内容
  43. * @param options 配置项:onlySlide -- 仅处理页面粘贴;onlyElements -- 仅处理元素粘贴;
  44. */
  45. const pasteTextClipboardData = (text: string, options?: PasteTextClipboardDataOptions) => {
  46. const onlySlide = options?.onlySlide || false
  47. const onlyElements = options?.onlyElements || false
  48. const clipboardData = pasteCustomClipboardString(text)
  49. // 元素或页面
  50. if (typeof clipboardData === 'object') {
  51. const { type, data } = clipboardData
  52. if (type === 'elements' && !onlySlide) addElementsFromData(data)
  53. else if (type === 'slides' && !onlyElements) addSlidesFromData(data)
  54. }
  55. // 普通文本
  56. else if (!onlyElements && !onlySlide) {
  57. // 普通文字
  58. if (shiftKeyState.value) {
  59. const string = parseText2Paragraphs(clipboardData)
  60. createTextElementFromClipboard(string)
  61. }
  62. else {
  63. // 尝试检查是否为图片地址链接
  64. if (isValidImgURL(clipboardData)) {
  65. createImageElement(clipboardData)
  66. }
  67. // 尝试检查是否为超链接
  68. else if (isValidURL(clipboardData)) {
  69. createTextElementFromClipboard(`<a href="${clipboardData}" title="${clipboardData}" target="_blank">${clipboardData}</a>`)
  70. }
  71. // 尝试检查是否为SVG代码
  72. else if (isSVGString(clipboardData)) {
  73. const file = svg2File(clipboardData)
  74. getImageDataURL(file).then(dataURL => createImageElement(dataURL))
  75. }
  76. // 普通文字
  77. else {
  78. const string = parseText2Paragraphs(clipboardData)
  79. createTextElementFromClipboard(string)
  80. }
  81. }
  82. }
  83. }
  84. return {
  85. pasteTextClipboardData,
  86. }
  87. }