Skip to content

Novel이란?

진예원 edited this page Oct 30, 2024 · 1 revision

Novel

Novel은 Tiptab에 노션의 command, bubble 기능을 추가한 라이브러리이다.

Novel 패키지에는 스타일이 포함되어 있지 않다. Tiptap의 사용자 지정 구성 및 컴포넌트 모음일 뿐이다.

Tiptab : Wysiwyg기반 에디터인 ProseMirror에 에디터 내부 컨텐츠 조작 기능을 제공해주는 라이브러리이다.

Wysiwyg(위즈윅, what you see is what you get) : 사용자가 보는 것이 그대로 최종 산물에 나타나도록 하는 유저 인터페이스 Wysiwyg 에디터: 편집 상태인데 최종 산물이 보이는 에디터


살펴보면 좋은 링크



Novel 에디터 사용법

기본 HTML 요소 스타일 변경

Novel의 extensions인 StarterKit에서 설정하고, EditorContent의 extension 프로퍼티에 추가하면 된다.

import { cx } from "class-variance-authority";

const starterKit = StarterKit.configure({
  bulletList: {
    HTMLAttributes: {
      class: cx("list-disc list-outside leading-3 -mt-2"),
    },
  },
  orderedList: {
    HTMLAttributes: {
      class: cx("list-decimal list-outside leading-3 -mt-2"),
    },
  },
  listItem: {
    HTMLAttributes: {
      class: cx("leading-normal -mb-2"),
    },
  },
  blockquote: {
    HTMLAttributes: {
      class: cx("border-l-4 border-primary"),
    },
  }
  ...
});

예시 보러가기


EditorBubble

Bubble

드래그한 텍스트를 커스텀할 수 있는 툴바이다.

// https://github.com/steven-tey/novel/blob/ecdb5d2ff5d3e6ab5f5af95b5a81de3ab4e8a0e9/examples/novel-tailwind/src/components/editor/advanced-editor.tsx#L84-L103
import { NodeSelector } from "./selectors/node-selector";
import { LinkSelector } from "./selectors/link-selector";
import { ColorSelector } from "./selectors/color-selector";

<EditorBubble
  tippyOptions={{
    placement: "top",
  }}
  className="flex w-fit max-w-[90vw] overflow-hidden rounded-md border border-muted bg-background shadow-xl"
>
  <Separator orientation="vertical" />
  <NodeSelector open={openNode} onOpenChange={setOpenNode} />
  <Separator orientation="vertical" />

  <LinkSelector open={openLink} onOpenChange={setOpenLink} />
  <Separator orientation="vertical" />
  <TextButtons />
  <Separator orientation="vertical" />
  <ColorSelector open={openColor} onOpenChange={setOpenColor} />
</EditorBubble>

EditorCommand

command PNG

노션에서 / 를 입력하면 나오는 단축키 기능이다.

// https://github.com/steven-tey/novel/blob/main/examples/novel-tailwind/src/components/editor/slash-command.tsx
export const suggestionItems = createSuggestionItems([
  {
    title: "Send Feedback",
    description: "Let us know how we can improve.",
    icon: <MessageSquarePlus size={18} />,
    command: ({ editor, range }) => {
      editor.chain().focus().deleteRange(range).run();
      window.open("/feedback", "_blank");
    },
  },
  {
    title: "Text",
    description: "Just start typing with plain text.",
    searchTerms: ["p", "paragraph"],
    icon: <Text size={18} />,
    command: ({ editor, range }) => {
      editor
        .chain()
        .focus()
        .deleteRange(range)
        .toggleNode("paragraph", "paragraph")
        .run();
    },
  },
  ...
)

// https://github.com/steven-tey/novel/blob/ecdb5d2ff5d3e6ab5f5af95b5a81de3ab4e8a0e9/examples/novel-tailwind/src/components/editor/advanced-editor.tsx#L62C9-L81C31
<EditorCommandList>
  {suggestionItems.map((item) => (
    <EditorCommandItem
      value={item.title}
      onCommand={(val) => item.command?.(val)}
      className={`flex w-full items-center space-x-2 rounded-md px-2 py-1 text-left text-sm hover:bg-accent aria-selected:bg-accent `}
      key={item.title}
    >
      <div className="flex h-10 w-10 items-center justify-center rounded-md border border-muted bg-background">
        {item.icon}
      </div>
      <div>
        <p className="font-medium">{item.title}</p>
        <p className="text-xs text-muted-foreground">{item.description}</p>
      </div>
    </EditorCommandItem>
  ))}
</EditorCommandList>;



수정해야 할 문제?

  • Block 단위의 DND가 잘 안된다.
    1 PNG

네모 박스와 같은 drag-handler를 따로 추가해야할듯



TMI 링크

개발 문서

⚓️ 사용자 피드백과 버그 기록
👷🏻 기술적 도전
📖 위키와 학습정리
🚧 트러블슈팅

팀 문화

🧸 팀원 소개
⛺️ 그라운드 룰
🍞 커밋 컨벤션
🧈 이슈, PR 컨벤션
🥞 브랜치 전략

그룹 기록

📢 발표 자료
🌤️ 데일리 스크럼
📑 회의록
🏖️ 그룹 회고
🚸 멘토링 일지
Clone this wiki locally