Skip to content

Commit

Permalink
Merge pull request #105 from hw-coconote/fix/HC-210
Browse files Browse the repository at this point in the history
[FEAT & FIX] 캔버스 동기화 작업, block indent 작업 진행 중
  • Loading branch information
ara-ro authored Oct 21, 2024
2 parents a3f9a71 + e4e00fd commit 0c7dc89
Show file tree
Hide file tree
Showing 2 changed files with 180 additions and 13 deletions.
36 changes: 23 additions & 13 deletions src/components/tiptab/TipTabEditor.vue
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,9 @@ import DraggableItem from "@/components/tiptab/DraggableItem";
import Image from "@tiptap/extension-image"; // 이미지 추가용
// import { NodePos } from '@tiptap/core';
// 코드 내 들여쓰기 용
import { Indent } from "@/components/tiptab/indent";
import { mapGetters, mapActions } from "vuex";
export default {
Expand Down Expand Up @@ -199,6 +202,9 @@ export default {
dragCheckSelectionNode: null,
tempDragCheckSelectionNode: null,
// 처음로딩 + 내용없음
isFirstAndNullContent: false,
// image 업로드 용
fileList: [], // 업로드할 파일 리스트
tempFilesRes: null, // 서버에 저장된 파일 메타데이터 응답
Expand Down Expand Up @@ -313,6 +319,7 @@ export default {
// Do something with the node
},
}),
Indent
],
onUpdate: () => {
const selectedNode = this.editor.state.selection;
Expand Down Expand Up @@ -345,6 +352,7 @@ export default {
// return removedIds; // 사라진 ID 반환
this.$parent.deleteBlock(removedIds[0]);
return false;
// this.nodeLength = updateAllFeIds.length;
}
Expand All @@ -357,27 +365,29 @@ export default {
const updateContent =
selectedNode?.$head?.path[3]?.content?.content[0]?.text;
// console.log(
// "⭐ Node:",
// updateBlockID,
// updateContent,
// this.editor.view?.trackWrites?.dataset?.id,
// updateContent == "",
// this.editor.view?.trackWrites?.data,
// updateContent == undefined
// );
console.log(
"⭐ Node:",
updateBlockID,
updateContent,
this.editor.view?.trackWrites?.dataset?.id,
updateContent == "",
this.editor.view?.trackWrites?.data,
updateContent == undefined
);
if (this.localJSON.content == undefined) {
this.localJSON = this.editor.getJSON();
this.isFirstAndNullContent = true;
this.localJSON = this.editor.getJSON(); // 이 부분 때문에 첫 로딩 시 updateContent 값 비교 시 무조건 같은 값
}
// 내용 차이 확인
const filteredItems = this.localJSON?.content.filter(
(item) => item.attrs.id === updateBlockID
);
console.log("filteredItems >> ", filteredItems);
if (filteredItems.length > 0) {
if (
!this.isFirstAndNullContent &&
filteredItems[0].content != undefined &&
filteredItems[0].content[0].text == updateContent
) {
Expand Down Expand Up @@ -781,9 +791,9 @@ export default {
display: flex;
flex-direction: column;
#editorArea {
height: 100%;
min-height: 100%;
> div {
height: 100%;
min-height: 100%;
}
}
}
Expand Down
157 changes: 157 additions & 0 deletions src/components/tiptab/indent.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
import { Extension } from "@tiptap/core";
// import { Node } from "prosemirror-model";
import { TextSelection, AllSelection } from "prosemirror-state";

export function clamp(val, min, max) {
if (val < min) {
return min;
}
if (val > max) {
return max;
}
return val;
}

export const IndentProps = {
min: 0,
max: 210,
more: 30,
less: -30,
};

export function isBulletListNode(node) {
return node.type.name === "bulletList";
}

export function isOrderedListNode(node) {
return node.type.name === "orderedList";
}

export function isTodoListNode(node) {
return node.type.name === "listItem";
}

export function isListNode(node) {
return isBulletListNode(node) || isOrderedListNode(node) || isTodoListNode(node);
}

function setNodeIndentMarkup(tr, pos, delta) {
if (!tr.doc) return tr;

const node = tr.doc.nodeAt(pos);
if (!node) return tr;

const minIndent = IndentProps.min;
const maxIndent = IndentProps.max;

const indent = clamp((node.attrs.indent || 0) + delta, minIndent, maxIndent);

if (indent === node.attrs.indent) return tr;

const nodeAttrs = {
...node.attrs,
indent,
};

return tr.setNodeMarkup(pos, node.type, nodeAttrs, node.marks);
}

function updateIndentLevel(tr, delta) {
const { doc, selection } = tr;

if (!doc || !selection) return tr;

if (!(selection instanceof TextSelection || selection instanceof AllSelection)) {
return tr;
}

const { from, to } = selection;

doc.nodesBetween(from, to, (node, pos) => {
const nodeType = node.type;

if (nodeType.name === "paragraph" || nodeType.name === "heading") {
tr = setNodeIndentMarkup(tr, pos, delta);
return false;
}
if (isListNode(node)) {
return false;
}
return true;
});

return tr;
}

export const Indent = Extension.create({
name: "indent",

addOptions() {
return {
types: ["heading", "paragraph"],
indentLevels: [0, 30, 60, 90, 120, 150, 180, 210],
defaultIndentLevel: 0,
};
},

addGlobalAttributes() {
return [
{
types: this.options.types,
attributes: {
indent: {
default: this.options.defaultIndentLevel,
renderHTML: (attributes) => {
return {
style: `margin-left: ${attributes.indent}px !important`,
};
},
parseHTML: (element) => {
return parseInt(element.style.marginLeft) || this.options.defaultIndentLevel;
},
},
},
},
];
},

addCommands() {
return {
indent:
() =>
({ tr, state, dispatch }) => {
const { selection } = state;
tr = tr.setSelection(selection);
tr = updateIndentLevel(tr, IndentProps.more);

if (tr.docChanged) {
dispatch && dispatch(tr);
return true;
}

return false;
},
outdent:
() =>
({ tr, state, dispatch }) => {
const { selection } = state;
tr = tr.setSelection(selection);
tr = updateIndentLevel(tr, IndentProps.less);

if (tr.docChanged) {
dispatch && dispatch(tr);
return true;
}

return false;
},
};
},

addKeyboardShortcuts() {
return {
Tab: () => this.editor.commands.indent(),
"Shift-Tab": () => this.editor.commands.outdent(),
};
},
});

0 comments on commit 0c7dc89

Please sign in to comment.