Ace をベースにした Markdown エディターを共有する

Ace をベースにした Markdown エディターを共有する

エディターは 2 つのカテゴリに分かれていると思います。1 つは、即時レンダリングを実現するために左側と右側に分かれているもので、もう 1 つは、最初に構文を記述してからボタンを介してレンダリングを実現するものです。

実は、リアルタイムレンダリングは難しくありません。考慮すべき共通の問題はXSSです。レンダリングライブラリはサードパーティのXSSフィルタリングをカスタマイズできるため(以前は設定で実現、つまり付属していましたが、あるバージョン以降はキャンセルされました)、XSSは公式に推奨されているdompurifyを使用します。エディター独自の API を使用してテキストの変更を監視することで、リアルタイム レンダリングを実現できます。考慮する必要があるもう 1 つの問題は、コードとレンダリング領域の対応です。しかし、これは私のニーズに反するため、ここでは紹介しません。小さなボスなら簡単に実現できると信じています。

統一された慣例、効果図を見てみましょう

図1
図2

上記のツールバーは実際にイベントを追加し、対応するステートメントをカーソルに挿入します。絵文字はまだ実装されておらず、サードパーティのライブラリからのサポートが必要なようです。

全体的には難しい点はありませんが、これらの点については、ドキュメントが散在していて不明瞭であるか、ドキュメントが見つからないかのどちらかです。本当にドキュメントがなかったり、公式ドキュメントが非常に単純な場合は、彼に挨拶したくなるかもしれません、ハハハ。このとき、使えるコードであることが特に重要です。コメントは多くないかもしれませんが、その意味を理解できるほど賢い人であると信じています。では早速、コードを見てみましょう〜

