@logicflow/extension 2.0.0-beta.2 → 2.0.0-beta.4

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 (44) hide show
  1. package/.turbo/turbo-build.log +7 -7
  2. package/dist/index.min.js +2 -2
  3. package/es/components/menu/index.d.ts +1 -1
  4. package/es/components/menu/index.js +9 -10
  5. package/es/components/menu/index.js.map +1 -1
  6. package/es/index.d.ts +1 -0
  7. package/es/index.js +1 -0
  8. package/es/index.js.map +1 -1
  9. package/es/insert-node-in-polyline/index.js +3 -3
  10. package/es/insert-node-in-polyline/index.js.map +1 -1
  11. package/es/materials/node-selection/index.d.ts +2 -1
  12. package/es/materials/node-selection/index.js +64 -56
  13. package/es/materials/node-selection/index.js.map +1 -1
  14. package/es/tools/snapshot/index.d.ts +101 -11
  15. package/es/tools/snapshot/index.js +331 -147
  16. package/es/tools/snapshot/index.js.map +1 -1
  17. package/es/tools/snapshot/utils.d.ts +35 -0
  18. package/es/tools/snapshot/utils.js +238 -0
  19. package/es/tools/snapshot/utils.js.map +1 -0
  20. package/lib/components/menu/index.d.ts +1 -1
  21. package/lib/components/menu/index.js +9 -10
  22. package/lib/components/menu/index.js.map +1 -1
  23. package/lib/index.d.ts +1 -0
  24. package/lib/index.js +1 -0
  25. package/lib/index.js.map +1 -1
  26. package/lib/insert-node-in-polyline/index.js +2 -2
  27. package/lib/insert-node-in-polyline/index.js.map +1 -1
  28. package/lib/materials/node-selection/index.d.ts +2 -1
  29. package/lib/materials/node-selection/index.js +63 -55
  30. package/lib/materials/node-selection/index.js.map +1 -1
  31. package/lib/tools/snapshot/index.d.ts +101 -11
  32. package/lib/tools/snapshot/index.js +331 -147
  33. package/lib/tools/snapshot/index.js.map +1 -1
  34. package/lib/tools/snapshot/utils.d.ts +35 -0
  35. package/lib/tools/snapshot/utils.js +247 -0
  36. package/lib/tools/snapshot/utils.js.map +1 -0
  37. package/package.json +7 -4
  38. package/src/components/menu/index.ts +16 -13
  39. package/src/index.ts +1 -0
  40. package/src/insert-node-in-polyline/index.ts +3 -3
  41. package/src/materials/node-selection/index.ts +72 -69
  42. package/src/tools/snapshot/README.md +130 -5
  43. package/src/tools/snapshot/index.ts +264 -98
  44. package/src/tools/snapshot/utils.ts +163 -0
