@kaitify/core 0.0.1-beta.1

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 (119) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +3 -0
  3. package/examples/App.vue +342 -0
  4. package/examples/content.js +1 -0
  5. package/examples/main.ts +4 -0
  6. package/examples/test.html +23 -0
  7. package/lib/extensions/Extension.d.ts +172 -0
  8. package/lib/extensions/align/index.d.ts +10 -0
  9. package/lib/extensions/attachment/index.d.ts +29 -0
  10. package/lib/extensions/back-color/index.d.ts +9 -0
  11. package/lib/extensions/blockquote/index.d.ts +12 -0
  12. package/lib/extensions/bold/index.d.ts +9 -0
  13. package/lib/extensions/code/index.d.ts +12 -0
  14. package/lib/extensions/code-block/hljs.d.ts +12 -0
  15. package/lib/extensions/code-block/index.d.ts +15 -0
  16. package/lib/extensions/color/index.d.ts +9 -0
  17. package/lib/extensions/font-family/index.d.ts +9 -0
  18. package/lib/extensions/font-size/index.d.ts +9 -0
  19. package/lib/extensions/heading/index.d.ts +13 -0
  20. package/lib/extensions/history/index.d.ts +10 -0
  21. package/lib/extensions/horizontal/index.d.ts +7 -0
  22. package/lib/extensions/image/index.d.ts +26 -0
  23. package/lib/extensions/indent/index.d.ts +8 -0
  24. package/lib/extensions/index.d.ts +29 -0
  25. package/lib/extensions/italic/index.d.ts +9 -0
  26. package/lib/extensions/line-height/index.d.ts +9 -0
  27. package/lib/extensions/link/index.d.ts +27 -0
  28. package/lib/extensions/list/index.d.ts +18 -0
  29. package/lib/extensions/math/index.d.ts +11 -0
  30. package/lib/extensions/strikethrough/index.d.ts +9 -0
  31. package/lib/extensions/subscript/index.d.ts +9 -0
  32. package/lib/extensions/superscript/index.d.ts +9 -0
  33. package/lib/extensions/table/index.d.ts +21 -0
  34. package/lib/extensions/task/index.d.ts +12 -0
  35. package/lib/extensions/text/index.d.ts +14 -0
  36. package/lib/extensions/underline/index.d.ts +9 -0
  37. package/lib/extensions/video/index.d.ts +27 -0
  38. package/lib/index.d.ts +3 -0
  39. package/lib/kaitify-core.es.js +38337 -0
  40. package/lib/kaitify-core.umd.js +2 -0
  41. package/lib/model/Editor.d.ts +504 -0
  42. package/lib/model/History.d.ts +42 -0
  43. package/lib/model/KNode.d.ts +258 -0
  44. package/lib/model/Selection.d.ts +29 -0
  45. package/lib/model/config/dom-observe.d.ts +10 -0
  46. package/lib/model/config/event-handler.d.ts +33 -0
  47. package/lib/model/config/format-patch.d.ts +25 -0
  48. package/lib/model/config/format-rules.d.ts +37 -0
  49. package/lib/model/config/function.d.ts +84 -0
  50. package/lib/model/index.d.ts +6 -0
  51. package/lib/tools/index.d.ts +49 -0
  52. package/lib/view/index.d.ts +21 -0
  53. package/lib/view/js-render/dom-patch.d.ts +65 -0
  54. package/lib/view/js-render/index.d.ts +5 -0
  55. package/package.json +52 -0
  56. package/src/css/style.less +56 -0
  57. package/src/css/var.less +45 -0
  58. package/src/extensions/Extension.ts +200 -0
  59. package/src/extensions/align/index.ts +115 -0
  60. package/src/extensions/attachment/icon.svg +1 -0
  61. package/src/extensions/attachment/index.ts +293 -0
  62. package/src/extensions/attachment/style.less +25 -0
  63. package/src/extensions/back-color/index.ts +56 -0
  64. package/src/extensions/blockquote/index.ts +144 -0
  65. package/src/extensions/blockquote/style.less +16 -0
  66. package/src/extensions/bold/index.ts +77 -0
  67. package/src/extensions/code/index.ts +295 -0
  68. package/src/extensions/code/style.less +14 -0
  69. package/src/extensions/code-block/hljs.less +183 -0
  70. package/src/extensions/code-block/hljs.ts +95 -0
  71. package/src/extensions/code-block/index.ts +308 -0
  72. package/src/extensions/code-block/style.less +20 -0
  73. package/src/extensions/color/index.ts +56 -0
  74. package/src/extensions/font-family/index.ts +80 -0
  75. package/src/extensions/font-size/index.ts +56 -0
  76. package/src/extensions/heading/index.ts +164 -0
  77. package/src/extensions/heading/style.less +42 -0
  78. package/src/extensions/history/index.ts +96 -0
  79. package/src/extensions/horizontal/index.ts +45 -0
  80. package/src/extensions/horizontal/style.less +13 -0
  81. package/src/extensions/image/index.ts +242 -0
  82. package/src/extensions/image/style.less +8 -0
  83. package/src/extensions/indent/index.ts +98 -0
  84. package/src/extensions/index.ts +29 -0
  85. package/src/extensions/italic/index.ts +77 -0
  86. package/src/extensions/line-height/index.ts +113 -0
  87. package/src/extensions/link/index.ts +184 -0
  88. package/src/extensions/link/style.less +19 -0
  89. package/src/extensions/list/index.ts +410 -0
  90. package/src/extensions/list/style.less +19 -0
  91. package/src/extensions/math/index.ts +233 -0
  92. package/src/extensions/math/style.less +21 -0
  93. package/src/extensions/strikethrough/index.ts +78 -0
  94. package/src/extensions/subscript/index.ts +77 -0
  95. package/src/extensions/superscript/index.ts +77 -0
  96. package/src/extensions/table/index.ts +1148 -0
  97. package/src/extensions/table/style.less +71 -0
  98. package/src/extensions/task/index.ts +243 -0
  99. package/src/extensions/task/style.less +59 -0
  100. package/src/extensions/text/index.ts +359 -0
  101. package/src/extensions/underline/index.ts +78 -0
  102. package/src/extensions/video/index.ts +273 -0
  103. package/src/extensions/video/style.less +8 -0
  104. package/src/index.ts +9 -0
  105. package/src/model/Editor.ts +1963 -0
  106. package/src/model/History.ts +115 -0
  107. package/src/model/KNode.ts +677 -0
  108. package/src/model/Selection.ts +39 -0
  109. package/src/model/config/dom-observe.ts +184 -0
  110. package/src/model/config/event-handler.ts +237 -0
  111. package/src/model/config/format-patch.ts +215 -0
  112. package/src/model/config/format-rules.ts +218 -0
  113. package/src/model/config/function.ts +1018 -0
  114. package/src/model/index.ts +6 -0
  115. package/src/tools/index.ts +156 -0
  116. package/src/view/index.ts +46 -0
  117. package/src/view/js-render/dom-patch.ts +324 -0
  118. package/src/view/js-render/index.ts +210 -0
  119. package/vite-env.d.ts +2 -0
