Make checkboxes enabled and change markdown when changing checkbox

155 views Asked by At

I have this basic code that renders inputted md as html, and by default all checkboxes are disabled and even if I make them enabled with developer menu in browser they are still can`t be checked. How can I make them checkable, and how can I change the markdown according to "preview mode" where I'm changing state of these checkboxes?

I tried using the Rehype library but it didn't go well, which is why I'm asking this question.

import { createElement } from "react";
import { unified } from "unified";
import remarkParse from "remark-parse";
import remarkGfm from "remark-gfm";
import remarkReact from "remark-react/lib";
import { PreviewWindow } from "./style";
import RemarkCode from "./remarkCode";
import { defaultSchema } from "hast-util-sanitize";
import "github-markdown-css/github-markdown.css";
import { ViewMode } from "../types";
import remarkRehype from "remark-rehype";
import rehypeDocument from "rehype-document";
import rehypeFormat from "rehype-format";
import rehypeStringify from "rehype-stringify";
import rehypeReact from "rehype-react";

interface Props {
  doc: string;
  mode: ViewMode;
}

const schema = {
  ...defaultSchema,
  attributes: {
    ...defaultSchema.attributes,
    code: [...(defaultSchema.attributes?.code || []), "className"],
  },
};

const Preview = (props: Props) => {
  const { doc, mode } = props;

  if (mode !== ViewMode.Edit) {
    const md = unified()
      .use(remarkParse)
      .use(remarkGfm)
      // .use(remarkRehype)
      // .use(rehypeDocument)
      // .use(rehypeFormat)
      // .use(rehypeStringify)
      .use(remarkReact, {
        createElement: createElement,
        sanitize: schema,
        remarkReactComponents: {
          code: RemarkCode,
        },
      } as any)
      // .use(rehypeReact, {
      //   createElement: createElement,
      //   sanitize: schema,
      //   remarkReactComponents: {
      //     code: RemarkCode,
      //   },
      // } as any)
      .processSync(doc).result;

    return (
      <PreviewWindow $mode={mode} className="markdown-body editor">
        {" "}
        {md as any}
      </PreviewWindow>
    );
  }
};

export default Preview;

import { MutableRefObject, useEffect, useRef, useState } from "react";
import { defaultKeymap, history, historyKeymap } from "@codemirror/commands";
import { EditorState } from "@codemirror/state";
import { EditorView, keymap, highlightActiveLine, lineNumbers, highlightActiveLineGutter, drawSelection } from "@codemirror/view";
import { syntaxHighlighting, HighlightStyle, indentOnInput, bracketMatching } from "@codemirror/language";
import { tags } from "@lezer/highlight";
import { markdown, markdownLanguage } from "@codemirror/lang-markdown";
import { languages } from "@codemirror/language-data";
import { oneDark } from "@codemirror/theme-one-dark";
import { vim, Vim } from "@replit/codemirror-vim";

interface Props {
  initialDoc: string,
  onChange?: (state: EditorState) => void
}

const transparentTheme = EditorView.theme({
  "&": {
    backgroundColor: "transparent !important",
    height: "100%"
  }
});

const syntaxHighlightingCustom = HighlightStyle.define([
  {
    tag: tags.heading1,
    fontSize: "1.6em",
    fontWeight: "bold"
  },
  {
    tag: tags.heading2,
    fontSize: "1.4em",
    fontWeight: "bold"
  },
  {
    tag: tags.heading3,
    fontSize: "1.2em",
    fontWeight: "bold"
  }
]);

const useCodeMirror = <T extends Element>(
  props: Props
): [MutableRefObject<T | null>, EditorView?] => {
  const refContainer = useRef<T>(null);
  const [editorView, setEditorView] = useState<EditorView>();
  const { onChange } = props;
  useEffect(() => {
    if (!refContainer.current) return;

    const startState = EditorState.create({
      doc: props.initialDoc,
      extensions: [
        vim(),
        keymap.of([...defaultKeymap, ...historyKeymap]),
        lineNumbers(),
        highlightActiveLineGutter(),
        history(),
        indentOnInput(),
        bracketMatching(),
        highlightActiveLine(),
        drawSelection(),
        markdown({
          base: markdownLanguage,
          codeLanguages: languages,
          addKeymap: true
        }),
        oneDark,
        transparentTheme,
        syntaxHighlighting(syntaxHighlightingCustom),
        EditorView.lineWrapping,
        EditorView.updateListener.of(update => {
          if (update.changes) {
            onChange && onChange(update.state);
          }
        })
      ]
    });

    Vim.map(":", "<Esc>");

    const view = new EditorView({
      state: startState,
      parent: refContainer.current
    });

    setEditorView(view);

    return () => {
      view.destroy();
    }
  }, [refContainer]);

  return [refContainer, editorView];
}

export default useCodeMirror;
import { EditorState } from "@codemirror/state";
import { useCallback } from "react";
import useCodeMirror from "./useCodeMirror";
import { EditorWindow } from "./style";
import { ViewMode } from "../types";

interface Props {
  initialDoc: string,
  mode: ViewMode
  onChange: (doc: string) => void
}

const Editor = (props: Props) => {
  const { onChange, initialDoc, mode } = props;

  if (mode !== ViewMode.Preview) {
    const handleChange = useCallback(
      (state: EditorState) => onChange(state.doc.toString()),
      [onChange]
    );
    const [refContainer, editorView] = useCodeMirror<HTMLDivElement>({
      initialDoc,
      onChange: handleChange
    });

    return <EditorWindow $mode={mode} ref={refContainer}></EditorWindow>
  }
}

export default Editor;
0

There are 0 answers