66 :text-align =" textAlign"
77 :list-type =" listType"
88 @executeCommand =" onExecuteCommand"
9+ @execute-command =" onExecuteCommand"
910 />
1011
1112 <v-editor-body
1516 @updateModel:textAlign =" textAlign = $event"
1617 @updateModel:listType =" listType = $event"
1718 />
18-
19- {{ fontColor }}
20- {{ fontSize }}
21- {{ textAlign }}
2219 </div >
2320</template >
2421
2522<script lang="ts">
2623import { defineComponent , Ref , ref } from ' @vue/composition-api' ;
2724import VEditorHead from ' @/components/editor/VEditorHead.vue' ;
2825import VEditorBody from ' @/components/editor/VEditorBody.vue' ;
29- import { useSelection } from ' @/shared/selection' ;
26+ import { useRange } from ' @/shared/selection' ;
27+ import { useDOMManipulation } from ' @/shared/DOMManipulation' ;
3028import { CommandsItem } from ' @/@types/index' ;
3129
32- const useCommandsHandler = (editorBody : Ref < typeof VEditorBody > ) => {
30+ const useCommandsHandler = () => {
3331 const actions: Record <string , Function > = {
3432 textAlign(el : HTMLDivElement , value : string ) {
35- const { range, moveCursorToEnd } = useSelection ();
33+ const { range, moveCursorToEnd } = useRange ();
3634 const common = range .commonAncestorContainer ;
3735 let newElement;
3836
@@ -51,7 +49,7 @@ const useCommandsHandler = (editorBody: Ref<typeof VEditorBody>) => {
5149 },
5250
5351 list(el : HTMLDivElement , value : string ) {
54- const { range, moveCursorToEnd } = useSelection ();
52+ const { range, moveCursorToEnd } = useRange ();
5553 const common = range .commonAncestorContainer ;
5654
5755 if (! el .contains (common ) || common .isSameNode (el )) return ;
@@ -80,12 +78,55 @@ const useCommandsHandler = (editorBody: Ref<typeof VEditorBody>) => {
8078 el .replaceChild (newEl , myNode );
8179 moveCursorToEnd (newEl );
8280 },
81+
82+ color(el : HTMLDivElement , value : string ): void {
83+ const { range, setRange, moveCursorToEnd } = useRange ();
84+ const { getEndNode } = useDOMManipulation ();
85+ const { startContainer, startOffset, endOffset, endContainer } = range as Range & { startContainer: Text };
86+ const endSpan = document .createElement (' span' );
87+ const startSpan = document .createElement (' span' );
88+ const startTextNode = document .createTextNode (startContainer .textContent ?.slice (startOffset ) || ' \u200B ' );
89+ const endTextNode = document .createTextNode (' ' );
90+
91+ if (! el .contains (startContainer )) return moveCursorToEnd (el .lastChild || el );
92+
93+ startSpan .style .color = value ;
94+ endSpan .style .color = value ;
95+ startSpan .appendChild (startTextNode );
96+ startContainer .replaceData (startOffset , - 1 , ' ' );
97+ startContainer .after (startSpan );
98+
99+ if (startContainer .isSameNode (endContainer )) return setRange ({ node: startTextNode }, { node: startTextNode });
100+
101+ const endNode = getEndNode (startTextNode , endContainer , (n ) => {
102+ const sibling = (n .nodeType === 3 ? n .parentElement : n ) as HTMLElement ;
103+ sibling .style .color = value ;
104+ });
105+
106+ let textEndNode = (endNode .nodeType === 3 ? endNode : endNode .lastChild ) as Text | null ;
107+
108+ if (! textEndNode ) {
109+ textEndNode = document .createTextNode (' ' );
110+ endNode .appendChild (textEndNode );
111+ }
112+
113+ endTextNode .textContent = (textEndNode .textContent || ' ' ).slice (0 , endOffset );
114+ endSpan .appendChild (endTextNode );
115+ textEndNode .replaceData (0 , endOffset , ' ' );
116+
117+ if (endNode .isSameNode (textEndNode )) {
118+ const parentEndNode = endNode .parentNode as Node ;
119+ parentEndNode .insertBefore (endSpan , textEndNode );
120+ } else {
121+ endNode .insertBefore (endSpan , textEndNode );
122+ }
123+
124+ return setRange ({ node: startTextNode }, { node: endTextNode });
125+ },
83126 };
84127
85128 const onExecuteCommand = (rule : CommandsItem ) => {
86- // eslint-disable-next-line @typescript-eslint/ban-ts-ignore
87- // @ts-ignore
88- actions [rule .command ](editorBody .value .$data .textContainer , rule .value );
129+ actions [rule .command ](document .querySelector (' #text-editor' ), rule .value );
89130 };
90131
91132 return { onExecuteCommand };
@@ -113,10 +154,8 @@ export default defineComponent({
113154
114155 setup() {
115156 const editorBody = ref (VEditorBody );
116- const { onExecuteCommand } = useCommandsHandler (editorBody );
117- const {
118- fontSize, fontColor, textAlign, listType,
119- } = useProepertiesControll ();
157+ const { onExecuteCommand } = useCommandsHandler ();
158+ const { fontSize, fontColor, textAlign, listType } = useProepertiesControll ();
120159
121160 return {
122161 fontSize ,
0 commit comments