@difizen/libro-core 0.0.2-alpha.0

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 (312) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +3 -0
  3. package/es/add-cell/index.d.ts +4 -0
  4. package/es/add-cell/index.d.ts.map +1 -0
  5. package/es/add-cell/index.js +3 -0
  6. package/es/add-cell/index.less +38 -0
  7. package/es/add-cell/libro-add-cell-module.d.ts +3 -0
  8. package/es/add-cell/libro-add-cell-module.d.ts.map +1 -0
  9. package/es/add-cell/libro-add-cell-module.js +4 -0
  10. package/es/add-cell/libro-add-cell-slot-contribution.d.ts +12 -0
  11. package/es/add-cell/libro-add-cell-slot-contribution.d.ts.map +1 -0
  12. package/es/add-cell/libro-add-cell-slot-contribution.js +53 -0
  13. package/es/add-cell/libro-add-cell-view.d.ts +21 -0
  14. package/es/add-cell/libro-add-cell-view.d.ts.map +1 -0
  15. package/es/add-cell/libro-add-cell-view.js +129 -0
  16. package/es/cell/index.d.ts +10 -0
  17. package/es/cell/index.d.ts.map +1 -0
  18. package/es/cell/index.js +9 -0
  19. package/es/cell/libro-cell-contribution.d.ts +13 -0
  20. package/es/cell/libro-cell-contribution.d.ts.map +1 -0
  21. package/es/cell/libro-cell-contribution.js +41 -0
  22. package/es/cell/libro-cell-model.d.ts +19 -0
  23. package/es/cell/libro-cell-model.d.ts.map +1 -0
  24. package/es/cell/libro-cell-model.js +103 -0
  25. package/es/cell/libro-cell-module.d.ts +10 -0
  26. package/es/cell/libro-cell-module.d.ts.map +1 -0
  27. package/es/cell/libro-cell-module.js +30 -0
  28. package/es/cell/libro-cell-protocol.d.ts +42 -0
  29. package/es/cell/libro-cell-protocol.d.ts.map +1 -0
  30. package/es/cell/libro-cell-protocol.js +11 -0
  31. package/es/cell/libro-cell-service.d.ts +28 -0
  32. package/es/cell/libro-cell-service.d.ts.map +1 -0
  33. package/es/cell/libro-cell-service.js +242 -0
  34. package/es/cell/libro-cell-view.d.ts +65 -0
  35. package/es/cell/libro-cell-view.d.ts.map +1 -0
  36. package/es/cell/libro-cell-view.js +191 -0
  37. package/es/cell/libro-edit-cell-view.d.ts +32 -0
  38. package/es/cell/libro-edit-cell-view.d.ts.map +1 -0
  39. package/es/cell/libro-edit-cell-view.js +72 -0
  40. package/es/cell/libro-executable-cell-model.d.ts +14 -0
  41. package/es/cell/libro-executable-cell-model.d.ts.map +1 -0
  42. package/es/cell/libro-executable-cell-model.js +7 -0
  43. package/es/cell/libro-executable-cell-view.d.ts +27 -0
  44. package/es/cell/libro-executable-cell-view.d.ts.map +1 -0
  45. package/es/cell/libro-executable-cell-view.js +66 -0
  46. package/es/cell/libro-markdown-cell-model.d.ts +9 -0
  47. package/es/cell/libro-markdown-cell-model.d.ts.map +1 -0
  48. package/es/cell/libro-markdown-cell-model.js +7 -0
  49. package/es/collapse-service.d.ts +36 -0
  50. package/es/collapse-service.d.ts.map +1 -0
  51. package/es/collapse-service.js +55 -0
  52. package/es/command/document-commands.d.ts +6 -0
  53. package/es/command/document-commands.d.ts.map +1 -0
  54. package/es/command/document-commands.js +13 -0
  55. package/es/command/index.d.ts +7 -0
  56. package/es/command/index.d.ts.map +1 -0
  57. package/es/command/index.js +6 -0
  58. package/es/command/kernel-command.d.ts +5 -0
  59. package/es/command/kernel-command.d.ts.map +1 -0
  60. package/es/command/kernel-command.js +39 -0
  61. package/es/command/libro-command-contribution.d.ts +14 -0
  62. package/es/command/libro-command-contribution.d.ts.map +1 -0
  63. package/es/command/libro-command-contribution.js +1751 -0
  64. package/es/command/libro-command-register.d.ts +22 -0
  65. package/es/command/libro-command-register.d.ts.map +1 -0
  66. package/es/command/libro-command-register.js +105 -0
  67. package/es/command/module.d.ts +3 -0
  68. package/es/command/module.d.ts.map +1 -0
  69. package/es/command/module.js +4 -0
  70. package/es/command/notebook-commands.d.ts +6 -0
  71. package/es/command/notebook-commands.d.ts.map +1 -0
  72. package/es/command/notebook-commands.js +468 -0
  73. package/es/components/cell-protocol.d.ts +20 -0
  74. package/es/components/cell-protocol.d.ts.map +1 -0
  75. package/es/components/cell-protocol.js +4 -0
  76. package/es/components/dnd-cell-item-render.d.ts +12 -0
  77. package/es/components/dnd-cell-item-render.d.ts.map +1 -0
  78. package/es/components/dnd-cell-item-render.js +253 -0
  79. package/es/components/dnd-component/custom-drag-layer.d.ts +9 -0
  80. package/es/components/dnd-component/custom-drag-layer.d.ts.map +1 -0
  81. package/es/components/dnd-component/custom-drag-layer.js +141 -0
  82. package/es/components/dnd-component/default-dnd-content.d.ts +10 -0
  83. package/es/components/dnd-component/default-dnd-content.d.ts.map +1 -0
  84. package/es/components/dnd-component/default-dnd-content.js +257 -0
  85. package/es/components/dnd-component/dnd-context.d.ts +3 -0
  86. package/es/components/dnd-component/dnd-context.d.ts.map +1 -0
  87. package/es/components/dnd-component/dnd-context.js +20 -0
  88. package/es/components/dnd-component/dnd-list.d.ts +10 -0
  89. package/es/components/dnd-component/dnd-list.d.ts.map +1 -0
  90. package/es/components/dnd-component/dnd-list.js +115 -0
  91. package/es/components/dnd-component/index.d.ts +5 -0
  92. package/es/components/dnd-component/index.d.ts.map +1 -0
  93. package/es/components/dnd-component/index.js +4 -0
  94. package/es/components/index.d.ts +6 -0
  95. package/es/components/index.d.ts.map +1 -0
  96. package/es/components/index.js +5 -0
  97. package/es/components/libro-component.d.ts +5 -0
  98. package/es/components/libro-component.d.ts.map +1 -0
  99. package/es/components/libro-component.js +35 -0
  100. package/es/components/libro-side-toolbar-menu.d.ts +21 -0
  101. package/es/components/libro-side-toolbar-menu.d.ts.map +1 -0
  102. package/es/components/libro-side-toolbar-menu.js +58 -0
  103. package/es/components/libro-view-header.d.ts +3 -0
  104. package/es/components/libro-view-header.d.ts.map +1 -0
  105. package/es/components/libro-view-header.js +37 -0
  106. package/es/configuration/libro-configuration-contribution.d.ts +5 -0
  107. package/es/configuration/libro-configuration-contribution.d.ts.map +1 -0
  108. package/es/configuration/libro-configuration-contribution.js +24 -0
  109. package/es/configuration/libro-configuration.d.ts +10 -0
  110. package/es/configuration/libro-configuration.d.ts.map +1 -0
  111. package/es/configuration/libro-configuration.js +81 -0
  112. package/es/content/index.d.ts +5 -0
  113. package/es/content/index.d.ts.map +1 -0
  114. package/es/content/index.js +4 -0
  115. package/es/content/libro-content-contribution.d.ts +11 -0
  116. package/es/content/libro-content-contribution.d.ts.map +1 -0
  117. package/es/content/libro-content-contribution.js +32 -0
  118. package/es/content/libro-content-module.d.ts +3 -0
  119. package/es/content/libro-content-module.d.ts.map +1 -0
  120. package/es/content/libro-content-module.js +5 -0
  121. package/es/content/libro-content-protocol.d.ts +8 -0
  122. package/es/content/libro-content-protocol.d.ts.map +1 -0
  123. package/es/content/libro-content-protocol.js +2 -0
  124. package/es/content/libro-content-service.d.ts +9 -0
  125. package/es/content/libro-content-service.d.ts.map +1 -0
  126. package/es/content/libro-content-service.js +35 -0
  127. package/es/index.d.ts +20 -0
  128. package/es/index.d.ts.map +1 -0
  129. package/es/index.js +19 -0
  130. package/es/index.less +682 -0
  131. package/es/libro-context-key.d.ts +22 -0
  132. package/es/libro-context-key.d.ts.map +1 -0
  133. package/es/libro-context-key.js +80 -0
  134. package/es/libro-keybind-registry.d.ts +5 -0
  135. package/es/libro-keybind-registry.d.ts.map +1 -0
  136. package/es/libro-keybind-registry.js +68 -0
  137. package/es/libro-model.d.ts +129 -0
  138. package/es/libro-model.d.ts.map +1 -0
  139. package/es/libro-model.js +803 -0
  140. package/es/libro-protocol.d.ts +241 -0
  141. package/es/libro-protocol.d.ts.map +1 -0
  142. package/es/libro-protocol.js +34 -0
  143. package/es/libro-service.d.ts +34 -0
  144. package/es/libro-service.d.ts.map +1 -0
  145. package/es/libro-service.js +180 -0
  146. package/es/libro-view-tracker.d.ts +6 -0
  147. package/es/libro-view-tracker.d.ts.map +1 -0
  148. package/es/libro-view-tracker.js +13 -0
  149. package/es/libro-view.d.ts +151 -0
  150. package/es/libro-view.d.ts.map +1 -0
  151. package/es/libro-view.js +1963 -0
  152. package/es/material-from-designer.d.ts +27 -0
  153. package/es/material-from-designer.d.ts.map +1 -0
  154. package/es/material-from-designer.js +550 -0
  155. package/es/module.d.ts +3 -0
  156. package/es/module.d.ts.map +1 -0
  157. package/es/module.js +55 -0
  158. package/es/output/index.d.ts +6 -0
  159. package/es/output/index.d.ts.map +1 -0
  160. package/es/output/index.js +5 -0
  161. package/es/output/output-area.d.ts +51 -0
  162. package/es/output/output-area.d.ts.map +1 -0
  163. package/es/output/output-area.js +346 -0
  164. package/es/output/output-contribution.d.ts +11 -0
  165. package/es/output/output-contribution.d.ts.map +1 -0
  166. package/es/output/output-contribution.js +31 -0
  167. package/es/output/output-model.d.ts +27 -0
  168. package/es/output/output-model.d.ts.map +1 -0
  169. package/es/output/output-model.js +95 -0
  170. package/es/output/output-module.d.ts +3 -0
  171. package/es/output/output-module.d.ts.map +1 -0
  172. package/es/output/output-module.js +6 -0
  173. package/es/output/output-protocol.d.ts +130 -0
  174. package/es/output/output-protocol.d.ts.map +1 -0
  175. package/es/output/output-protocol.js +18 -0
  176. package/es/slot/index.d.ts +5 -0
  177. package/es/slot/index.d.ts.map +1 -0
  178. package/es/slot/index.js +4 -0
  179. package/es/slot/libro-slot-manager.d.ts +13 -0
  180. package/es/slot/libro-slot-manager.d.ts.map +1 -0
  181. package/es/slot/libro-slot-manager.js +57 -0
  182. package/es/slot/libro-slot-protocol.d.ts +19 -0
  183. package/es/slot/libro-slot-protocol.d.ts.map +1 -0
  184. package/es/slot/libro-slot-protocol.js +5 -0
  185. package/es/slot/libro-slot-view.d.ts +9 -0
  186. package/es/slot/libro-slot-view.d.ts.map +1 -0
  187. package/es/slot/libro-slot-view.js +81 -0
  188. package/es/slot/module.d.ts +3 -0
  189. package/es/slot/module.d.ts.map +1 -0
  190. package/es/slot/module.js +5 -0
  191. package/es/theme/libro-color-registry.d.ts +6 -0
  192. package/es/theme/libro-color-registry.d.ts.map +1 -0
  193. package/es/theme/libro-color-registry.js +494 -0
  194. package/es/toolbar/change-cell-to-selector.d.ts +5 -0
  195. package/es/toolbar/change-cell-to-selector.d.ts.map +1 -0
  196. package/es/toolbar/change-cell-to-selector.js +48 -0
  197. package/es/toolbar/hide-all-selector.d.ts +5 -0
  198. package/es/toolbar/hide-all-selector.d.ts.map +1 -0
  199. package/es/toolbar/hide-all-selector.js +99 -0
  200. package/es/toolbar/index.d.ts +4 -0
  201. package/es/toolbar/index.d.ts.map +1 -0
  202. package/es/toolbar/index.js +3 -0
  203. package/es/toolbar/index.less +59 -0
  204. package/es/toolbar/libro-toolbar-protocol.d.ts +4 -0
  205. package/es/toolbar/libro-toolbar-protocol.d.ts.map +1 -0
  206. package/es/toolbar/libro-toolbar-protocol.js +1 -0
  207. package/es/toolbar/libro-toolbar.d.ts +8 -0
  208. package/es/toolbar/libro-toolbar.d.ts.map +1 -0
  209. package/es/toolbar/libro-toolbar.js +223 -0
  210. package/es/toolbar/module.d.ts +3 -0
  211. package/es/toolbar/module.d.ts.map +1 -0
  212. package/es/toolbar/module.js +5 -0
  213. package/es/toolbar/restart-clear-outputs-contribution.d.ts +5 -0
  214. package/es/toolbar/restart-clear-outputs-contribution.d.ts.map +1 -0
  215. package/es/toolbar/restart-clear-outputs-contribution.js +23 -0
  216. package/es/toolbar/restart-clear-outputs-modal.d.ts +6 -0
  217. package/es/toolbar/restart-clear-outputs-modal.d.ts.map +1 -0
  218. package/es/toolbar/restart-clear-outputs-modal.js +30 -0
  219. package/es/toolbar/save-icon.d.ts +3 -0
  220. package/es/toolbar/save-icon.d.ts.map +1 -0
  221. package/es/toolbar/save-icon.js +54 -0
  222. package/es/toolbar/shutdown-contribution.d.ts +5 -0
  223. package/es/toolbar/shutdown-contribution.d.ts.map +1 -0
  224. package/es/toolbar/shutdown-contribution.js +23 -0
  225. package/es/toolbar/shutdown-modal.d.ts +6 -0
  226. package/es/toolbar/shutdown-modal.d.ts.map +1 -0
  227. package/es/toolbar/shutdown-modal.js +30 -0
  228. package/es/toolbar/side-toolar-more-select.d.ts +4 -0
  229. package/es/toolbar/side-toolar-more-select.d.ts.map +1 -0
  230. package/es/toolbar/side-toolar-more-select.js +161 -0
  231. package/es/typings/index.d.ts +1 -0
  232. package/package.json +70 -0
  233. package/src/add-cell/index.less +38 -0
  234. package/src/add-cell/index.ts +3 -0
  235. package/src/add-cell/libro-add-cell-module.ts +9 -0
  236. package/src/add-cell/libro-add-cell-slot-contribution.ts +31 -0
  237. package/src/add-cell/libro-add-cell-view.tsx +101 -0
  238. package/src/cell/README.md +14 -0
  239. package/src/cell/index.ts +9 -0
  240. package/src/cell/libro-cell-contribution.ts +38 -0
  241. package/src/cell/libro-cell-model.ts +61 -0
  242. package/src/cell/libro-cell-module.ts +40 -0
  243. package/src/cell/libro-cell-protocol.ts +53 -0
  244. package/src/cell/libro-cell-service.ts +157 -0
  245. package/src/cell/libro-cell-view.tsx +128 -0
  246. package/src/cell/libro-edit-cell-view.tsx +60 -0
  247. package/src/cell/libro-executable-cell-model.ts +32 -0
  248. package/src/cell/libro-executable-cell-view.ts +74 -0
  249. package/src/cell/libro-markdown-cell-model.ts +20 -0
  250. package/src/collapse-service.ts +69 -0
  251. package/src/command/document-commands.ts +18 -0
  252. package/src/command/index.ts +6 -0
  253. package/src/command/kernel-command.ts +41 -0
  254. package/src/command/libro-command-contribution.ts +1339 -0
  255. package/src/command/libro-command-register.ts +171 -0
  256. package/src/command/module.ts +9 -0
  257. package/src/command/notebook-commands.ts +498 -0
  258. package/src/components/cell-protocol.ts +22 -0
  259. package/src/components/dnd-cell-item-render.tsx +308 -0
  260. package/src/components/dnd-component/custom-drag-layer.tsx +145 -0
  261. package/src/components/dnd-component/default-dnd-content.tsx +275 -0
  262. package/src/components/dnd-component/dnd-context.tsx +28 -0
  263. package/src/components/dnd-component/dnd-list.tsx +116 -0
  264. package/src/components/dnd-component/index.tsx +4 -0
  265. package/src/components/index.ts +5 -0
  266. package/src/components/libro-component.tsx +30 -0
  267. package/src/components/libro-side-toolbar-menu.tsx +82 -0
  268. package/src/components/libro-view-header.tsx +33 -0
  269. package/src/configuration/libro-configuration-contribution.ts +29 -0
  270. package/src/configuration/libro-configuration.ts +88 -0
  271. package/src/content/index.ts +4 -0
  272. package/src/content/libro-content-contribution.ts +17 -0
  273. package/src/content/libro-content-module.ts +9 -0
  274. package/src/content/libro-content-protocol.ts +8 -0
  275. package/src/content/libro-content-service.ts +30 -0
  276. package/src/index.less +682 -0
  277. package/src/index.tsx +19 -0
  278. package/src/libro-context-key.ts +80 -0
  279. package/src/libro-keybind-registry.ts +43 -0
  280. package/src/libro-model.ts +614 -0
  281. package/src/libro-protocol.ts +322 -0
  282. package/src/libro-service.ts +121 -0
  283. package/src/libro-view-tracker.ts +9 -0
  284. package/src/libro-view.tsx +1399 -0
  285. package/src/material-from-designer.tsx +457 -0
  286. package/src/module.ts +90 -0
  287. package/src/output/index.ts +5 -0
  288. package/src/output/output-area.tsx +255 -0
  289. package/src/output/output-contribution.ts +18 -0
  290. package/src/output/output-model.tsx +66 -0
  291. package/src/output/output-module.ts +10 -0
  292. package/src/output/output-protocol.ts +164 -0
  293. package/src/slot/index.ts +4 -0
  294. package/src/slot/libro-slot-manager.ts +37 -0
  295. package/src/slot/libro-slot-protocol.ts +28 -0
  296. package/src/slot/libro-slot-view.tsx +51 -0
  297. package/src/slot/module.ts +9 -0
  298. package/src/theme/libro-color-registry.ts +371 -0
  299. package/src/toolbar/change-cell-to-selector.tsx +58 -0
  300. package/src/toolbar/hide-all-selector.tsx +126 -0
  301. package/src/toolbar/index.less +59 -0
  302. package/src/toolbar/index.ts +3 -0
  303. package/src/toolbar/libro-toolbar-protocol.ts +4 -0
  304. package/src/toolbar/libro-toolbar.tsx +192 -0
  305. package/src/toolbar/module.ts +11 -0
  306. package/src/toolbar/restart-clear-outputs-contribution.tsx +10 -0
  307. package/src/toolbar/restart-clear-outputs-modal.tsx +37 -0
  308. package/src/toolbar/save-icon.tsx +47 -0
  309. package/src/toolbar/shutdown-contribution.tsx +10 -0
  310. package/src/toolbar/shutdown-modal.tsx +37 -0
  311. package/src/toolbar/side-toolar-more-select.tsx +172 -0
  312. package/src/typings/index.d.ts +1 -0