<テンプレート>
  <div>
    <div class="section-ace">
      <el-行>
        <el-col :span="6">
          <el-行>
            <el-col :span="12">
              <a class="editor-tab-content" :class="isEditActive" @click="showEdit">
                <i class="fa fa-pencil-square-o" aria-hidden="true"></i>
                編集
            </el-col>
            <el-col :span="12">
              <a class="preview-tab-content" :class="isPreviewActive" @click="showPreview">
                <i class="fa fa-eye" aria-hidden="true"></i>
                プレビュー
            </el-col>
          </el-row>
        </el-col>
        <el-col :push="8" :span="18">
          <el-行>
            <div class="ツールバー">
              <el-col :span="1">
                <div>
                  <i @click="insertBoldCode" class="fa fa-bold" aria-hidden="true"></i>
                </div>
              </el-col>
              <el-col :span="1">
                <div>
                  <i @click="挿入イタリックコード" クラス="fa fa-italic" aria-hidden="true"></i>
                </div>
              </el-col>
              <el-col :span="1">
                <div>
                  <i @click="insertMinusCode" class="fa fa-minus" aria-hidden="true"></i>
                </div>
              </el-col>
              <el-col :span="1">
                <el-popover 配置="下"
                            幅="125"
                            transition="フェードインリニア"
                            トリガー="クリック"
                            コンテンツ="">
                  <i slot="reference" class="fa fa-header" aria-hidden="true"></i>
                  <div>
                    <div class="header1-btn" :class="isHeader1Active" @click="insertHeader1Code">
                      見出し 1 (Ctrl+Alt+1)
                    </div>
                    <div class="header2-btn" :class="isHeader2Active" @click="insertHeader2Code">
                      見出し2 (Ctrl+Alt+2)
                    </div>
                    <div class="header3-btn" :class="isHeader3Active" @click="insertHeader3Code">
                      見出し 3 (Ctrl+Alt+3)
                    </div>
                  </div>
                </el-popover>
              </el-col>
              <el-col :span="1">
                <el-popover 配置="下"
                            幅="125"
                            transition="フェードインリニア"
                            トリガー="クリック"
                            コンテンツ="">
                  <i slot="reference" class="fa fa-code" aria-hidden="true"></i>
                  <div>
                    <div class="text-btn" :class="isTextActive" @click="insertText">
                      テキスト (Ctrl+Alt+P)
                    </div>
                    <div class="code-btn" :class="isCodeActive" @click="挿入コード">
                      コード (Ctrl+Alt+C)
                    </div>
                  </div>
                </el-popover>
              </el-col>
              <el-col :span="1">
                <div>
                  <i @click="insertQuoteCode" class="fa fa-quote-left" aria-hidden="true"></i>
                </div>
              </el-col>
              <el-col :span="1">
                <div>
                  <i @click="insertUlCode" class="fa fa-list-ul" aria-hidden="true"></i>
                </div>
              </el-col>
              <el-col :span="1">
                <div>
                  <i @click="insertOlCode" class="fa fa-list-ol" aria-hidden="true"></i>
                </div>
              </el-col>
              <el-col :span="1">
                <div>
                  <i @click="insertLinkCode" class="fa fa-link" aria-hidden="true"></i>
                </div>
              </el-col>
              <el-col :span="1">
                <div>
                  <i @click="insertImgCode" class="fa fa-picture-o" aria-hidden="true"></i>
                </div>
              </el-col>
              <el-col :span="1">
                <div>
                  <el-アップロード
                    クラス="アップロードデモ"
                    アクション="https://jsonplaceholder.typicode.com/posts/"
                    :limit="1">
                    <i class="fa fa-cloud-upload" aria-hidden="true"></i>
                  </el-アップロード>
                </div>
              </el-col>
              <el-col :span="1">
                <div>
                  <i @click="selectEmoji" class="fa fa-smile-o" aria-hidden="true"></i>
                </div>
              </el-col>
              <el-col :span="1">
                <div>
                  <i @click="toggleMaximize" class="fa fa-arrows-alt" aria-hidden="true"></i>
                </div>
              </el-col>
              <el-col :span="1">
                <i @click="toggleHelp" class="fa fa-question-circle" aria-hidden="true"></i>
                <el-dialog :visible.sync="ダイアログヘルプが表示可能"
                           :show-close="false"
                           トップ= "5vh"
                           幅="60%"
                           :本文に追加="true"
                           :close-on-press-escape="true">
                  <el-card class="box-card" style="margin: -60px -20px -30px -20px">
                    <div スロット="ヘッダー" クラス="helpHeader">
                      <i class="fa fa-question-circle" aria-hidden="true"><span>マークダウン ガイド</span></i>
                    </div>
                    <p>このサイトはMarkdownで作成されています。完全なドキュメントについては、
                      <a href="http://commonmark.org/help/" rel="external nofollow" target="_blank">ここをクリック</a>
                    </p>
                    <el-テーブル
                      :data="テーブルデータ"
                      ストライプ
                      国境
                      :highlight-current-row="true"
                      スタイル="幅: 100%">
                      <el-テーブル列
                        prop="コード"
                        label="コード"
                        幅="150">
                        <テンプレート スロット スコープ="スコープ">
                          <p v-html='scope.row.code'></p>
                        </テンプレート>
                      </el-table-column>
                      <el-テーブル列
                        prop="または"
                        label="または"
                        幅="180">
                        <テンプレート スロット スコープ="スコープ">
                          <p v-html='scope.row.or'></p>
                        </テンプレート>
                      </el-table-column>
                      <el-テーブル列
                        prop="デバイス"
                        ラベル="Linux/Windows">
                      </el-table-column>
                      <el-テーブル列
                        prop="デバイス"
                        ラベル="Mac OS"
                        幅="180">
                      </el-table-column>
                      <el-テーブル列
                        プロパティ="表示オフ"
                        label="... 取得する"
                      幅="200">
                        <テンプレート スロット スコープ="スコープ">
                          <p v-html='scope.row.showOff'></p>
                        </テンプレート>
                      </el-table-column>
                    </el-table>
                  </el-card>
                </el-ダイアログ>
              </el-col>
            </div>
          </el-row>
        </el-col>
      </el-row>
    </div>
    <br>
    <div id="コンテナ">
      <div class="show-panel">
        <div ref="markdown" class="ace" v-show="!isShowPreview"></div>
        <div class="panel-preview" ref="preview" v-show="isShowPreview"></div>
      </div>
    </div>
  </div>
</テンプレート>
<スクリプト>
'ace-builds' から ace をインポートします
// webpack 環境で使用するには、 import 'ace-builds/webpack-resolver' をインポートする必要があります。
'marked' から marked をインポートする
「highlight.js」からハイライトをインポートします。
「highlight.js/styles/foundation.css」をインポートします。
'katex' から katex をインポートします
'katex/dist/katex.css' をインポートします
'dompurify' から DOMPurify をインポートします。

