個人的なエッセイを記録するために、最近、markdown-it をベースにした
次に、この機能を実装する手順を順を追って説明します。 Vue CLIはVueプロジェクトを構築します選択したディレクトリで カスタムテンプレートを選択します(デフォルトのVue 3テンプレートを選択できます) Vue3とTypeScriptを選択し、プロジェクトに応じて他のオプションを選択します。 効果を確認するには Vue プロジェクトをマークダウンエディターに変換v-md-editorをインストールするには、 TypeScript型定義ファイルを追加する
モジュール「*.vue」を宣言します。 "vue" から DefineComponent 型をインポートします。 const コンポーネント: DefineComponent<{}, {}, any>; デフォルトコンポーネントをエクスポートします。 } <!-- 追加されたコンテンツ --> モジュール「@kangc/v-md-editor/lib/theme/vuepress.js」を宣言します。 モジュール "@kangc/v-md-editor/lib/plugins/copy-code/index" を宣言します。 モジュール「@kangc/v-md-editor/lib/plugins/line-number/index」を宣言します。 モジュール "@kangc/v-md-editor" を宣言します。 モジュール「prismjs」を宣言します。 App.vueの変換 <テンプレート> <div> <v-md-editor v-model="content" height="100vh"></v-md-editor> </div> </テンプレート> <script lang="ts"> // エディター import VMdEditor from "@kangc/v-md-editor"; "@kangc/v-md-editor/lib/style/base-editor.css" をインポートします。 「@kangc/v-md-editor/lib/theme/vuepress.js」からvuepressをインポートします。 "@kangc/v-md-editor/lib/theme/style/vuepress.css" をインポートします。 // ハイライト import Prism from "prismjs"; 「prismjs/components/prism-json」をインポートします。 「prismjs/components/prism-dart」をインポートします。 「prismjs/components/prism-c」をインポートします。 「prismjs/components/prism-swift」をインポートします。 「prismjs/components/prism-kotlin」をインポートします。 「prismjs/components/prism-java」をインポートします。 // コードをすばやくコピーします import createCopyCodePlugin from "@kangc/v-md-editor/lib/plugins/copy-code/index"; "@kangc/v-md-editor/lib/plugins/copy-code/copy-code.css" をインポートします。 // 行番号 import createLineNumbertPlugin from "@kangc/v-md-editor/lib/plugins/line-number/index"; VMdEditor.use(vuepress, { プリズム、 }) .use(コピーコードプラグインの作成()) .use(createLineNumbertPlugin()); 「vue」からdefineComponent、refをインポートします。 エクスポートデフォルトdefineComponent({ 名前:「アプリ」、 コンポーネント: { VMdEditor }, 設定() { 定数コンテンツ = ref(""); {コンテンツ}を返します。 }, }); </スクリプト> <スタイル> /* いくつかのボタンを削除します */ .v-md-icon-save、 .v-md-アイコン-フルスクリーン { 表示: なし; } </スタイル>
効果は以下のとおりです Vue CLI プラグイン Electron ビルダーVite 2.0 を使用してElectronプロジェクトを構築しようとしましたが、 ViteとElectronをうまく組み合わせた同様のツールが見つからなかったため、 Vite 2.0の誘惑をあきらめました。何かおすすめがあれば、ぜひ共有してください。 インストールには
効果を確認するには
最適化全画面表示を開始紹介画面 「electron」から { screen } をインポートします。 ウィンドウを作成するときに画面サイズを設定する <!-- 背景.ts --> 非同期関数createWindow() { const { 幅、高さ } = screen.getPrimaryDisplay().workAreaSize; const win = 新しいブラウザウィンドウ({ 幅、 身長、 // 省略... }); // 省略... }
メニューバーを変更するメニューバーを定義する <!-- 背景.ts --> const テンプレート: Array<MenuItemConstructorOptions> = [ { ラベル: "MarkDown", サブメニュー: [ { ラベル: "About", アクセラレータ: "CmdOrCtrl+W", 役割: "について", }, { ラベル: "プログラムを終了", アクセラレータ: "CmdOrCtrl+Q", 役割: 「終了」、 }, ]、 }, { ラベル: "ファイル", サブメニュー: [ { ラベル: "ファイルを開く", アクセラレータ: "CmdOrCtrl+O", クリック: ( 項目: メニュー項目、 focusedWindow: BrowserWindow | 未定義、 _event: キーボードイベント ) => { // TODO: ファイルを開く}, }, { ラベル: 「ストレージ」、 アクセラレータ: "CmdOrCtrl+S", クリック: ( 項目: メニュー項目、 focusedWindow: BrowserWindow | 未定義、 _event: キーボードイベント ) => { //TODO: コンテンツを保存する}, }, ]、 }, { ラベル: "編集", サブメニュー: [ { ラベル: 「取り消し」、 アクセラレータ: "CmdOrCtrl+Z", 役割: 「元に戻す」、 }, { ラベル: 「やり直し」、 アクセラレータ: "Shift+CmdOrCtrl+Z", 役割: 「やり直し」、 }, { タイプ:「セパレータ」、 }, { ラベル: 「カット」、 アクセラレータ: "CmdOrCtrl+X", 役割: 「カット」、 }, { ラベル: "コピー", アクセラレータ: "CmdOrCtrl+C", 役割: "コピー"、 }, { ラベル:「貼り付け」、 アクセラレータ: "CmdOrCtrl+V", 役割: 「貼り付け」、 }, ]、 }, { ラベル: "ウィンドウ", 役割: "ウィンドウ"、 サブメニュー: [ { ラベル: 「最小化」、 アクセラレータ: "CmdOrCtrl+M", 役割: 「最小化」、 }, { ラベル:「最大化」、 アクセラレータ: "CmdOrCtrl+M", クリック: ( 項目: メニュー項目、 focusedWindow: BrowserWindow | 未定義、 _event: キーボードイベント ) => { if (focusedWindow) { フォーカスウィンドウを最大化します。 } }, }, { タイプ:「セパレータ」、 }, { ラベル: 「全画面に切り替える」、 アクセラレータ: (function () { プロセスプラットフォームが「ダーウィン」の場合 「Ctrl+Command+F」を返します。 } それ以外 { 「F11」を返します。 } })(), クリック: ( 項目: メニュー項目、 focusedWindow: BrowserWindow | 未定義、 // eslint 次の行を無効にする @typescript-eslint/未使用変数なし _event: キーボードイベント ) => { if (focusedWindow) { focusWindow.setFullScreen(!focusedWindow.isFullScreen()); } }, }, ]、 }, { ラベル: "ヘルプ", 役割: "ヘルプ"、 サブメニュー: [ { ラベル: "詳細を見る", クリック: 関数 () { シェルを外部から開きます("http://electron.atom.io"); }, }, ]、 }, ];
メニューバーを設定する "electron"から{Menu}をインポートします。 app.on("準備完了", 非同期() => { // 省略... // メニューを作成しますMenu.setApplicationMenu(Menu.buildFromTemplate(template)); });
効果 エディターはmarkdonwファイルの内容を開きますメインスレッドはファイルを選択し、ファイルパスをレンダリングスレッドに渡します。 <!-- 背景.ts --> ダイアログ .showOpenDialog({ プロパティ: ["openFile"], フィルター: [{ name: "カスタムファイルタイプ", 拡張子: ["md"] }], }) .then((res) => { res && res["filePaths"].length > 0 の場合 { const filePath = res["filePaths"][0]; // ファイルをレンダリングスレッドに渡す if (focusedWindow) { focusedWindow.webContents.send("open-file-path", filePath); } } }) .catch((エラー) => { コンソールログ(エラー); });
レンダリングスレッドはファイルパスを取得し、ファイルの内容を読み取り、それをマークダウンエディタに割り当てます。 <!-- App.vue --> 「electron」から { ipcRenderer } をインポートします。 「fs」から{readFileSync}をインポートします。 エクスポートデフォルトdefineComponent({ // 省略... 設定() { 定数コンテンツ = ref(""); マウント時(() => { // 1. ipcRenderer.on("open-file-path", (e, filePath: 文字列) => { ファイルパス && ファイルパス.長さ > 0 の場合 { // 2. content.value = readFileSync(filePath).toString(); } }); }); {コンテンツ}を返します。 }, }); Vue がノードサポートを追加 <!-- vue.config.js --> モジュール.エクスポート = { プラグインオプション: { 電子ビルダー: { ノード統合: true、 }, }, }; 効果 markdonwの内容をファイルに保存するメインスレッドはレンダリングスレッドにエディタコンテンツを取得する要求を開始します。 <!-- background.js --> if (focusedWindow) { focusedWindow.webContents.send("get-content", ""); } レンダリングスレッドはエディターのコンテンツをメインスレッドに返します。 <!-- App.vue --> マウント時(() => { ipcRenderer.on("コンテンツを取得", () => { ipcRenderer.send("save-content", content.value); }); }); メインスレッドはコンテンツを受け取り、ファイルに保存します <!-- 背景.ts --> // ファイルを保存 ipcMain.on("save-content", (event: unknown, content: string) => { 開いたファイルの長さが0より大きい場合 // ファイルに直接保存する try { 開いたファイルの内容を書き込む。 console.log("正常に保存しました"); } キャッチ(エラー){ console.log("保存に失敗しました"); } } それ以外 { 定数オプション = { タイトル:「ファイルを保存」、 デフォルトパス: "new.md", フィルター: [{ name: "カスタムファイルタイプ", 拡張子: ["md"] }], }; 定数 focusWindow = BrowserWindow.getFocusedWindow(); if (focusedWindow) { ダイアログ .showSaveDialog(フォーカスされたウィンドウ、オプション) .then((結果: Electron.SaveDialogReturnValue) => { if (結果.ファイルパス) { 試す { writeFileSync(結果.filePath、コンテンツ); console.log("正常に保存されました"); 開いたファイル = result.filePath; } キャッチ(エラー){ console.log("保存に失敗しました"); } } }) .catch((エラー) => { コンソール.log(エラー); }); } } }); 効果 パックアプリケーションの名前と画像を設定する <!-- vue.config.js --> モジュール.エクスポート = { プラグインオプション: { 電子ビルダー: { ノード統合: true、 // 追加された設定 builderOptions: { アプリID: "com.johnny.markdown", productName: "JJMarkDown", // アプリケーション名 copyright: "Copyright © 2021", // 著作権声明 mac: { アイコン: "./public/icon.icns", // アイコン }, }, }, }, }; icon.icns 生成用の 1024*1024 の画像を準備し、同じディレクトリに さまざまなサイズの画像ファイルを作成する sips -z 16 16 icon.png -o icons.iconset/icon_16x16.png sips -z 32 32 icon.png -o icons.iconset/[email protected] sips -z 32 32 icon.png -o icons.iconset/icon_32x32.png sips -z 64 64 icon.png -o icons.iconset/[email protected] sips -z 128 128 icon.png -o icons.iconset/icon_128x128.png sips -z 256 256 icon.png -o icons.iconset/[email protected] sips -z 256 256 icon.png -o icons.iconset/icon_256x256.png sips -z 512 512 icon.png -o icons.iconset/[email protected] sips -z 512 512 icon.png -o icons.iconset/icon_512x512.png sips -z 1024 1024 icon.png -o icons.iconset/[email protected] icon.icnsという名前のアイコンファイルを取得します。 アイコンユーティリティ -c icns icons.iconset -o icon.icns パック npm 実行 electron:build 結果 取得した dmg ファイルは直接インストールして使用できます。 コード <!-- 背景.ts --> 「厳密な使用」; 輸入 { アプリ、 プロトコル、 ブラウザウィンドウ、 画面、 メニュー、 メニュー項目、 シェル、 ダイアログ、 ipcメイン、 } から "electron" へ; 「electron/main」から KeyboardEvent と MenuItemConstructorOptions をインポートします。 「vue-cli-plugin-electron-builder/lib」から createProtocol をインポートします。 「electron-devtools-installer」から installExtension、{ VUEJS3_DEVTOOLS } をインポートします。 const isDevelopment = process.env.NODE_ENV !== "production"; 「fs」から writeFileSync をインポートします。 開いたファイル = ""; // ファイルを保存 ipcMain.on("save-content", (event: unknown, content: string) => { 開いたファイルの長さが0より大きい場合 // ファイルに直接保存する try { 開いたファイルの内容を書き込む。 console.log("正常に保存しました"); } キャッチ(エラー){ console.log("保存に失敗しました"); } } それ以外 { 定数オプション = { タイトル:「ファイルを保存」、 デフォルトパス: "new.md", フィルター: [{ name: "カスタムファイルタイプ", 拡張子: ["md"] }], }; 定数 focusWindow = BrowserWindow.getFocusedWindow(); if (focusedWindow) { ダイアログ .showSaveDialog(フォーカスされたウィンドウ、オプション) .then((結果: Electron.SaveDialogReturnValue) => { if (結果.ファイルパス) { 試す { writeFileSync(結果.filePath、コンテンツ); console.log("正常に保存しました"); 開いたファイル = result.filePath; } キャッチ(エラー){ console.log("保存に失敗しました"); } } }) .catch((エラー) => { コンソール.log(エラー); }); } } }); const テンプレート: Array<MenuItemConstructorOptions> = [ { ラベル: "MarkDown", サブメニュー: [ { ラベル: "About", アクセラレータ: "CmdOrCtrl+W", 役割: "について", }, { ラベル: "プログラムを終了", アクセラレータ: "CmdOrCtrl+Q", 役割: 「終了」、 }, ]、 }, { ラベル: "ファイル", サブメニュー: [ { ラベル: "ファイルを開く", アクセラレータ: "CmdOrCtrl+O", クリック: ( 項目: メニュー項目、 focusedWindow: BrowserWindow | 未定義、 // eslint 次の行を無効にする @typescript-eslint/未使用変数なし _event: キーボードイベント ) => { ダイアログ .showOpenDialog({ プロパティ: ["openFile"], フィルター: [{ name: "カスタムファイルタイプ", 拡張子: ["md"] }], }) .then((res) => { res && res["filePaths"].length > 0 の場合 { 定数ファイルパス = res["ファイルパス"][0]; // レンダリングスレッドにファイルを渡す if (focusedWindow) { focusedWindow.webContents.send("open-file-path", filePath); 開かれたファイル = ファイルパス; } } }) .catch((エラー) => { コンソールログ(エラー); }); }, }, { ラベル: 「ストレージ」、 アクセラレータ: "CmdOrCtrl+S", クリック: ( 項目: メニュー項目、 focusedWindow: BrowserWindow | 未定義、 // eslint 次の行を無効にする @typescript-eslint/未使用変数なし _event: キーボードイベント ) => { if (focusedWindow) { focusedWindow.webContents.send("get-content", ""); } }, }, ]、 }, { ラベル: "編集", サブメニュー: [ { ラベル: 「取り消し」、 アクセラレータ: "CmdOrCtrl+Z", 役割: 「元に戻す」、 }, { ラベル: 「やり直し」、 アクセラレータ: "Shift+CmdOrCtrl+Z", 役割: 「やり直し」、 }, { タイプ:「セパレータ」、 }, { ラベル: 「カット」、 アクセラレータ: "CmdOrCtrl+X", 役割: 「カット」、 }, { ラベル: "コピー", アクセラレータ: "CmdOrCtrl+C", 役割: "コピー"、 }, { ラベル:「貼り付け」、 アクセラレータ: "CmdOrCtrl+V", 役割: 「貼り付け」、 }, ]、 }, { ラベル: "ウィンドウ", 役割: "ウィンドウ"、 サブメニュー: [ { ラベル: 「最小化」、 アクセラレータ: "CmdOrCtrl+M", 役割: 「最小化」、 }, { ラベル: "最大化", アクセラレータ: "CmdOrCtrl+M", クリック: ( 項目: メニュー項目、 focusedWindow: BrowserWindow | 未定義、 // eslint 次の行を無効にする @typescript-eslint/未使用変数なし _event: キーボードイベント ) => { if (focusedWindow) { フォーカスウィンドウを最大化します。 } }, }, { タイプ:「セパレータ」、 }, { ラベル: 「全画面に切り替える」、 アクセラレータ: (function () { プロセスプラットフォームが「ダーウィン」の場合 「Ctrl+Command+F」を返します。 } それ以外 { 「F11」を返します。 } })(), クリック: ( 項目: メニュー項目、 focusedWindow: BrowserWindow | 未定義、 // eslint 次の行を無効にする @typescript-eslint/未使用変数なし _event: キーボードイベント ) => { if (focusedWindow) { focusWindow.setFullScreen(!focusedWindow.isFullScreen()); } }, }, ]、 }, { ラベル: "ヘルプ", 役割: "ヘルプ"、 サブメニュー: [ { ラベル: "詳細を見る", クリック: 関数 () { シェルを外部から開きます("http://electron.atom.io"); }, }, ]、 }, ]; プロトコル.registerSchemesAsPrivileged([ { スキーム: "app"、権限: { secure: true、 standard: true } }、 ]); 非同期関数createWindow() { const { 幅、高さ } = screen.getPrimaryDisplay().workAreaSize; const win = 新しいブラウザウィンドウ({ 幅、 身長、 ウェブ設定: { ノード統合: true、 コンテキスト分離: false、 }, }); プロセス環境のWEBPACK_DEV_SERVER_URLの場合{ // 開発モードの場合は開発サーバーの URL をロードします win.loadURL(process.env.WEBPACK_DEV_SERVER_URL を文字列として) を待機します。 プロセス環境がIS_TESTの場合、win.webContents.openDevTools(); } それ以外 { プロトコルを作成します("アプリ"); // 開発中でないときにindex.htmlをロードする win.loadURL("app://./index.html"); } } // すべてのウィンドウが閉じられたら終了します。 app.on("ウィンドウがすべて閉じました", () => { // macOSではアプリケーションとそのメニューバーでよく使われる // ユーザーがCmd + Qで明示的に終了するまでアクティブのままにします プロセスプラットフォームが "darwin" の場合 アプリを終了します。 } }); app.on("アクティブ化", () => { // macOSでは、アプリが終了してもウィンドウを再作成するのが一般的です。 // ドックアイコンがクリックされ、他のウィンドウは開いていません。 BrowserWindow.getAllWindows().length === 0 の場合、createWindow(); }); // このメソッドはElectronが終了したときに呼び出されます // 初期化が完了し、ブラウザ ウィンドウを作成する準備が整いました。 // 一部の API はこのイベントが発生した後にのみ使用できます。 app.on("準備完了", 非同期() => { if (isDevelopment && !process.env.IS_TEST) { // Vue Devtools をインストール 試す { VUEJS3_DEVTOOLS のインストールを待機します。 } キャッチ (e) { console.error("Vue Devtools のインストールに失敗しました:", e.toString()); } } ウィンドウを作成します。 // メニューを作成しますMenu.setApplicationMenu(Menu.buildFromTemplate(template)); }); // 開発モードで親プロセスからの要求に応じて正常に終了します。 if (isDevelopment) { プロセスプラットフォームが "win32" の場合 process.on("メッセージ", (データ) => { if (data === "graceful-exit") { アプリを終了します。 } }); } それ以外 { プロセス.on("SIGTERM", () => { アプリを終了します。 }); } } デスクトップアプリケーションを実装するための Vue3 と Electron の詳細な説明については、この記事で終わります。Vue3 Electron デスクトップアプリケーションの関連コンテンツについては、123WORDPRESS.COM の以前の記事を検索するか、次の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。 以下もご興味があるかもしれません:
|
<<: MySQLのページング制限のパフォーマンス問題についての簡単な説明
質問:オリジン サーバーはターゲット リソースの表現を見つけることができないか、既存の表現を公開した...
MySQL には、10 進数などの標準データ型だけでなく、float や double などの非標...
オリンピック期間中にIE8ベータ2がリリースされ、英語版のリリースに合わせて中国語版も第一波でリリー...
#docker ps チェック、すべてのポートがマップされています コンテナID イメージ コマンド...
目次序文グローバルパラメータの永続性最後に要約する参考資料:序文2018 年に MySQL 8.0....
Linux LVM論理ボリューム構成プロセスの詳細な説明多くの Linux ユーザーは、オペレーティ...
目次1. データベースの使用を選択2. 情報を表示する3. テーブルを作成する4. データを挿入する...
MySQLグループソートで上位Nを見つけるテーブル構造grp でグループ化し、num で並べ替えて、...
システム トレイ アイコンは、今日でも魔法のような機能です。アイコンを右クリックして目的のアクション...
1.ファビコン.cc ico アイコンの Web サイトをオンラインで作成するには、画像をアップロー...
目次1. はじめに2. MySQLルーターを構成する2.1 MySQLルーターのインストール2.2 ...
一つの環境Alibaba Cloud Server: CentOS 7.4 64 ビット (RedH...
目次スロークエリログとは何ですか?スロークエリを有効にする方法ログ分析ツール mysqldumpsh...
1. 要件:データベースのバックアップは、実稼働環境にとって特に重要です。データベースのバックアップ...
コードをコピーコードは次のとおりです。 <HTML> <ヘッド> <T...