WaniKani Markdown Editor Notes (2023)

Write Markdown and HTML in the notes

目前为 2023-06-18 提交的版本。查看 最新版本

// ==UserScript==
// @name         WaniKani Markdown Editor Notes (2023)
// @namespace    wanikani
// @description  Write Markdown and HTML in the notes
// @version      2.0.1
// @require      https://uicdn.toast.com/editor/latest/toastui-editor-all.min.js
// @require      https://unpkg.com/dexie@3/dist/dexie.js
// @require      https://gf.qytechs.cn/scripts/430565-wanikani-item-info-injector/code/WaniKani%20Item%20Info%20Injector.user.js?version=1207013
// @icon         https://www.google.com/s2/favicons?sz=64&domain=markdownguide.org
// @match        *://www.wanikani.com/*
// @match        *://preview.wanikani.com/*
// @license      MIT
// @homepage     https://gf.qytechs.cn/en/scripts/468764-wanikani-markdown-editor-notes-2023
// @source       https://github.com/patarapolw/wanikani-userscript/blob/master/userscripts/markdown-notes.user.js
// @supportURL   https://community.wanikani.com/t/userscript-markdown-editor-notes-2023/62246
// @grant        none
// ==/UserScript==

// @ts-check
/// <reference path="./types/item-info.d.ts" />
(function () {
  'use strict';

  const entryClazz = 'wk-markdown-notes';

  // @ts-ignore
  const _Dexie = /** @type {typeof import('dexie').default} */ (Dexie);
  /**
   * @typedef {{ id: number; state: any; markdown: string }} EntryMarkdown
   */

  class Database extends _Dexie {
    /** @type {import('dexie').Table<EntryMarkdown, number>} */
    markdown;

    constructor() {
      super(entryClazz);
      this.version(1).stores({
        markdown: 'id',
      });
    }
  }

  const db = new Database();

  /** @type {HTMLElement} */
  let elEditor;
  /** @type {import('@toast-ui/editor').Editor} */
  let editor;
  /** @type {WKItemInfoState} */
  let state;

  const injector = wkItemInfo
    .under('meaning,reading')
    .spoiling('nothing')
    .append('Markdown Notes', (o) => {
      if (editor) {
        save();
      }

      state = o;

      const onElLoaded = () => {
        db.markdown.get(state.id).then((entry) => {
          if (editor) {
            editor.setMarkdown(entry?.markdown || '');
            setTimeout(() => {
              editor.blur();
            });
          } else {
            /** @type {import('@toast-ui/editor').EditorOptions} */
            const opts = {
              el: elEditor,
              initialEditType: 'markdown',
              previewStyle: 'vertical',
              hideModeSwitch: true,
              linkAttributes: {
                target: '_blank',
              },
              previewHighlight: false,
              customHTMLSanitizer: (s) => {
                return s;
              },
              autofocus: false,
              initialValue: entry?.markdown,
            };

            // @ts-ignore
            editor = new toastui.Editor(opts);

            const elSave = document.createElement('button');
            elSave.type = 'button';
            elSave.className = 'fa fa-save save-button';

            elSave.onclick = () => {
              elSave.classList.add(isClickedClass);
              save();
              setTimeout(() => {
                elSave.classList.remove(isClickedClass);
              }, 100);
            };

            editor.insertToolbarItem(
              { groupIndex: -1, itemIndex: -1 },
              {
                name: 'Save',
                el: elSave,
              },
            );

            editor.on('blur', () => {
              save();
            });
          }
        });
      };

      if (!elEditor) {
        elEditor = document.createElement('div');
        elEditor.id = 'wk-markdown-editor';
        elEditor.lang = 'ja';
        elEditor.onkeydown = (ev) => {
          ev.stopImmediatePropagation();
          ev.stopPropagation();
        };
      }

      onElLoaded();

      return elEditor;
    });

  window.addEventListener('willShowNextQuestion', () => {
    injector.renew();
  });

  function save() {
    if (editor) {
      db.markdown.put(
        { id: state.id, state, markdown: editor.getMarkdown() },
        state.id,
      );

      if (!elEditor) {
        editor.destroy();
      }
    }
  }

  const isClickedClass = 'is-clicked';

  add_css(/* css */ `
    @import url("https://uicdn.toast.com/editor/latest/toastui-editor.min.css");

    .toastui-editor-defaultUI {
      background-color: #fff;
    }

    .toastui-editor-defaultUI button.save-button {
      position: relative;
      background: transparent;
      font-size: 1em;
      bottom: 0.5em;
    }

    .toastui-editor-defaultUI button.save-button.${isClickedClass} {
      background-color: gray;
    }
  `);

  function add_css(css) {
    const style = document.createElement('style');
    style.append(document.createTextNode(css));
    document.head.append(style);
  }
})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址