const レンダラー = 新しい marked.Renderer();
関数toHtml(テキスト){
  temp = document.createElement("div"); とします。
  temp.innerHTML = テキスト;
  出力を temp.innerText || temp.textContent とします。
  温度 = null;
  出力を返します。
}

関数 mathsExpression(expr) {
  (expr.match(/^\$\$[\s\S]*\$\$$/))の場合{
    expr = expr.substr(2, expr.length - 4);
    katex.renderToString(expr, { displayMode: true }) を返します。
  } そうでない場合 (expr.match(/^\$[\s\S]*\$$/)) {
    expr = toHtml(expr); // 一時的なソリューション
    expr = expr.substr(1, expr.length - 2);
    //これはテキストが動的にページに追加されることを意味しますか?もしそうなら、誰かがKaTeXを呼び出してレンダリングしているはずです
    // それに加えて、その呼び出しでは strict フラグも false に設定する必要があります。つまり、% がエスケープされている、中国語であるなどのコンソール警告が表示されなくなります // リンク: https://katex.org/docs/options.html
    katex.renderToString(expr, { displayMode: false , strict: false}); を返します。
  }
}

const 未変更 = 新しい marked.Renderer()
renderer.code = function(コード、言語、エスケープ) {
  console.log(言語);
  const isMarkup = ['c++', 'cpp', 'golang', 'java', 'js', 'javascript', 'python'].includes(language);
  hled = '' とします。
  if (isMarkup) {
    const math = mathsExpression(コード);
    if (数学) {
      数学を返します。
    } それ以外 {
      console.log("ハイライト");
      hled = highlight.highlight(言語、コード).value;
    }
  } それ以外 {
    console.log("ハイライト自動");
    hled = highlight.highlightAuto(コード).値;
  }
  `<pre class="hljs ${language}"><code class="${language}">${hled}</code></pre>` を返します。
  // 未変更のコード(コード、言語、エスケープ済み)を返します。
};
renderer.codespan = function(テキスト) {
  const math = mathsExpression(テキスト);
  if (数学) {
    数学を返します。
  }
  変更せずにcodespan(text)を返します。
};