@@ -0,0 +1,614 @@
1
+ /* eslint-disable @typescript-eslint/unified-signatures */
2
+ import type {
3
+ ICodeCell,
4
+ INotebookContent,
5
+ INotebookMetadata,
6
+ } from '@difizen/libro-common';
7
+ import type {
8
+ CellTypeAdaptor,
9
+ ISharedNotebook,
10
+ NotebookChange,
11
+ } from '@difizen/libro-shared-model';
12
+ import { YNotebook, createMutex } from '@difizen/libro-shared-model';
13
+ import { ConfigurationService } from '@difizen/mana-app';
14
+ import { getOrigin } from '@difizen/mana-app';
15
+ import { Emitter } from '@difizen/mana-app';
16
+ import { inject, transient } from '@difizen/mana-app';
17
+ import { prop } from '@difizen/mana-app';
18
+ import { v4 } from 'uuid';
19
+
20
+ import { LibroContentService } from './content/index.js';
21
+ import type {
22
+ NotebookModel,
23
+ CellOptions,
24
+ DndListModel,
25
+ CellView,
26
+ MouseMode,
27
+ } from './libro-protocol.js';
28
+ import { isCellView, NotebookOption } from './libro-protocol.js';
29
+ import { EnterEditModeWhenAddCell } from './configuration/libro-configuration.js';
30
+
31
+ @transient()
32
+ export class LibroModel implements NotebookModel, DndListModel {
33
+ @inject(NotebookOption) options: NotebookOption;
34
+ @inject(LibroContentService) libroContentService: LibroContentService;
35
+ @inject(ConfigurationService) configurationService: ConfigurationService;
36
+
37
+ protected onCommandModeChangedEmitter: Emitter<boolean> = new Emitter();
38
+ get onCommandModeChanged() {
39
+ return this.onCommandModeChangedEmitter.event;
40
+ }
41
+
42
+ protected onContentChangedEmitter: Emitter<boolean> = new Emitter();
43
+ get onContentChanged() {
44
+ return this.onContentChangedEmitter.event;
45
+ }
46
+
47
+ id: string = v4();
48
+
49
+ /**
50
+ * The shared notebook model.
51
+ */
52
+ readonly sharedModel: ISharedNotebook;
53
+
54
+ /**
55
+ * A mutex to update the shared model.
56
+ */
57
+ protected readonly _modelDBMutex = createMutex();
58
+
59
+ @prop()
60
+ lastClipboardInteraction?: string;
61
+
62
+ clipboard?: CellView | CellView[];
63
+
64
+ @prop()
65
+ quickEditMode = false;
66
+
67
+ @prop()
68
+ commandMode = true;
69
+
70
+ @prop()
71
+ isEditMode = true;
72
+
73
+ @prop()
74
+ dndAreaNullEnable = false;
75
+
76
+ @prop()
77
+ dirty = false;
78
+
79
+ @prop()
80
+ readOnly = false;
81
+
82
+ @prop()
83
+ cells: CellView[] = [];
84
+
85
+ getCells() {
86
+ return this.cells.filter((cell) => !!cell);
87
+ }
88
+
89
+ @prop()
90
+ active?: CellView;
91
+
92
+ @prop()
93
+ activeIndex = 0;
94
+
95
+ @prop()
96
+ hover: CellView | undefined = undefined;
97
+
98
+ @prop()
99
+ isInitialized = false;
100
+
101
+ @prop()
102
+ executeCount = 0;
103
+
104
+ @prop()
105
+ mouseMode?: MouseMode;
106
+
107
+ @prop()
108
+ selections: CellView[] = [];
109
+
110
+ deletedCells: CellView[] = [];
111
+
112
+ metadata: INotebookMetadata = {};
113
+
114
+ @prop()
115
+ customParams: Record<string, any> = {};
116
+
117
+ @prop()
118
+ libroViewClass = '';
119
+
120
+ @prop()
121
+ canUndo = false;
122
+
123
+ @prop()
124
+ canRedo = false;
125
+
126
+ /**
127
+ * 默认为true,可以在metadata修改
128
+ */
129
+ @prop()
130
+ trusted = true;
131
+
132
+ canRun() {
133
+ return true;
134
+ }
135
+
136
+ getCustomKey(key: string) {
137
+ return this.customParams[key];
138
+ }
139
+
140
+ setCustomKey(key: string, val: any) {
141
+ this.customParams[key] = val;
142
+ // 备份到metadata
143
+ // 备份到metadata
144
+ this.metadata['customParams'] = this.customParams;
145
+ }
146
+
147
+ // 字体大小
148
+ @prop()
149
+ fontSize = 12;
150
+
151
+ // 主题
152
+ @prop()
153
+ theme = '';
154
+
155
+ cellViewCache = new Map<string, CellView>();
156
+
157
+ nbformat_minor = 4;
158
+ nbformat = 4;
159
+
160
+ cellTypeAdaptor?: CellTypeAdaptor;
161
+
162
+ constructor() {
163
+ this.sharedModel = YNotebook.create({
164
+ disableDocumentWideUndoRedo: false,
165
+ cellTypeAdaptor: this.cellTypeAdaptor,
166
+ });
167
+ this.sharedModel.changed(this.onSharedModelChanged);
168
+ this.sharedModel.undoChanged((value) => {
169
+ if (value !== this.canUndo) {
170
+ this.canUndo = value;
171
+ }
172
+ });
173
+ this.sharedModel.redoChanged((value) => {
174
+ if (value !== this.canRedo) {
175
+ this.canRedo = value;
176
+ }
177
+ });
178
+ }
179
+
180
+ protected onSharedModelChanged = (change: NotebookChange) => {
181
+ let currpos = 0;
182
+ change.cellsChange?.forEach((delta) => {
183
+ if (delta.insert !== null && delta.insert !== undefined) {
184
+ const cellViews = delta.insert.map((cell) => {
185
+ const view = this.cellViewCache.get(cell.id)!;
186
+ return view;
187
+ });
188
+ this.insertCellsView(cellViews, currpos);
189
+ currpos += delta.insert.length;
190
+ } else if (delta.delete !== null && delta.delete !== undefined) {
191
+ this.removeRange(currpos, currpos + delta.delete);
192
+ } else if (delta.retain !== null && delta.retain !== undefined) {
193
+ currpos += delta.retain;
194
+ }
195
+ });
196
+ if (this.readOnly && !this.isInitialized) {
197
+ this.selectCell(undefined);
198
+ return;
199
+ }
200
+ this.selectCell(this.cells[this.activeIndex]);
201
+ if (this.cells[this.activeIndex]) {
202
+ this.scrollToView(this.cells[this.activeIndex]);
203
+ }
204
+ this.configurationService
205
+ .get(EnterEditModeWhenAddCell)
206
+ .then((value) => {
207
+ if (value) {
208
+ if (this.isEditMode) {
209
+ this.enterEditMode();
210
+ } else {
211
+ this.enterCommandMode();
212
+ }
213
+ }
214
+ return;
215
+ })
216
+ .catch(() => {
217
+ //
218
+ });
219
+ };
220
+
221
+ toString = () => {
222
+ return JSON.stringify(this.toJSON());
223
+ };
224
+ fromString = (value: string) => {
225
+ this.fromJSON(JSON.parse(value));
226
+ };
227
+
228
+ /**
229
+ * Serialize the model to JSON.
230
+ */
231
+ toJSON(): INotebookContent {
232
+ return {
233
+ metadata: this.metadata,
234
+ nbformat_minor: this.nbformat_minor,
235
+ nbformat: this.nbformat,
236
+ cells: this.getCells().map((item) => item.toJSON()),
237
+ };
238
+ }
239
+
240
+ /**
241
+ * Deserialize the model from JSON.
242
+ *
243
+ * #### Notes
244
+ * Should emit a [contentChanged] signal.
245
+ */
246
+ fromJSON(value: INotebookContent) {
247
+ this.sharedModel.transact(() => {
248
+ const useId = value.nbformat === 4 && value.nbformat_minor >= 5;
249
+ const ycells = value.cells.map((cell) => {
250
+ if (!useId) {
251
+ delete cell.id;
252
+ }
253
+ return cell;
254
+ });
255
+ if (!ycells.length) {
256
+ // Create cell when notebook is empty
257
+ // (non collaborative)
258
+ ycells.push({ cell_type: 'code' } as ICodeCell);
259
+ }
260
+ this.sharedModel.insertCells(this.sharedModel.cells.length, ycells);
261
+ this.sharedModel.deleteCellRange(0, this.sharedModel.cells.length);
262
+ });
263
+ }
264
+
265
+ /**
266
+ * cell list change or cell content change
267
+ */
268
+ onChange() {
269
+ this.dirty = true;
270
+ this.onContentChangedEmitter.fire(true);
271
+ }
272
+
273
+ /**
274
+ * override this method to load notebook from server
275
+ * @returns
276
+ */
277
+ async loadNotebookContent(): Promise<INotebookContent> {
278
+ return this.libroContentService.loadLibroContent(this.options, this);
279
+ }
280
+
281
+ async saveNotebookContent(): Promise<void> {
282
+ //
283
+ }
284
+
285
+ async initialize(): Promise<CellOptions[]> {
286
+ const content = await this.loadNotebookContent();
287
+ this.metadata = content.metadata;
288
+ if (this.metadata?.['customParams']) {
289
+ this.customParams = this.metadata?.['customParams'] as Record<string, any>;
290
+ }
291
+ if (this.metadata?.['trusted']) {
292
+ this.trusted = this.metadata?.['trusted'] as boolean;
293
+ }
294
+ this.nbformat = content.nbformat;
295
+ this.nbformat_minor = content.nbformat_minor;
296
+ return content.cells.map((cell) => {
297
+ return { cell };
298
+ });
299
+ }
300
+
301
+ protected toCellIndex(arg: string | number | CellView): number | undefined {
302
+ let index: number | undefined = undefined;
303
+ if (typeof arg === 'number') {
304
+ index = arg;
305
+ } else if (typeof arg === 'string') {
306
+ index = this.cells.findIndex((cell) => cell.id === arg);
307
+ } else if (isCellView(arg)) {
308
+ index = this.cells.findIndex((cell) => cell.id === arg.id);
309
+ }
310
+ return index;
311
+ }
312
+ selectCell = (cell: CellView | undefined) => {
313
+ if (!cell || this.active?.id === cell.id) {
314
+ return;
315
+ }
316
+ this.active = cell;
317
+ cell.focus(false);
318
+ const index = this.cells.findIndex((_cell) => _cell.id === cell.id);
319
+ if (index > -1) {
320
+ this.activeIndex = index;
321
+ }
322
+ };
323
+
324
+ hoverCell = (cell?: CellView) => {
325
+ this.hover = cell;
326
+ };
327
+
328
+ /**
329
+ * 自动滚动到可视范围内
330
+ */
331
+ scrollToView(cell: CellView) {
332
+ let target = document.getElementById(cell.id);
333
+ if (!target) {
334
+ return;
335
+ }
336
+ const _targetheight = target?.offsetHeight || 0;
337
+ let offsetTop = target?.offsetTop || 0;
338
+ while (
339
+ target?.offsetParent &&
340
+ !target?.offsetParent?.className?.includes('libro-view-content-left')
341
+ ) {
342
+ target = target?.offsetParent as HTMLElement;
343
+ offsetTop += target?.offsetTop || 0;
344
+ }
345
+ if (target?.offsetParent?.parentElement && _targetheight) {
346
+ const _height = target.offsetParent.parentElement.clientHeight;
347
+ const _scrollTop = target.offsetParent.parentElement.scrollTop;
348
+ if (offsetTop > _scrollTop && offsetTop + _targetheight < _height + _scrollTop) {
349
+ // 在可视范围内就不需要滚动
350
+ return;
351
+ }
352
+ if (offsetTop < _scrollTop) {
353
+ target.offsetParent.parentElement.scrollTop = offsetTop;
354
+ } else {
355
+ target.offsetParent.parentElement.scrollTop =
356
+ offsetTop + _targetheight - _height + 30; // 加缓冲向上不贴底部
357
+ }
358
+ }
359
+ }
360
+
361
+ addCell = (cell: CellView, position?: number, mode?: string) => {
362
+ this.insertCells([cell], position, mode);
363
+ };
364
+
365
+ insertCells = (cells: CellView[], position?: number, mode?: string) => {
366
+ // 非初始化阶段才需要自动滚动
367
+ if (!this.isInitialized) {
368
+ this.activeIndex = 0;
369
+ } else if (mode === 'above' && position !== undefined) {
370
+ this.activeIndex = position;
371
+ } else {
372
+ if (position === this.cells.length) {
373
+ this.activeIndex = position;
374
+ } else {
375
+ this.activeIndex = this.activeIndex + cells.length;
376
+ }
377
+ }
378
+ this.isEditMode = true;
379
+
380
+ const cellData = cells.map((cell) => {
381
+ this.cellViewCache.set(cell.model.id, cell);
382
+ return cell.toJSON();
383
+ });
384
+ getOrigin(this.sharedModel).transact(() => {
385
+ const insertIndex = position ?? this.sharedModel.cells.length;
386
+ getOrigin(this.sharedModel).insertCells(insertIndex, cellData);
387
+ });
388
+ };
389
+
390
+ invertCell = (toAddcell: CellView, position: number) => {
391
+ if (this.activeIndex !== position) {
392
+ this.activeIndex = position;
393
+ }
394
+ const cellData = [toAddcell].map((_cell) => {
395
+ this.cellViewCache.set(_cell.model.id, _cell);
396
+ return _cell.toJSON();
397
+ });
398
+ this.isEditMode = true;
399
+ getOrigin(this.sharedModel).transact(() => {
400
+ const invertIndex = position ?? this.sharedModel.cells.length;
401
+ getOrigin(this.sharedModel).deleteCell(invertIndex);
402
+ getOrigin(this.sharedModel).insertCells(invertIndex, cellData);
403
+ });
404
+ };
405
+
406
+ splitCell = (newCells: CellView[], position: number) => {
407
+ const newActiveIndex = position + newCells.length - 1;
408
+ if (this.activeIndex !== newActiveIndex) {
409
+ this.activeIndex = newActiveIndex;
410
+ }
411
+ const cellData = newCells.map((_cell) => {
412
+ this.cellViewCache.set(_cell.model.id, _cell);
413
+ return _cell.toJSON();
414
+ });
415
+ getOrigin(this.sharedModel).transact(() => {
416
+ getOrigin(this.sharedModel).deleteCell(position);
417
+ getOrigin(this.sharedModel).insertCells(position, cellData);
418
+ });
419
+ //切分cell操作结束后进入编辑态
420
+ this.enterEditMode();
421
+ };
422
+
423
+ protected insertCellsView = (cell: CellView[], position?: number) => {
424
+ if (position === 0) {
425
+ this.cells.unshift(...cell);
426
+ return;
427
+ }
428
+ if (position !== undefined) {
429
+ const _cells: CellView[] = [];
430
+ this.getCells().forEach((_cell, index) => {
431
+ _cells.push(_cell);
432
+ _cell.isAttached = true;
433
+ if (index + 1 === position) {
434
+ _cells.push(...cell);
435
+ }
436
+ });
437
+ this.cells = _cells;
438
+ } else {
439
+ this.cells.push(...cell);
440
+ }
441
+ };
442
+
443
+ removeRange(start: number, end: number) {
444
+ this.cells.splice(start, end - start);
445
+ }
446
+
447
+ deleteCell(id: string | number): boolean;
448
+ deleteCell(index: number): boolean;
449
+ deleteCell(cell: CellView): boolean;
450
+ deleteCell(arg: string | number | CellView) {
451
+ const index = this.toCellIndex(arg);
452
+ if (index === undefined) {
453
+ return false;
454
+ }
455
+ if (this.activeIndex === this.cells.length - 1) {
456
+ this.activeIndex = this.cells.length - 2;
457
+ } else {
458
+ this.activeIndex = index;
459
+ }
460
+ this.isEditMode = false;
461
+ getOrigin(this.sharedModel).transact(() => {
462
+ getOrigin(this.sharedModel).deleteCell(index);
463
+ });
464
+ return true;
465
+ }
466
+
467
+ /**
468
+ * 删除 cell 节点
469
+ * @param arg id、index、cell
470
+ * @returns
471
+ */
472
+ protected deleteCellView(arg: string | number | CellView) {
473
+ if (arg === this.active?.id) {
474
+ // 如果删除项正好是选中项,则清空active
475
+ this.active = undefined;
476
+ }
477
+ return this.doDeleteCell(arg);
478
+ }
479
+
480
+ protected doDeleteCell = (arg: string | number | CellView) => {
481
+ const index = this.toCellIndex(arg);
482
+ if (index !== undefined) {
483
+ const _cells: CellView[] = [];
484
+ this.getCells().forEach((item, _index) => {
485
+ if (index !== _index) {
486
+ _cells.push(item);
487
+ }
488
+ });
489
+ this.cells = _cells;
490
+ if (index !== this.cells.length) {
491
+ this.selectCell(this.cells[index]);
492
+ } else {
493
+ this.selectCell(this.cells[index - 1]);
494
+ }
495
+ return true;
496
+ }
497
+
498
+ return false;
499
+ };
500
+ exchangeCell(source: CellView, target: CellView): boolean;
501
+ exchangeCell(sourceIndex: number, targetIndex: number): boolean;
502
+ exchangeCell(sourceId: string, targetId: string): boolean;
503
+ exchangeCell(source: string | number | CellView, target: string | number | CellView) {
504
+ const sourceIndex = this.toCellIndex(source);
505
+ const targetIndex = this.toCellIndex(target);
506
+ if (sourceIndex === undefined || targetIndex === undefined) {
507
+ return false;
508
+ }
509
+ this.activeIndex = targetIndex;
510
+ this.isEditMode = false;
511
+ getOrigin(this.sharedModel).transact(() => {
512
+ getOrigin(this.sharedModel).moveCell(sourceIndex, targetIndex);
513
+ });
514
+ this.activeIndex = targetIndex;
515
+ return true;
516
+ }
517
+
518
+ exchangeCells(source: CellView[], targetIndex: number) {
519
+ const startIndex = this.toCellIndex(source[0]);
520
+ const endIndex = this.toCellIndex(source[source.length - 1]);
521
+ if (startIndex === undefined || endIndex === undefined) {
522
+ return false;
523
+ }
524
+ this.isEditMode = false;
525
+ const cellData = source.map((cell) => {
526
+ this.cellViewCache.set(cell.model.id, cell);
527
+ return cell.toJSON();
528
+ });
529
+
530
+ getOrigin(this.sharedModel).transact(() => {
531
+ if (targetIndex > endIndex) {
532
+ //往下交换cell
533
+ if (startIndex === this.activeIndex) {
534
+ //active在头
535
+ this.activeIndex = targetIndex - source.length;
536
+ } else {
537
+ //active在头尾
538
+ this.activeIndex = targetIndex - 1;
539
+ }
540
+ getOrigin(this.sharedModel).deleteCellRange(startIndex, endIndex + 1);
541
+ getOrigin(this.sharedModel).insertCells(targetIndex - source.length, cellData);
542
+ } else {
543
+ //往上交换cell
544
+ if (startIndex === this.activeIndex) {
545
+ //active在头
546
+ this.activeIndex = targetIndex - source.length;
547
+ } else {
548
+ //active在尾
549
+ this.activeIndex = targetIndex + 1;
550
+ }
551
+ getOrigin(this.sharedModel).deleteCellRange(startIndex, endIndex + 1);
552
+ getOrigin(this.sharedModel).insertCells(targetIndex, cellData);
553
+ }
554
+ });
555
+ return true;
556
+ }
557
+
558
+ /**
559
+ * 交换 cell 节点位置
560
+ * @param source id、index、cell
561
+ * @param target id、index、cell
562
+ * @returns
563
+ */
564
+ protected exchangeCellView(
565
+ source: string | number | CellView,
566
+ target: string | number | CellView,
567
+ ) {
568
+ const sourceIndex = this.toCellIndex(source);
569
+ const targetIndex = this.toCellIndex(target);
570
+ if (sourceIndex !== undefined && targetIndex !== undefined) {
571
+ // 交换位置
572
+ const sourceItem = this.cells[sourceIndex];
573
+ const cells = [...this.cells];
574
+ cells.splice(sourceIndex, 1);
575
+ cells.splice(targetIndex, 0, sourceItem);
576
+ this.cells = cells;
577
+ setTimeout(() => {
578
+ // 上下移动也需要调整可视区域范围
579
+ this.scrollToView(sourceItem);
580
+ }, 300);
581
+ return true;
582
+ }
583
+ return false;
584
+ }
585
+ /**
586
+ * 进入命令模式
587
+ */
588
+ enterCommandMode() {
589
+ if (this.active) {
590
+ this.commandMode = true;
591
+ this.onCommandModeChangedEmitter.fire(true);
592
+ this.active.blur();
593
+ }
594
+ }
595
+
596
+ enterEditMode() {
597
+ if (this.active) {
598
+ if (this.selections.length !== 0) {
599
+ this.selections = [];
600
+ }
601
+ this.commandMode = false;
602
+ this.onCommandModeChangedEmitter.fire(false);
603
+ this.active.focus(true);
604
+ }
605
+ }
606
+
607
+ undo() {
608
+ getOrigin(this.sharedModel).undo();
609
+ }
610
+
611
+ redo() {
612
+ getOrigin(this.sharedModel).redo();
613
+ }
614
+ }