Zenn을 위해 미리 보기를 하면서 글을 쓸 수 있는 태그 다운로드 편집기의 이야기를 개발했다

26988 단어 ReactMarkdowntech
저는 개발자의 친구로서 Zenn의 개발에 참여했습니다.지금은 이미 학급 방법에 양도되었기 때문에 나는 개발에 참여하지 않았다.
젠은 아직 탑재되지는 않았지만 기사의 결과를 미리 보면서 표기하는 편집을 개발했기 때문에 그 편집자의 공양으로도 미리 보도해야 한다고 생각한다.

개발물


미리 보면서 글을 쓸 수 있는 React 제판 상표 편집

이 편집기를 오픈 원본 코드로 창고에 공개합니다!
https://github.com/steelydylan/react-split-mde

특징.

  • 스크롤 동기화
  • TypeScript Friendly
  • 줄 바꿈 시 자동으로 목록 삽입
  • 탭 키를 입력할 때 목록 들여쓰기
  • 태그 파서
  • 를 사용자 정의할 수 있음
  • 이벤트를 정의할 수 있음
  • 고유한 단축키 명령 정의
  • https://react-split-mde.vercel.app/

    도대체 왜 개발된 건지.


    기존 편집자가 Qita보다 못한 점이 있는데...


    이처럼 트위터에 젠에 대한 글을 올릴 때 많은 이들이 미리 보면서 기사를 쓰길 원한다.확실히 Qita라면 HTML로 변환한 결과가 가로로 배열돼 있어 쓰기 쉽다.

    이미 공개된 편집에 만족할 수 없는 기능


    그래서 나는 먼저 그런 표지와 미리보기로 나누어 기사를 쓸 수 있는 편집자를 찾았다.
    이미 몇 개의 공개 편집자가 있다.
    https://github.com/sparksuite/simplemde-markdown-editor
    젠은 독자적인 표기 방법이 많기 때문에 맞춤형 서비스를 할 수 있는 기능이 있어야 한다.그러나 Mardown에서 HTML로 변환할 수 있는 파트를 혼자 맞춤형으로 편집하는 경우는 드물다.

    스크롤 동기화 문제


    태그 하강 결과가 사용자 정의되더라도 글이 굴러가는 위치에 따라 미리 보기 결과를 굴릴 수 없으면 결국 수동으로 굴러가기 때문에 불편도는 크게 달라지지 않는다.마크의 독자 기법을 스스로 정의할 수 있고, 스크롤도 동기화할 수 있기 때문에, 이렇게 편리한 편집은 자신이 찾는 범위가 아니다.

    자신의 단축키 명령을 정의해야 합니다.


    또 젠은 시크한 UI도 판매하기 때문에 여분의 편집 장식을 줄이려는 생각도 있다.
    또한 이미지 업로드 기능과 트위터 등 삽입부품의 호출ショートカットコマンド에서 원하는 모호 기능도 맞춤형으로 충족해야 한다.

    트위터 등 위젯의 재작성 문제


    젠에서는 글에 트위터, 지스트, 유튜브 위젯을 삽입할 수 있다.
    대부분의 커서 편집에서는 글을 쓸 때마다 모든 미리보기 결과를 다시 보여 주기 때문에 글을 쓸 때 미리보기 결과가 굴러가는 위치가 자주 변합니다.
    현재 쓰고 있는 기사의 행의 구조를 다시 과장해야 한다는 것이다.따라서 개발된react-split-mde에서 사용morphdom 프로그램 라이브러리는 편집 중인 요소만 재현한다.

    사용법


    어렵게 개발한 거라 사용법을 조금 소개해 드릴게요.아직 완성되지 않은 만큼 앞으로 규격이 바뀔 가능성도 있다.

    설치 방법


    $ yarn add react-split-mde
    
    또는
    $ npm install react-split-mde
    

    간단한 사용법


    맞춤형 제작이 없으면 이것만으로도 이동이 가능합니다.
    import { useState } from "react"
    import { Editor } from "react-split-mde"
    import "react-split-mde/css/index.css"
    const defaultValue = "# React Split MDE"
    
    export const EditorDemo = () => {
      const [value, setValue] = useState(defaultValue)
      const handleValueChange = (newValue) => {
        setValue(newValue)
      }
      return (<Editor 
        value={value}
        onChange={handleValueChange} 
      />)
    }
    

    이미지 삽입 샘플

    Provider를 사용하면 텍스트 삽입과 방향을 바꾸는 등 다양한 이벤트를 편집자에게 전달할 수 있습니다.
    다음은 파일을 선택할 때 이 파일 내용을 편집기에 삽입하는 간단한 샘플 코드입니다.
    import { useState, useCallback } from "react"
    import { Editor, useProvider } from "react-split-mde"
    import "react-split-mde/css/index.css"
    const defaultValue = "# React Split MDE"
    export const EditorDemo = () => {
      const [emit, Provider] = useProvider()
      const [value, setValue] = useState(defaultValue)
      const handleImageUpload = useCallback(
        async (e: React.ChangeEvent<HTMLInputElement>) => {
          const uploadingMsg = "![](now uploading...)";
          emit({
            type: "insert",
            text: uploadingMsg,
          });
          await new Promise((resolve) => {
            setTimeout(() => resolve(), 1000);
          });
          emit({
            type: "replace",
            targetText: uploadingMsg,
            text: "![](https://source.unsplash.com/1600x900/?nature,water)",
          });
        },
        []
      )
      const handleValueChange = (newValue) => {
        setValue(newValue)
      }
      return (
        <Provider>
          <input type="file" onChange={handleImageUpload} />
          <Editor
            value={value} 
            onChange={handleValueChange} 
          />
        </Provider>
      )
    }
    

    단축키 명령 사용자화


    다음 코드는 Enter 키와 명령 키를 동시에 입력할 때 발생하는 이벤트의 예입니다.
    import { useState } from "react"
    import { Editor, defaultCommands } from "react-split-mde"
    import "react-split-mde/css/index.css"
    const defaultValue = "# React Split MDE"
    export const EditorDemo = () => {
      const [value, setValue] = useState(defaultValue)
      const handleValueChange = (newValue) => {
        setValue(newValue)
      }
      return (<Editor
        value={value} 
        onChange={handleValueChange}
        commands={
          ...defaultCommands,
          save: (textarea, option) => {
            const { composing, code, shiftKey, metaKey, ctrlKey } = option;
            if ((metaKey || ctrlKey) && !shiftKey) {
              if (!composing && code === EnterKey) {
                // ここに実行したい関数を定義します。
                return { stop: true, change: false };
              }
            }
          },
        }
      />)
    }
    

    웹 워커와 함께 사용

    react-split-mde에서 Parer를 독자적으로 정의할 수 있기 때문에 Parer 자체는 웹 워커 등을 통해 실행하고 결과를 편집에 맡기면 맞춤형 제작도 가능하다.어때요? 웹 워커를 사용하는 샘플입니다.
    markdown.worker.ts
    const ctx: Worker = self as any;
    ctx.Prism = {}
    ctx.Prism.disableWorkerMessageHandler = true;
    // you have to disable prism worker handle option first
    import markdownHTML, { enablePreview } from "zenn-markdown-html";
    enablePreview();
    // Respond to message from parent thread
    ctx.addEventListener("message", (event) => {
      const result = markdownHTML(event.data);
      ctx.postMessage(result);
    });
    
    editor.tsx
    import Worker from "worker-loader!./markdown.worker";
    import pEvent from "p-event";
    import { useState, useMemo } from "react"
    import { Editor } from "react-split-mde"
    import "react-split-mde/css/index.css"
    const defaultValue = "# React Split MDE"
    export const EditorDemo = () => {
      const worker = useMemo(() => {
        const w = new Worker();
        return w;
      }, []);
      const [value, setValue] = useState(defaultValue)
      const handleValueChange = (newValue: string) => {
        setValue(newValue)
      }
      const handleMarkdown = async (str: string) => {
        worker.postMessage(str);
        const e = await pEvent(worker, "message");
        return e.data;
      };
      return (<Editor 
        value={value}
        parser={handleMarkdown}
        onChange={handleValueChange} 
      />)
    }
    

    총결산


    너무 길면 개발된 프로그램 라이브러리의 소개가 될 수 있으니 이 근처에 두세요.
    이 기사에서 제가 말씀드리고 싶은 것은 공개된 많은 넉다운자, 굴러가는 문제, 넉다운 문제, 과장된 문제 등 넘어야 할 많은 장애물들이 존재한다는 것입니다. 이 벽을 돌파하기 위해 다양한 개발을 노력했습니다.
    현재 Zenn은 이미 유형 방법에 의해 인수되었기 때문에 자신은 개발과 무관하지만 라이브러리 자체의 개발은 개방원으로 개발되었기 때문에 계속 진행할 수 있다.언젠가 우리는 Zenn 측npm install에서 dependencies가 사용될 날을 기다리며 계속 열심히 개발할 것입니다!

    좋은 웹페이지 즐겨찾기