@@ -0,0 +1,56 @@
1
+ .Kaitify {
2
+ display: block;
3
+ position: relative;
4
+ font-size: var(--kaitify-font-size);
5
+ font-family: var(--kaitify-font-family);
6
+ color: var(--kaitify-font-color);
7
+ -webkit-font-smoothing: antialiased;
8
+ text-size-adjust: none;
9
+ line-height: var(--kaitify-line-height);
10
+ border: 1px solid var(--kaitify-border-color);
11
+ border-radius: var(--kaitify-border-radius);
12
+ background: var(--kaitify-background-color);
13
+ padding: var(--kaitify-padding);
14
+ transition: border-color 500ms;
15
+ overflow-x: hidden;
16
+ overflow-y: auto;
17
+ outline: none;
18
+
19
+ ::selection {
20
+ background-color: var(--kaitify-light-theme);
21
+ }
22
+
23
+ *,
24
+ *::before,
25
+ *::after {
26
+ box-sizing: border-box;
27
+ -webkit-tap-highlight-color: transparent;
28
+ outline: none;
29
+ }
30
+
31
+ //编辑状态下才有的样式
32
+ &[contenteditable='true'] {
33
+ &:focus {
34
+ border-color: var(--kaitify-theme);
35
+ }
36
+
37
+ &[kaitify-placeholder].showPlaceholder::before {
38
+ content: attr(kaitify-placeholder);
39
+ position: absolute;
40
+ left: 0;
41
+ top: 0;
42
+ padding: var(--kaitify-padding);
43
+ line-height: var(--kaitify-line-height);
44
+ opacity: 0.5;
45
+ cursor: text;
46
+ }
47
+
48
+ [contenteditable='false']:hover {
49
+ cursor: not-allowed;
50
+ }
51
+ }
52
+ }
53
+
54
+ html[kaitify-dark] {
55
+ color-scheme: dark;
56
+ }
@@ -0,0 +1,45 @@
1
+ @theme: #308af3;
2
+
3
+ :root {
4
+ //主题色
5
+ --kaitify-theme: @theme;
6
+ //最浅主题色,通常用于悬浮效果
7
+ --kaitify-lightest-theme: fade(@theme, 10);
8
+ //更浅主题色,通常用于激活效果
9
+ --kaitify-lighter-theme: fade(@theme, 20);
10
+ //浅主题色,用于选区颜色
11
+ --kaitify-light-theme: fade(@theme, 30);
12
+ //字体颜色
13
+ --kaitify-font-color: #505050;
14
+ //边框颜色
15
+ --kaitify-border-color: #dedede;
16
+ //背景色
17
+ --kaitify-background-color: #fff;
18
+ //行高
19
+ --kaitify-line-height: 1.5;
20
+ //字号
21
+ --kaitify-font-size: 14px;
22
+ //通用圆角大小
23
+ --kaitify-border-radius: 3px;
24
+ //外边距
25
+ --kaitify-margin: 10px;
26
+ --kaitify-small-margin: 5px;
27
+ --kaitify-large-margin: 15px;
28
+ //内边距
29
+ --kaitify-padding: 10px;
30
+ --kaitify-small-padding: 5px;
31
+ --kaitify-large-padding: 20px;
32
+ //节点两侧和其他节点的间距
33
+ --kaitify-sides-between: 2px;
34
+ //字体
35
+ --kaitify-font-family: PingFang SC, -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica Neue, Helvetica, Hiragino KaKu Gothic Pro, Microsoft YaHei, Arial, sans-serif;
36
+ }
37
+
38
+ :root[kaitify-dark] {
39
+ //字体颜色
40
+ --kaitify-font-color: #f5f5f5;
41
+ //边框颜色
42
+ --kaitify-border-color: #3b3b3b;
43
+ //背景色
44
+ --kaitify-background-color: #1b1b1f;
45
+ }
@@ -0,0 +1,200 @@
1
+ import { Editor, EditorCommandsType, KNode, KNodeMarksType, KNodeStylesType, RuleFunctionType, Selection } from '@/model'
2
+
3
+ /**
4
+ * 创建扩展的入参类型
5
+ */
6
+ export type ExtensionCreateOptionType = {
7
+ /**
8
+ * 扩展名称
9
+ */
10
+ name: string
11
+ /**
12
+ * 置空的标签
13
+ */
14
+ emptyRenderTags?: string[]
15
+ /**
16
+ * 额外保留的标签
17
+ */
18
+ extraKeepTags?: string[]
19
+ /**
20
+ * 自定义格式化规则
21
+ */
22
+ formatRules?: RuleFunctionType[]
23
+ /**
24
+ * 自定义dom转为非文本节点的后续处理
25
+ */
26
+ domParseNodeCallback?: (this: Editor, node: KNode) => KNode
27
+ /**
28
+ * 光标变化回调
29
+ */
30
+ onSelectionUpdate?: (this: Editor, selection: Selection) => void
31
+ /**
32
+ * 插入段落时回调
33
+ */
34
+ onInsertParagraph?: (this: Editor, node: KNode) => void
35
+ /**
36
+ * 完成删除回调
37
+ */
38
+ onDeleteComplete?: (this: Editor) => void
39
+ /**
40
+ * 光标在编辑器内时键盘按下回调
41
+ */
42
+ onKeydown?: (this: Editor, event: KeyboardEvent) => void
43
+ /**
44
+ * 光标在编辑器内时键盘松开回调
45
+ */
46
+ onKeyup?: (this: Editor, event: KeyboardEvent) => void
47
+ /**
48
+ * 编辑器聚焦时回调
49
+ */
50
+ onFocus?: (this: Editor, event: FocusEvent) => void
51
+ /**
52
+ * 编辑器失焦时回调
53
+ */
54
+ onBlur?: (this: Editor, event: FocusEvent) => void
55
+ /**
56
+ * 节点粘贴保留标记的自定义方法
57
+ */
58
+ pasteKeepMarks?: (this: Editor, node: KNode) => KNodeMarksType
59
+ /**
60
+ * 节点粘贴保留样式的自定义方法
61
+ */
62
+ pasteKeepStyles?: (this: Editor, node: KNode) => KNodeStylesType
63
+ /**
64
+ * 视频更新前回调
65
+ */
66
+ beforeUpdateView?: (this: Editor) => void
67
+ /**
68
+ * 视图更新后回调
69
+ */
70
+ afterUpdateView?: (this: Editor) => void
71
+ /**
72
+ * 在删除和换行操作中块节点节点从其父节点中抽离出去成为与父节点同级的节点后触发,如果返回true则表示继续使用默认逻辑,会将该节点转为段落,返回false则不走默认逻辑,需要自定义处理
73
+ */
74
+ onDetachMentBlockFromParentCallback?: (this: Editor, node: KNode) => boolean
75
+ /**
76
+ * 编辑器updateView执行时,通过比对新旧节点数组获取需要格式化的节点,在这些节点被格式化前,触发此方法,回调参数即当前需要被格式化的节点,该方法返回一个节点,返回的节点将会被格式化,如果你不需要任何特殊处理,返回入参提供的节点即可
77
+ */
78
+ beforePatchNodeToFormat?: (this: Editor, node: KNode) => KNode
79
+
80
+ /**
81
+ * 自定义命令
82
+ */
83
+ addCommands?: (this: Editor) => EditorCommandsType
84
+ }
85
+
86
+ /**
87
+ * 扩展
88
+ */
89
+ export class Extension {
90
+ /**
91
+ * 扩展名称
92
+ */
93
+ name: string
94
+ /**
95
+ * 是否已注册
96
+ */
97
+ registered: boolean = false
98
+ /**
99
+ * 置空的标签
100
+ */
101
+ emptyRenderTags: string[] = []
102
+ /**
103
+ * 额外保留的标签
104
+ */
105
+ extraKeepTags: string[] = []
106
+ /**
107
+ * 自定义格式化规则
108
+ */
109
+ formatRules: RuleFunctionType[] = []
110
+ /**
111
+ * 自定义dom转为非文本节点的后续处理
112
+ */
113
+ domParseNodeCallback?: (this: Editor, node: KNode) => KNode
114
+ /**
115
+ * 光标变化回调
116
+ */
117
+ onSelectionUpdate?: (this: Editor, selection: Selection) => void
118
+ /**
119
+ * 插入段落时回调
120
+ */
121
+ onInsertParagraph?: (this: Editor, node: KNode) => void
122
+ /**
123
+ * 完成删除回调
124
+ */
125
+ onDeleteComplete?: (this: Editor) => void
126
+ /**
127
+ * 光标在编辑器内时键盘按下回调
128
+ */
129
+ onKeydown?: (this: Editor, event: KeyboardEvent) => void
130
+ /**
131
+ * 光标在编辑器内时键盘松开回调
132
+ */
133
+ onKeyup?: (this: Editor, event: KeyboardEvent) => void
134
+ /**
135
+ * 编辑器聚焦时回调
136
+ */
137
+ onFocus?: (this: Editor, event: FocusEvent) => void
138
+ /**
139
+ * 编辑器失焦时回调
140
+ */
141
+ onBlur?: (this: Editor, event: FocusEvent) => void
142
+ /**
143
+ * 节点粘贴保留标记的自定义方法
144
+ */
145
+ pasteKeepMarks?: (this: Editor, node: KNode) => KNodeMarksType
146
+ /**
147
+ * 节点粘贴保留样式的自定义方法
148
+ */
149
+ pasteKeepStyles?: (this: Editor, node: KNode) => KNodeStylesType
150
+ /**
151
+ * 视频更新前回调
152
+ */
153
+ beforeUpdateView?: (this: Editor) => void
154
+ /**
155
+ * 视图更新后回调
156
+ */
157
+ afterUpdateView?: (this: Editor) => void
158
+ /**
159
+ * 在删除和换行操作中块节点节点从其父节点中抽离出去成为与父节点同级的节点后触发,如果返回true则表示继续使用默认逻辑,会将该节点转为段落,返回false则不走默认逻辑,需要自定义处理
160
+ */
161
+ onDetachMentBlockFromParentCallback?: (this: Editor, node: KNode) => boolean
162
+ /**
163
+ * 编辑器updateView执行时,通过比对新旧节点数组获取需要格式化的节点,在这些节点被格式化前,触发此方法,回调参数即当前需要被格式化的节点,该方法返回一个节点,返回的节点将会被格式化,如果你不需要任何特殊处理,返回入参提供的节点即可
164
+ */
165
+ beforePatchNodeToFormat?: (this: Editor, node: KNode) => KNode
166
+ /**
167
+ * 自定义命令
168
+ */
169
+ addCommands?: (this: Editor) => EditorCommandsType
170
+
171
+ constructor(name: string) {
172
+ this.name = name
173
+ }
174
+
175
+ /**
176
+ * 创建扩展
177
+ */
178
+ static create(options: ExtensionCreateOptionType) {
179
+ const extension = new Extension(options.name)
180
+ if (options.emptyRenderTags) extension.emptyRenderTags = options.emptyRenderTags
181
+ if (options.extraKeepTags) extension.extraKeepTags = options.extraKeepTags
182
+ if (options.formatRules) extension.formatRules = options.formatRules
183
+ if (options.domParseNodeCallback) extension.domParseNodeCallback = options.domParseNodeCallback
184
+ if (options.onSelectionUpdate) extension.onSelectionUpdate = options.onSelectionUpdate
185
+ if (options.onInsertParagraph) extension.onInsertParagraph = options.onInsertParagraph
186
+ if (options.onDeleteComplete) extension.onDeleteComplete = options.onDeleteComplete
187
+ if (options.onKeydown) extension.onKeydown = options.onKeydown
188
+ if (options.onKeyup) extension.onKeyup = options.onKeyup
189
+ if (options.onFocus) extension.onFocus = options.onFocus
190
+ if (options.onBlur) extension.onBlur = options.onBlur
191
+ if (options.pasteKeepMarks) extension.pasteKeepMarks = options.pasteKeepMarks
192
+ if (options.pasteKeepStyles) extension.pasteKeepStyles = options.pasteKeepStyles
193
+ if (options.beforeUpdateView) extension.beforeUpdateView = options.beforeUpdateView
194
+ if (options.afterUpdateView) extension.afterUpdateView = options.afterUpdateView
195
+ if (options.onDetachMentBlockFromParentCallback) extension.onDetachMentBlockFromParentCallback = options.onDetachMentBlockFromParentCallback
196
+ if (options.beforePatchNodeToFormat) extension.beforePatchNodeToFormat = options.beforePatchNodeToFormat
197
+ if (options.addCommands) extension.addCommands = options.addCommands
198
+ return extension
199
+ }
200
+ }
@@ -0,0 +1,115 @@
1
+ import { KNode, KNodeStylesType } from '@/model'
2
+ import { deleteProperty } from '@/tools'
3
+ import { Extension } from '../Extension'
4
+ import { getSelectionBlockNodes } from '@/model/config/function'
5
+
6
+ export type AlignValueType = 'left' | 'right' | 'center' | 'justify'
7
+
8
+ declare module '../../model' {
9
+ interface EditorCommandsType {
10
+ isAlign?: (value: AlignValueType) => boolean
11
+ setAlign?: (value: AlignValueType) => Promise<void>
12
+ unsetAlign?: (value: AlignValueType) => Promise<void>
13
+ }
14
+ }
15
+
16
+ /**
17
+ * 删除指定块节点及以上块节点的对齐方式
18
+ */
19
+ const clearAlign = (blockNode: KNode, value: AlignValueType) => {
20
+ const matchNode = blockNode.getMatchNode({ styles: { textAlign: value } })
21
+ if (matchNode) {
22
+ matchNode.styles = deleteProperty(matchNode.styles!, 'textAlign')
23
+ clearAlign(matchNode, value)
24
+ }
25
+ }
26
+
27
+ export const AlignExtension = () =>
28
+ Extension.create({
29
+ name: 'align',
30
+ pasteKeepStyles(node) {
31
+ const styles: KNodeStylesType = {}
32
+ if (node.isBlock() && node.hasStyles()) {
33
+ if (node.styles!.hasOwnProperty('textAlign')) styles.textAlign = node.styles!.textAlign
34
+ }
35
+ return styles
36
+ },
37
+ addCommands() {
38
+ /**
39
+ * 光标所在的块节点是否都是符合的对齐方式
40
+ */
41
+ const isAlign = (value: AlignValueType) => {
42
+ if (!this.selection.focused()) {
43
+ return false
44
+ }
45
+ //起点和终点在一起
46
+ if (this.selection.collapsed()) {
47
+ const block = this.selection.start!.node.getBlock()
48
+ return !!block.getMatchNode({ styles: { textAlign: value } })
49
+ }
50
+ //起点和终点不在一起
51
+ const blockNodes = getSelectionBlockNodes.apply(this)
52
+ return blockNodes.every(item => {
53
+ return !!item.getMatchNode({ styles: { textAlign: value } })
54
+ })
55
+ }
56
+
57
+ /**
58
+ * 设置对齐方式
59
+ */
60
+ const setAlign = async (value: AlignValueType) => {
61
+ if (isAlign(value)) {
62
+ return
63
+ }
64
+ //起点和终点在一起
65
+ if (this.selection.collapsed()) {
66
+ const blockNode = this.selection.start!.node.getBlock()
67
+ const styles: KNodeStylesType = blockNode.hasStyles() ? blockNode.styles! : {}
68
+ blockNode.styles = {
69
+ ...styles,
70
+ textAlign: value
71
+ }
72
+ }
73
+ //起点和终点不在一起
74
+ else {
75
+ const blockNodes = getSelectionBlockNodes.apply(this)
76
+ blockNodes.forEach(item => {
77
+ const styles: KNodeStylesType = item.hasStyles() ? item.styles! : {}
78
+ item.styles = {
79
+ ...styles,
80
+ textAlign: value
81
+ }
82
+ })
83
+ }
84
+ await this.updateView()
85
+ }
86
+
87
+ /**
88
+ * 取消对齐方式
89
+ */
90
+ const unsetAlign = async (value: AlignValueType) => {
91
+ if (!isAlign(value)) {
92
+ return
93
+ }
94
+ //起点和终点在一起
95
+ if (this.selection.collapsed()) {
96
+ const blockNode = this.selection.start!.node.getBlock()
97
+ clearAlign(blockNode, value)
98
+ }
99
+ //起点和终点不在一起
100
+ else {
101
+ const blockNodes = getSelectionBlockNodes.apply(this)
102
+ blockNodes.forEach(item => {
103
+ clearAlign(item, value)
104
+ })
105
+ }
106
+ await this.updateView()
107
+ }
108
+
109
+ return {
110
+ isAlign,
111
+ setAlign,
112
+ unsetAlign
113
+ }
114
+ }
115
+ })
@@ -0,0 +1 @@
1
+ <svg t="1728556328694" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1473" width="200" height="200"><path d="M960 448c0 88-72 160-160 160H352c-52.8 0-96-43.2-96-96s43.2-96 96-96h416v64H352c-17.6 0-32 14.4-32 32s14.4 32 32 32h448c52.8 0 96-43.2 96-96s-43.2-96-96-96H288c-88 0-160 72-160 160s72 160 160 160h352v64H288C164 736 64 636 64 512s100-224 224-224h512c88 0 160 72 160 160z" p-id="1474" fill="#06c27c"></path></svg>