エクスポートデフォルト{
  名前: "abc",
  小道具: {
    価値: {
      タイプ: 文字列、
      必須: true
    }
  },
  データ() {
    戻る {
      テーブルデータ: [{
        コード: ':emoji_name:',
        または: '-'、
        デバイス: '—',
        デバイス: '-'、
        見せびらかす: '🧡'
      },{
        コード: '*イタリック体*',
        または: '_イタリック_'、
        デバイス: 'Ctrl+I'、
        デバイス: 'Command+I'、
        showOff: '<em>イタリック体</em>'
      },{
        コード: '**太字**'、
        または: '__太字__'、
        デバイス: 'Ctrl+B'、
        デバイス: 'Command+B'、
        showOff: '<em>太字</em>'
      },{
        コード: '++アンダースコア++',
        または: '-'、
        デバイス: 'Shift+U'、
        デバイス: 'Option+U'、
        showOff: '<ins>アンダースコア</ins>'
      },{
        コード: '~~取り消し線~~',
        または: '-'、
        デバイス: 'Shift+S'、
        デバイス: 'Option+S'、
        showOff: '<del>取り消し線</del>'
      },{
        コード: '# 見出し 1',
        または: '見出し 1<br>=========',
        デバイス: 'Ctrl+Alt+1'、
        デバイス: 'Command+Option+1'、
        showOff: '<h1>見出し 1</h1>'
      },{
        コード: '## 見出し 2',
        または: '見出し 2<br>-----------'、
        デバイス: 'Ctrl+Alt+2'、
        デバイス: 'Command+Option+2',
        showOff: '<h2>見出し 1</h2>'
      },{
        コード: '[リンク](https://a.com)',
        または: '[リンク][1]<br>⁝<br>[1]: https://b.org',
        デバイス: 'Ctrl+L'、
        デバイス: 'Command+L'、
        showOff: '<a href="https://commonmark.org/" rel="external nofollow" >リンク</a>'
      },{
        コード: '![画像](http://url/a.png)',
        または: '![画像][1]<br>⁝<br>[1]: http://url/b.jpg',
        デバイス: 'Ctrl+Shift+I'、
        デバイス: 'Command+Option+I'、
        表示オフ: '<img src="https://cdn.acwing.com/static/plugins/images/commonmark.png" width="36" height="36" alt="Markdown">'
      },{
        コード: '> 引用',
        または: '-'、
        デバイス: 'Ctrl+Q'、
        デバイス: 'Command+Q'、
        showOff: '<blockquote><p>Blockquote</p></blockquote>'
      },{
        コード: '段落。<br><br>1 行の空白行の後に段落。',
        または: '-'、
        デバイス: '—',
        デバイス: '-'、
        showOff: '<p>段落。</p><p>1 行の空白行の後に段落。</p>'
      },{
        コード: '<p>* リスト<br> * リスト<br> * リスト</p>',
        または: '<p> - リスト<br> - リスト<br> - リスト<br></p>',
        デバイス: 'Ctrl+U'、
        デバイス: 'Command+U'、
        showOff: '<ul><li>リスト</li><li>リスト</li><li>リスト</li></ul>'
      },{
        コード: '<p> 1. 1<br> 2. 2<br> 3. 3</p>',
        または: '<p> 1) 1<br> 2) 2<br> 3) 3</p>'、
        デバイス: 'Ctrl+Shift+O'、
        デバイス: 'Command+Option+O'、
        showOff: '<ol><li>1</li><li>2</li><li>3</li></ol>'
      },{
        コード: '水平線<br><br>-----------',
        または: '水平線<br><br>***********'、
        デバイス: 'Ctrl+H'、
        デバイス: 'Command+H'、
        showOff: '水平線<hr>'
      },{
        コード: '`バッククォート付きインラインコード`',
        または: '-'、
        デバイス: 'Ctrl+Alt+C'、
        デバイス: 'Command+Option+C'、
        showOff: '<code>インライン コード</code> (バッククォート付き)'
      },{
        コード: '```<br> def whatever(foo):<br>&nbsp;&nbsp;&nbsp;&nbsp;return foo<br>```',
        または: '<b>タブ / 4 つのスペースを使用</b><br>....def whatever(foo):<br>....&nbsp;&nbsp;&nbsp;&nbsp;return foo',
        デバイス: 'Ctrl+Alt+P'、
        デバイス: 'Command+Option+P'、
        表示オフ: '<pre class="hljs"><code class=""><span class="hljs-function"><span class="hljs-keyword">def</span>' +
          '<span class="hljs-title">何でも</span><span class="hljs-params">(foo)</span></span>:\n' +
          ' <span class="hljs-keyword">戻り値</span> foo</code></pre>'
      }],
      dialogHelpVisible: false、
      テキストアクティブ: ''、
      isCodeActive: ''、
      isHeader1アクティブ: ''、
      isHeader2アクティブ: ''、
      isHeader3アクティブ: ''、
      isShowPreview: false、
      isEditActive: "アクティブ",
      プレビューアクティブ: "",
      aceEditor: null、
      themePath: 'ace/theme/crimson_editor', // webpack-resolver がインポートされていない場合、モジュール パスはエラーを報告します modePath: 'ace/mode/markdown', // 上記と同じ codeValue: this.value || '',
    };
  },
  メソッド: {
    太字コードを挿入する() {
      this.aceEditor.insert("****");
      カーソル位置を this.aceEditor.getCursorPosition() に設定します。
      this.aceEditor.moveCursorTo(カーソル位置.行、カーソル位置.列 - 2);
    },
    斜体コードを挿入する() {
      this.aceEditor.insert("__");
      カーソル位置を this.aceEditor.getCursorPosition() に設定します。
      this.aceEditor.moveCursorTo(カーソル位置.行、カーソル位置.列 - 1);
    },
    マイナスコードを挿入する() {
      カーソル位置を this.aceEditor.getCursorPosition() に設定します。
      this.aceEditor.insert("\n\n");
      this.aceEditor.insert("-----------");
      this.aceEditor.insert("\n\n");
      this.aceEditor.gotoLine(カーソル位置.row + 5, カーソル位置.column,true);
    },
    ヘッダー1コードを挿入する() {
      this.isHeader2Active = this.isHeader3Active = '';
      this.isHeader1Active = 'アクティブ';
      this.aceEditor.insert("\n\n");
      this.aceEditor.insert("#");
    },
    挿入ヘッダー2コード() {
      this.isHeader1Active = this.isHeader3Active = '';
      this.isHeader2Active = 'アクティブ';
      this.aceEditor.insert("\n\n");
      this.aceEditor.insert("##");
    },
    ヘッダー3コードを挿入する() {
      this.isHeader1Active = this.isHeader2Active = '';
      this.isHeader3Active = 'アクティブ';
      this.aceEditor.insert("\n\n");
      this.aceEditor.insert("###");
    },
    挿入テキスト() {
      カーソル位置を this.aceEditor.getCursorPosition() に設定します。
      this.isCodeActive = '';
      this.isTextActive = 'アクティブ';
      this.aceEditor.insert("```\n\n```");
      this.aceEditor.gotoLine(カーソル位置.row + 2、カーソル位置.column、true);
    },
    挿入コード() {
      カーソル位置を this.aceEditor.getCursorPosition() に設定します。
      this.isTextActive = '';
      this.isCodeActive = 'アクティブ';
      this.aceEditor.insert("``");
      this.aceEditor.moveCursorTo(カーソル位置.行、カーソル位置.列 + 1);
    },
    引用コードを挿入する() {
      this.aceEditor.insert("\n>");
      カーソル位置を this.aceEditor.getCursorPosition() に設定します。
      this.aceEditor.moveCursorTo(カーソル位置.行、カーソル位置.列 + 1);
    },
    挿入UlCode() {
      this.aceEditor.insert("\n*");
      カーソル位置を this.aceEditor.getCursorPosition() に設定します。
      this.aceEditor.moveCursorTo(カーソル位置.行、カーソル位置.列 + 1);
    },
    挿入Olコード() {
      this.aceEditor.insert("\n1.");
      カーソル位置を this.aceEditor.getCursorPosition() に設定します。
      this.aceEditor.moveCursorTo(カーソル位置.行、カーソル位置.列 + 1);
    },
    挿入リンクコード() {
      this.aceEditor.insert("[]()");
      カーソル位置を this.aceEditor.getCursorPosition() に設定します。
      this.aceEditor.moveCursorTo(カーソル位置.行、カーソル位置.列 - 3);
    },
    挿入画像コード() {
      this.aceEditor.insert("![]()");
      カーソル位置を this.aceEditor.getCursorPosition() に設定します。
      this.aceEditor.moveCursorTo(カーソル位置.行、カーソル位置.列 - 3);
    },
    アップロード画像() {
      this.aceEditor.insert("![]()");
    },
    絵文字を選択します(){
      this.aceEditor.insert("****");
    },
    トグル最大化() {
      this.aceEditor.insert("****");
    },
    トグルヘルプ() {
      this.dialogHelpVisible = !this.dialogHelpVisible;
    },
    表示編集() {
      this.$refs.preview.innerHTML = '';
      this.isEditActive = 'アクティブ';
      this.isPreviewActive = '';
      this.isShowPreview = false;
    },
    プレビューを表示(){
      これを表示します。
      this.isEditActive = '';
      this.isPreviewActive = 'アクティブ';
      this.isShowPreview = true;
    },
    表示(データ) {
      値を this.aceEditor.session.getValue() に設定します。
      this.$refs.preview.innerHTML = DOMPurify.sanitize(marked(value));
      console.log(DOMPurify.sanitize(マークされた値)));
    },
  },
  マウント() {
    this.aceEditor = ace.edit(this.$refs.markdown,{
      selectionStyle: 'line', //選択されたスタイルmaxLines: 1000, //最大行数。これを超えると自動的にスクロールバーが表示されますminLines: 22, //最小行数。最大行数に達していない場合、エディターは自動的に拡大縮小しますfontSize: 14, //エディターのフォントサイズtheme: this.themePath, //デフォルトのテーマmode: this.modePath, //デフォルトの言語モードtabSize: 4, //タブは4スペースに設定されていますreadOnly: false, //読み取り専用wrap: true,
      ハイライトアクティブライン: true、
      値: this.codeValue
    });
    マークされた.setOptions({
      レンダラー: レンダラー、
      // ハイライト: 関数 (コード) {
      // highlight.highlightAuto(code).value を返します。
      // },
      gfm: true, //デフォルトは true です。 Git Hub 標準のマークダウンを許可します。
      tables: true, //デフォルトは true です。 テーブル構文のサポートを有効にします。このオプションでは、gfm が true である必要があります。
      breaks: false, //デフォルトは false です。 復帰と改行を許可します。このオプションでは、gfm が true である必要があります。
      pedantic: false, //デフォルトは false です。 markdown.pl のわかりにくい部分と可能な限り互換性を持たせるようにしてください。元のモデルの不良動作やエラーは修正されません。
      // sanitize: false, // 出力をフィルター (クリーン) します。サポートされていません。レンダリング時に sanitizer またはフィルターを直接使用します。xhtml: true, // true の場合、XHTML で要求されているように、void 要素 (<br/>、<img/> など) に "/" を含む自己終了 HTML タグを出力します。
      silent: true, //true の場合、パーサーは例外をスローしません。
      スマートリスト: true、
      smartypants: false // 引用符内のダッシュなど、よりスマートな句読点を使用します。
    });
    // this.aceEditor.session.on('change', this.show);
    // that = this とします。
    // this.aceEditor.commands.addCommand({
    // 名前: 'コピー',
    // バインドキー: {win: 'Ctrl-C', mac: 'Command-M'},
    // 実行: 関数(エディター) {
    // that.$message.success("コピー成功");
    // }
    // });
    // this.aceEditor.commands.addCommand({
    // 名前: '貼り付け',
    // バインドキー: {win: 'Ctrl-V', mac: 'Command-M'},
    // 実行: 関数(エディター) {
    // that.$message.success("貼り付けに成功しました");
    // }
    // });
  },
  時計:
    値(新しい値) {
      コンソールにログ出力します。
      this.aceEditor.setValue(newVal);
    }
  }
}
</スクリプト>