@@ -0,0 +1,163 @@
1
+ /**
2
+ * 图片缓存, 已请求过的图片直接从缓存中获取
3
+ */
4
+ const imageCache: Record<string, string> = {}
5
+
6
+ /**
7
+ * 当获取图片失败时会返回失败信息,是 text/plain 类型的数据
8
+ * @param str - 图片内容
9
+ * @returns
10
+ */
11
+ export function isTextPlainBase64(str: string) {
12
+ return str.startsWith('data:text/plain')
13
+ }
14
+
15
+ /**
16
+ * 将网络图片转为 base64
17
+ * @param url - 图片地址
18
+ * @returns
19
+ */
20
+ export async function convertImageToBase64(url: string): Promise<string> {
21
+ if (imageCache[url]) {
22
+ return imageCache[url]
23
+ }
24
+ return new Promise((resolve, reject) => {
25
+ try {
26
+ fetch(url)
27
+ .then((response) => response.blob())
28
+ .then((blob) => {
29
+ const reader = new FileReader()
30
+ reader.onloadend = () => {
31
+ resolve((imageCache[url] = reader.result as string))
32
+ }
33
+ reader.onerror = reject
34
+ reader.readAsDataURL(blob)
35
+ })
36
+ .catch(() => {
37
+ resolve((imageCache[url] = url))
38
+ })
39
+ } catch (error) {
40
+ // 如果转换失败,后续大概率仍然会失败,因此直接缓存
41
+ return (imageCache[url] = url)
42
+ }
43
+ })
44
+ }
45
+
46
+ /**
47
+ * 使用 base64 的图片替换 img 标签的 src 或 image 标签的 href
48
+ * @param node - html 节点或 svg 节点
49
+ */
50
+ export async function updateImageSrcOrHrefWithBase64Image(
51
+ node: HTMLImageElement | SVGImageElement,
52
+ attrName: 'src' | 'href',
53
+ ) {
54
+ try {
55
+ const url = node.getAttribute(attrName) || ''
56
+ // 已经是 base64 图片,不需要处理
57
+ if (url.startsWith('data:')) {
58
+ return
59
+ }
60
+ const base64Image = await convertImageToBase64(url)
61
+ if (isTextPlainBase64(base64Image)) {
62
+ return
63
+ }
64
+ node.setAttribute(attrName, base64Image)
65
+ } catch (error) {
66
+ console.error(error)
67
+ }
68
+ }
69
+
70
+ /**
71
+ * 使用 base64 的图片替换背景图片
72
+ * @param node - html 节点
73
+ * @param styleAttr - 样式属性名称
74
+ */
75
+ export async function updateBackgroundImageWithBase64Image(
76
+ node: HTMLElement,
77
+ url: string,
78
+ ) {
79
+ try {
80
+ // 已经是 base64 图片,不需要处理
81
+ if (url.startsWith('data:')) {
82
+ return
83
+ }
84
+ const base64Image = await convertImageToBase64(url)
85
+ if (isTextPlainBase64(base64Image)) {
86
+ return
87
+ }
88
+ node.style.backgroundImage = `url(${base64Image})`
89
+ } catch (error) {
90
+ console.error(error)
91
+ }
92
+ }
93
+
94
+ /**
95
+ * 更新图片数据
96
+ * @param node - 节点
97
+ */
98
+ export async function updateImageSource(node: HTMLElement | SVGElement) {
99
+ const nodes = [node]
100
+ let nodePtr
101
+ const promises: any[] = []
102
+ while (nodes.length) {
103
+ nodePtr = nodes.shift()
104
+ if (nodePtr.children.length) {
105
+ nodes.push(...nodePtr.children)
106
+ }
107
+ if (nodePtr instanceof HTMLElement) {
108
+ // 如果有 style 的 background, backgroundImage 属性中有 url(xxx), 尝试替换为 base64 图片
109
+ const { background, backgroundImage } = nodePtr.style
110
+ const backgroundUrlMatch = background.match(/url\(["']?(.*?)["']?\)/)
111
+ if (backgroundUrlMatch && backgroundUrlMatch[1]) {
112
+ const imageUrl = backgroundUrlMatch[1]
113
+ promises.push(updateBackgroundImageWithBase64Image(nodePtr, imageUrl))
114
+ }
115
+ const backgroundImageUrlMatch = backgroundImage.match(
116
+ /url\(["']?(.*?)["']?\)/,
117
+ )
118
+ if (backgroundImageUrlMatch && backgroundImageUrlMatch[1]) {
119
+ const imageUrl = backgroundImageUrlMatch[1]
120
+ promises.push(updateBackgroundImageWithBase64Image(nodePtr, imageUrl))
121
+ }
122
+ }
123
+ // 如果有 img 和 image 标签,尝试将 src 和 href 替换为 base64 图片
124
+ if (nodePtr instanceof HTMLImageElement) {
125
+ promises.push(updateImageSrcOrHrefWithBase64Image(nodePtr, 'src'))
126
+ } else if (nodePtr instanceof SVGImageElement) {
127
+ promises.push(updateImageSrcOrHrefWithBase64Image(nodePtr, 'href'))
128
+ }
129
+ }
130
+ await Promise.all(promises)
131
+ }
132
+
133
+ /**
134
+ * 重新复制canvas 用于在不裁剪原canvas的基础上通过拉伸方式达到自定义宽高目的
135
+ * @param originCanvas HTMLCanvasElement
136
+ * @param targetWidth number
137
+ * @param targetHeight number
138
+ */
139
+ export function copyCanvas(
140
+ originCanvas: HTMLCanvasElement,
141
+ targetWidth: number,
142
+ targetHeight: number,
143
+ ): HTMLCanvasElement {
144
+ const newCanvas = document.createElement('canvas')
145
+ newCanvas.width = targetWidth
146
+ newCanvas.height = targetHeight
147
+ const newCtx = newCanvas.getContext('2d')
148
+ if (newCtx) {
149
+ // 注意: 自定义宽高时,可能会拉伸图形,这时候padding也会被拉伸导致不准确
150
+ newCtx.drawImage(
151
+ originCanvas,
152
+ 0,
153
+ 0,
154
+ originCanvas.width,
155
+ originCanvas.height,
156
+ 0,
157
+ 0,
158
+ targetWidth,
159
+ targetHeight,
160
+ )
161
+ }
162
+ return newCanvas
163
+ }