<スタイル スコープ lang="scss">
.ツールバー{
  カーソル: ポインター; //マウスの手の形}
.show-panel {
  パディング: 5px;
  境界線: 1px 実線のライトグレー;
  .エース {
    位置: 相対 !重要;
    border-top: 1px 実線ライトグレー;
    表示: ブロック;
    マージン: 自動;
    高さ: 自動;
    幅: 100%;
  }
  .パネルプレビュー{
    パディング: 1rem;
    マージン: 0 0 0 0;
    幅: 自動;
    背景色: 白;
  }
}

.editor-tab-content、.preview-tab-content、.header1-btn、.header2-btn、.header3-btn、.text-btn、.code-btn{
  境界線下部の色: 透明;
  境界線下部のスタイル: solid;
  境界線の半径: 0;
  パディング: .85714286em 1.14285714em 1.29999714em 1.14285714em;
  境界線の下の幅: 2px;
  トランジション: カラー .1 秒のイーズ;
  カーソル: ポインター; //マウスの手の形}

.header1-btn、.header2-btn、.header3-btn、.code-btn、.text-btn {
  フォントサイズ: 5px;
  パディング: .78571429em 1.14285714em!重要;
}

。アクティブ {
  背景色: 透明;
  ボックスシャドウ: なし;
  境界線の色: #1B1C1D;
  フォントの太さ: 700;
  色: rgba(0,0,0,.95);
}

.header1-btn:hover、.header2-btn:hover、.header3-btn:hover、.text-btn:hover、.code-btn:hover {
  cursor: ポインター; //マウスの手の形状background: rgba(0,0,0,.05)!important;
  色: rgba(0,0,0,.95)!重要;
}

.helpヘッダー{
  フォントサイズ: 1.228571rem;
  行の高さ: 1.2857em;
  フォントの太さ: 700;
  左上の境界線の半径: .28571429rem;
  境界線の右上の半径: .28571429rem;
  表示: ブロック;
  フォントファミリー: Lato、'Helvetica Neue'、Arial、Helvetica、sans-serif;
  背景: #FFF;
  ボックスシャドウ: なし;
  色: rgba(0,0,0,.85);
}
</スタイル>

今回は、コードでは参照時に値、つまり編集ボックス内のコンテンツをバインドする必要があります。

<MarkdownEditor v-bind:value="''"></MarkdownEditor>

ああ、そういえば、言い忘れたことがありました。コード ブロックの強調表示と LaTeX レンダリングについて。

Highlight は highlight.js を使用します。Marked はこのライブラリをサポートしており、直接使用することができます。言語を自動で識別できます。その関数を呼び出したくない場合は、ユーザーが使用する言語を判断することもできます。テーマを使用するには、パッケージ内のスタイルに対応する CSS を参照する必要があります。もう 1 つ重要なことは、レンダリングされたタグにクラス hljs の属性がなければならないということです。そうでない場合は、コードが強調表示されていることしかわかりません。 class 属性の追加方法については、letax 要件がない場合は、レンダリング時にタグのレイヤーを追加するだけでよく、その class 属性は次のとおりです。

残っているのは LaTeX だけです。marked 自体は LaTeX をサポートしていませんが、LaTeX のサポートを実現するために render 関数を書き換えることはサポートしています。ここでは katex を使用していますが、興味のある方は mathjax を試してみてください。ただし、数式をコード ブロックで囲む必要があるという欠点があります (例: $a * b$ 。しかし、これは大きな問題ではありません。最も重要なのは、適切にレンダリングできるかどうかです。

さて、今回のシェアはこれで終わりです。またお会いしましょう〜

Ace ベースの Markdown エディターに関するこの記事はこれで終わりです。Ace Markdown エディターの詳細については、123WORDPRESS.COM の以前の記事を検索するか、以下の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。

以下もご興味があるかもしれません:
  • Vue3 でマークダウン エディター コンポーネントを使用する方法
  • Electronを使ってMarkdownエディタを簡単に作成する方法
  • Vue を使用してマークダウン エディターのサンプル コードを実装する
  • simplemde を使用して Vue でマークダウン エディターを実装する (画像アップロード機能の追加)

<<:  CSS3 Flex エラスティックレイアウトのサンプルコードの詳細な説明

>>:  HTML iframe 使用状況の概要の収集

推薦する

MySQL 5.7 における基本的な JSON 操作ガイド

序文プロジェクトのニーズにより、ストレージ フィールドは JSON 形式で保存されます。プロジェクト...

Robots.txtの詳細な紹介

robots.txt の基本的な紹介Robots.txt はプレーンテキスト ファイルであり、Web...

GDBデバッグMySQL実戦ソースコードコンパイルとインストール

ソースコードをダウンロード git クローン https://github.com/mysql/my...

Windows で MySQL 5.6 を 5.7 にアップグレードする方法

前面に書かれたMySQL をアップグレードする方法には、インプレース アップグレードと論理アップグレ...

CentOS7でXShellとネットワーク設定を接続する方法

1. Linuxネットワーク構成ネットワークを構成する前に、まずローカル IPv4 アドレスやデフォ...

mysql 起動時の ERROR 2003 (HY000) の問題を解決する方法

1. 問題の説明MYSQL を起動すると、図に示すように、「ERROR 2003 (HY000): ...

cocoscreatorプレハブの詳しい説明

目次プレハブプレハブの作り方プレハブの役割1. 同じタイプのノードをバッチで作成する2. 特定の時間...

MySQL で主キーと ROWID を使用する際の落とし穴の概要

序文MySQL の rowid の概念については聞いたことがあるかもしれませんが、テストや実践が難し...

WeChatアプレットが検索ボックス機能を実装

この記事の例では、WeChatアプレットの検索ボックス機能を実装するための具体的なコードを参考までに...

JSが5つ星の賞賛を獲得

この記事では、5つ星の評価を獲得するためのJSの具体的なコードを参考までに共有します。具体的な内容は...

携帯電話向けウェブページ作成のヒント

現在では多くの人がスマートフォンを使用していることを考慮すると、モバイル Web ページの書き方は、...

mysql のファイル mysql-bin.000001 とは何ですか? 削除できますか?

ポートを使用して MySQL をインストールした後、しばらくすると /var の容量が不足しているこ...

JavaScriptの構文とコード構造に関する深い理解

目次概要機能性と読みやすさ空白括弧セミコロンインデント身元大文字と小文字を区別予約キーワード概要すべ...

MySQL 8.0 以降の一般的なコマンドの詳細な説明

リモートアクセスを有効にする次のコマンドを実行して、root ユーザーのリモート アクセス権を有効に...