mirror of
https://github.com/heyman/heynote.git
synced 2024-11-21 15:33:14 +01:00
Add key bindings for inserting new blocks at the end/top of the buffer, as well as before the current block (#85)
* Add functionality to insert new block after the last block - Update key bindings in `initial-content.ts` to include `Alt + Enter` for adding a new block after the last block. - Implement `getLastNoteBlock` function in `block.js` to retrieve the last block in the note. - Add `addNewBlockAfterLast` command in `commands.js` to handle the insertion of a new block after the last one. - Integrate `addNewBlockAfterLast` command into the keymap in `keymap.js`. * Add block insertion before/after current, before first and after last. Also, tests. - Added `getFirstNoteBlock` in `block.js` for accessing the first text block. - Implemented new functions in `commands.js` like `addNewBlockBeforeCurrent` and `addNewBlockBeforeFirst`. - Updated `keymap.js` with new key bindings to facilitate block creation. - Introduced `block-creation.spec.js` for testing the new block manipulation features. * Fix visual bug when inserting new block at the top * Update help text and Readme * Fix wrong cursor position after inserting new blocks at the top of the buffer, when the previous first block's delimiter is long (e.g. Markdown) * Make RegEx more generic * Fix import * Auto-generate the README.md and initial-content documentation - Add a documentation generator - Add an option to force the initial content to be erased with an env variable * Add more specific tests * Fix Mod key on Mac in test --------- Co-authored-by: Jonatan Heyman <jonatan@heyman.info>
This commit is contained in:
parent
b80230454d
commit
d0d8f872a6
10
README.md
10
README.md
@ -97,8 +97,11 @@ I can totally see the usefulness of such a feature, and it's definitely somethin
|
||||
**On Mac**
|
||||
|
||||
```
|
||||
⌥ + Shift + Enter Add new block at the start of the buffer
|
||||
⌘ + Shift + Enter Add new block at the end of the buffer
|
||||
⌥ + Enter Add new block before the current block
|
||||
⌘ + Enter Add new block below the current block
|
||||
⌘ + Shift + Enter Split the current block at cursor position
|
||||
⌘ + ⌥ + Enter Split the current block at cursor position
|
||||
⌘ + L Change block language
|
||||
⌘ + Down Goto next block
|
||||
⌘ + Up Goto previous block
|
||||
@ -110,8 +113,11 @@ I can totally see the usefulness of such a feature, and it's definitely somethin
|
||||
**On Windows and Linux**
|
||||
|
||||
```
|
||||
Alt + Shift + Enter Add new block at the start of the buffer
|
||||
Ctrl + Shift + Enter Add new block at the end of the buffer
|
||||
Alt + Enter Add new block before the current block
|
||||
Ctrl + Enter Add new block below the current block
|
||||
Ctrl + Shift + Enter Split the current block at cursor position
|
||||
Ctrl + Alt + Enter Split the current block at cursor position
|
||||
Ctrl + L Change block language
|
||||
Ctrl + Down Goto next block
|
||||
Ctrl + Up Goto previous block
|
||||
|
@ -1,4 +1,4 @@
|
||||
const os = require('os');
|
||||
import os from 'os';
|
||||
|
||||
export const isDev = !!process.env.VITE_DEV_SERVER_URL
|
||||
|
||||
|
@ -1,31 +1,13 @@
|
||||
import { isLinux, isMac, isWindows } from "./detect-platform.js"
|
||||
|
||||
const modChar = isMac ? "⌘" : "Ctrl"
|
||||
const altChar = isMac ? "⌥" : "Alt"
|
||||
|
||||
const keyHelp = [
|
||||
[`${modChar} + Enter`, "Add new block below the current block"],
|
||||
[`${modChar} + Shift + Enter`, "Split the current block at cursor position"],
|
||||
[`${modChar} + L`, "Change block language"],
|
||||
[`${modChar} + Down`, "Goto next block"],
|
||||
[`${modChar} + Up`, "Goto previous block"],
|
||||
[`${modChar} + A`, "Select all text in a note block. Press again to select the whole buffer"],
|
||||
[`${modChar} + ${altChar} + Up/Down`, "Add additional cursor above/below"],
|
||||
[`${altChar} + Shift + F`, "Format block content (works for JSON, JavaScript, HTML, CSS and Markdown)"],
|
||||
]
|
||||
if (isWindows || isLinux) {
|
||||
keyHelp.push([altChar, "Show menu"])
|
||||
}
|
||||
|
||||
const keyMaxLength = keyHelp.map(([key, help]) => key.length).reduce((a, b) => Math.max(a, b))
|
||||
const keyHelpStr = keyHelp.map(([key, help]) => `${key.padEnd(keyMaxLength)} ${help}`).join("\n")
|
||||
import os from "os";
|
||||
import { keyHelpStr } from "../shared-utils/key-helper";
|
||||
|
||||
export const eraseInitialContent = !!process.env.ERASE_INITIAL_CONTENT
|
||||
|
||||
export const initialContent = `
|
||||
∞∞∞text
|
||||
∞∞∞markdown
|
||||
Welcome to Heynote! 👋
|
||||
|
||||
${keyHelpStr}
|
||||
${keyHelpStr(os.platform())}
|
||||
∞∞∞math
|
||||
This is a Math block. Here, rows are evaluated as math expressions.
|
||||
|
||||
@ -54,13 +36,13 @@ export const initialDevContent = initialContent + `
|
||||
def my_func():
|
||||
print("hejsan")
|
||||
|
||||
|
||||
∞∞∞javascript-a
|
||||
import {basicSetup} from "codemirror"
|
||||
import {EditorView, keymap} from "@codemirror/view"
|
||||
import {javascript} from "@codemirror/lang-javascript"
|
||||
import {indentWithTab, insertTab, indentLess, indentMore} from "@codemirror/commands"
|
||||
import {nord} from "./nord.mjs"
|
||||
∞∞∞javascript-a
|
||||
|
||||
let editor = new EditorView({
|
||||
//extensions: [basicSetup, javascript()],
|
||||
extensions: [
|
||||
|
@ -1,10 +1,9 @@
|
||||
import { app, BrowserWindow, Tray, shell, ipcMain, Menu, nativeTheme, globalShortcut, nativeImage } from 'electron'
|
||||
import { release } from 'node:os'
|
||||
import { join } from 'node:path'
|
||||
import * as jetpack from "fs-jetpack";
|
||||
|
||||
import { menu, getTrayMenu } from './menu'
|
||||
import { initialContent, initialDevContent } from '../initial-content'
|
||||
import { eraseInitialContent, initialContent, initialDevContent } from '../initial-content'
|
||||
import { WINDOW_CLOSE_EVENT, SETTINGS_CHANGE_EVENT } from '../constants';
|
||||
import CONFIG from "../config"
|
||||
import { onBeforeInputEvent } from "../keymap"
|
||||
@ -139,11 +138,11 @@ async function createWindow() {
|
||||
})
|
||||
|
||||
// Make all links open with the browser, not with the application
|
||||
win.webContents.setWindowOpenHandler(({ url }) => {
|
||||
win.webContents.setWindowOpenHandler(({url}) => {
|
||||
if (url.startsWith('https:') || url.startsWith('http:')) {
|
||||
shell.openExternal(url)
|
||||
}
|
||||
return { action: 'deny' }
|
||||
return {action: 'deny'}
|
||||
})
|
||||
|
||||
fixElectronCors(win)
|
||||
@ -260,10 +259,10 @@ const buffer = new Buffer({
|
||||
})
|
||||
|
||||
ipcMain.handle('buffer-content:load', async () => {
|
||||
if (buffer.exists()) {
|
||||
if (buffer.exists() && !(eraseInitialContent && isDev)) {
|
||||
return await buffer.load()
|
||||
} else {
|
||||
return isDev? initialDevContent : initialContent
|
||||
return isDev ? initialDevContent : initialContent
|
||||
}
|
||||
});
|
||||
|
||||
@ -271,7 +270,7 @@ async function save(content) {
|
||||
return await buffer.save(content)
|
||||
}
|
||||
|
||||
ipcMain.handle('buffer-content:save', async (event, content) => {
|
||||
ipcMain.handle('buffer-content:save', async (event, content) => {
|
||||
return await save(content)
|
||||
});
|
||||
|
||||
|
25
shared-utils/key-helper.ts
Normal file
25
shared-utils/key-helper.ts
Normal file
@ -0,0 +1,25 @@
|
||||
export const keyHelpStr = (platform: string) => {
|
||||
const modChar = platform === "darwin" ? "⌘" : "Ctrl"
|
||||
const altChar = platform === "darwin" ? "⌥" : "Alt"
|
||||
|
||||
const keyHelp = [
|
||||
[`${altChar} + Shift + Enter`, "Add new block at the start of the buffer"],
|
||||
[`${modChar} + Shift + Enter`, "Add new block at the end of the buffer"],
|
||||
[`${altChar} + Enter`, "Add new block before the current block"],
|
||||
[`${modChar} + Enter`, "Add new block below the current block"],
|
||||
[`${modChar} + ${altChar} + Enter`, "Split the current block at cursor position"],
|
||||
[`${modChar} + L`, "Change block language"],
|
||||
[`${modChar} + Down`, "Goto next block"],
|
||||
[`${modChar} + Up`, "Goto previous block"],
|
||||
[`${modChar} + A`, "Select all text in a note block. Press again to select the whole buffer"],
|
||||
[`${modChar} + ${altChar} + Up/Down`, "Add additional cursor above/below"],
|
||||
[`${altChar} + Shift + F`, "Format block content (works for JSON, JavaScript, HTML, CSS and Markdown)"],
|
||||
]
|
||||
|
||||
if (platform === "win32" || platform === "linux") {
|
||||
keyHelp.push([altChar, "Show menu"])
|
||||
}
|
||||
const keyMaxLength = keyHelp.map(([key]) => key.length).reduce((a, b) => Math.max(a, b))
|
||||
|
||||
return keyHelp.map(([key, help]) => `${key.padEnd(keyMaxLength)} ${help}`).join("\n")
|
||||
}
|
@ -4,4 +4,4 @@ export const heynoteEvent = Annotation.define()
|
||||
export const LANGUAGE_CHANGE = "heynote-change"
|
||||
export const CURRENCIES_LOADED = "heynote-currencies-loaded"
|
||||
export const SET_CONTENT = "heynote-set-content"
|
||||
|
||||
export const ADD_NEW_BLOCK = "heynote-add-new-block"
|
||||
|
@ -75,6 +75,14 @@ export function getActiveNoteBlock(state) {
|
||||
return state.facet(blockState).find(block => block.range.from <= range.head && block.range.to >= range.head)
|
||||
}
|
||||
|
||||
export function getFirstNoteBlock(state) {
|
||||
return state.facet(blockState)[0]
|
||||
}
|
||||
|
||||
export function getLastNoteBlock(state) {
|
||||
return state.facet(blockState)[state.facet(blockState).length - 1]
|
||||
}
|
||||
|
||||
export function getNoteBlockFromPos(state, pos) {
|
||||
return state.facet(blockState).find(block => block.range.from <= pos && block.range.to >= pos)
|
||||
}
|
||||
@ -86,8 +94,7 @@ class NoteBlockStart extends WidgetType {
|
||||
this.isFirst = isFirst
|
||||
}
|
||||
eq(other) {
|
||||
//return other.checked == this.checked
|
||||
return true
|
||||
return this.isFirst === other.isFirst
|
||||
}
|
||||
toDOM() {
|
||||
let wrap = document.createElement("div")
|
||||
@ -249,7 +256,7 @@ const preventFirstBlockFromBeingDeleted = EditorState.changeFilter.of((tr) => {
|
||||
* Transaction filter to prevent the selection from being before the first block
|
||||
*/
|
||||
const preventSelectionBeforeFirstBlock = EditorState.transactionFilter.of((tr) => {
|
||||
if (!firstBlockDelimiterSize) {
|
||||
if (!firstBlockDelimiterSize || tr.annotations.some(a => a.type === heynoteEvent)) {
|
||||
return tr
|
||||
}
|
||||
tr?.selection?.ranges.forEach(range => {
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { EditorSelection } from "@codemirror/state"
|
||||
import { heynoteEvent, LANGUAGE_CHANGE, CURRENCIES_LOADED } from "../annotation.js";
|
||||
import { blockState, getActiveNoteBlock, getNoteBlockFromPos } from "./block"
|
||||
import { heynoteEvent, LANGUAGE_CHANGE, CURRENCIES_LOADED, ADD_NEW_BLOCK } from "../annotation.js";
|
||||
import { blockState, getActiveNoteBlock, getFirstNoteBlock, getLastNoteBlock, getNoteBlockFromPos } from "./block"
|
||||
import { moveLineDown, moveLineUp } from "./move-lines.js";
|
||||
import { selectAll } from "./select-all.js";
|
||||
|
||||
@ -28,9 +28,32 @@ export const insertNewBlockAtCursor = ({ state, dispatch }) => {
|
||||
return true;
|
||||
}
|
||||
|
||||
export const addNewBlockBeforeCurrent = ({ state, dispatch }) => {
|
||||
console.log("addNewBlockBeforeCurrent")
|
||||
if (state.readOnly)
|
||||
return false
|
||||
|
||||
const block = getActiveNoteBlock(state)
|
||||
const delimText = "\n∞∞∞text-a\n"
|
||||
|
||||
dispatch(state.update({
|
||||
changes: {
|
||||
from: block.delimiter.from,
|
||||
insert: delimText,
|
||||
},
|
||||
selection: EditorSelection.cursor(block.delimiter.from + delimText.length),
|
||||
annotations: [heynoteEvent.of(ADD_NEW_BLOCK)],
|
||||
}, {
|
||||
scrollIntoView: true,
|
||||
userEvent: "input",
|
||||
}))
|
||||
return true;
|
||||
}
|
||||
|
||||
export const addNewBlockAfterCurrent = ({ state, dispatch }) => {
|
||||
if (state.readOnly)
|
||||
return false
|
||||
|
||||
const block = getActiveNoteBlock(state)
|
||||
const delimText = "\n∞∞∞text-a\n"
|
||||
|
||||
@ -47,10 +70,50 @@ export const addNewBlockAfterCurrent = ({ state, dispatch }) => {
|
||||
return true;
|
||||
}
|
||||
|
||||
export const addNewBlockBeforeFirst = ({ state, dispatch }) => {
|
||||
if (state.readOnly)
|
||||
return false
|
||||
|
||||
const block = getFirstNoteBlock(state)
|
||||
const delimText = "\n∞∞∞text-a\n"
|
||||
|
||||
dispatch(state.update({
|
||||
changes: {
|
||||
from: block.delimiter.from,
|
||||
insert: delimText,
|
||||
},
|
||||
selection: EditorSelection.cursor(delimText.length),
|
||||
annotations: [heynoteEvent.of(ADD_NEW_BLOCK)],
|
||||
}, {
|
||||
scrollIntoView: true,
|
||||
userEvent: "input",
|
||||
}))
|
||||
return true;
|
||||
}
|
||||
|
||||
export const addNewBlockAfterLast = ({ state, dispatch }) => {
|
||||
if (state.readOnly)
|
||||
return false
|
||||
const block = getLastNoteBlock(state)
|
||||
const delimText = "\n∞∞∞text-a\n"
|
||||
|
||||
dispatch(state.update({
|
||||
changes: {
|
||||
from: block.content.to,
|
||||
insert: delimText,
|
||||
},
|
||||
selection: EditorSelection.cursor(block.content.to + delimText.length)
|
||||
}, {
|
||||
scrollIntoView: true,
|
||||
userEvent: "input",
|
||||
}))
|
||||
return true;
|
||||
}
|
||||
|
||||
export function changeLanguageTo(state, dispatch, block, language, auto) {
|
||||
if (state.readOnly)
|
||||
return false
|
||||
const delimRegex = /^\n∞∞∞[a-z]{0,16}(-a)?\n/g
|
||||
const delimRegex = /^\n∞∞∞[a-z]+?(-a)?\n/g
|
||||
if (state.doc.sliceString(block.delimiter.from, block.delimiter.to).match(delimRegex)) {
|
||||
//console.log("changing language to", language)
|
||||
dispatch(state.update({
|
||||
|
@ -139,6 +139,10 @@ export class HeynoteEditor {
|
||||
return this.view.state.facet(blockState)
|
||||
}
|
||||
|
||||
getCursorPosition() {
|
||||
return this.view.state.selection.main.head
|
||||
}
|
||||
|
||||
focus() {
|
||||
this.view.focus()
|
||||
}
|
||||
|
@ -6,7 +6,8 @@ import {
|
||||
|
||||
import {
|
||||
insertNewBlockAtCursor,
|
||||
addNewBlockAfterCurrent,
|
||||
addNewBlockBeforeCurrent, addNewBlockAfterCurrent,
|
||||
addNewBlockBeforeFirst, addNewBlockAfterLast,
|
||||
moveLineUp, moveLineDown,
|
||||
selectAll,
|
||||
gotoPreviousBlock, gotoNextBlock,
|
||||
@ -38,8 +39,11 @@ export function heynoteKeymap(editor) {
|
||||
return keymapFromSpec([
|
||||
["Tab", indentMore],
|
||||
["Shift-Tab", indentLess],
|
||||
["Alt-Shift-Enter", addNewBlockBeforeFirst],
|
||||
["Mod-Shift-Enter", addNewBlockAfterLast],
|
||||
["Alt-Enter", addNewBlockBeforeCurrent],
|
||||
["Mod-Enter", addNewBlockAfterCurrent],
|
||||
["Mod-Shift-Enter", insertNewBlockAtCursor],
|
||||
["Mod-Alt-Enter", insertNewBlockAtCursor],
|
||||
["Mod-a", selectAll],
|
||||
["Alt-ArrowUp", moveLineUp],
|
||||
["Alt-ArrowDown", moveLineDown],
|
||||
|
117
tests/block-creation.spec.js
Normal file
117
tests/block-creation.spec.js
Normal file
@ -0,0 +1,117 @@
|
||||
import {expect, test} from "@playwright/test";
|
||||
import {HeynotePage} from "./test-utils.js";
|
||||
|
||||
let heynotePage
|
||||
|
||||
test.beforeEach(async ({page}) => {
|
||||
console.log("beforeEach")
|
||||
heynotePage = new HeynotePage(page)
|
||||
await heynotePage.goto()
|
||||
|
||||
expect((await heynotePage.getBlocks()).length).toBe(1)
|
||||
heynotePage.setContent(`
|
||||
∞∞∞text
|
||||
Block A
|
||||
∞∞∞text
|
||||
Block B
|
||||
∞∞∞text
|
||||
Block C`)
|
||||
await page.waitForTimeout(100);
|
||||
// check that blocks are created
|
||||
expect((await heynotePage.getBlocks()).length).toBe(3)
|
||||
|
||||
// check that visual block layers are created
|
||||
await expect(page.locator("css=.heynote-blocks-layer > div")).toHaveCount(3)
|
||||
});
|
||||
|
||||
/* from A */
|
||||
test("create block before current (A)", async ({page}) => {
|
||||
// select the first block
|
||||
await page.locator("body").press("ArrowUp")
|
||||
await page.locator("body").press("ArrowUp")
|
||||
await runTest(page, "Alt+Enter", ['D', 'A', 'B', 'C'])
|
||||
})
|
||||
|
||||
test("create block after current (A)", async ({page}) => {
|
||||
// select the first block
|
||||
await page.locator("body").press("ArrowUp")
|
||||
await page.locator("body").press("ArrowUp")
|
||||
await runTest(page, "Mod+Enter", ['A', 'D', 'B', 'C'])
|
||||
})
|
||||
|
||||
/* from B */
|
||||
test("create block before current (B)", async ({page}) => {
|
||||
// select the second block
|
||||
await page.locator("body").press("ArrowUp")
|
||||
await runTest(page, "Alt+Enter", ['A', 'D', 'B', 'C'])
|
||||
})
|
||||
|
||||
test("create block after current (B)", async ({page}) => {
|
||||
// select the second block
|
||||
await page.locator("body").press("ArrowUp")
|
||||
await runTest(page, "Mod+Enter", ['A', 'B', 'D', 'C'])
|
||||
})
|
||||
|
||||
/* from C */
|
||||
test("create block before current (C)", async ({page}) => {
|
||||
await runTest(page, "Alt+Enter", ['A', 'B', 'D', 'C'])
|
||||
})
|
||||
|
||||
test("create block after current (C)", async ({page}) => {
|
||||
await runTest(page, "Mod+Enter", ['A', 'B', 'C', 'D'])
|
||||
})
|
||||
|
||||
test("create block before first", async ({page}) => {
|
||||
await runTest(page, "Alt+Shift+Enter", ['D', 'A', 'B', 'C'])
|
||||
})
|
||||
|
||||
test("create block after last", async ({page}) => {
|
||||
for (let i = 0; i < 3; i++) {
|
||||
await page.locator("body").press("ArrowUp")
|
||||
}
|
||||
await runTest(page, "Mod+Shift+Enter", ['A', 'B', 'C', 'D'])
|
||||
})
|
||||
|
||||
test("create block before Markdown block", async ({page}) => {
|
||||
await heynotePage.setContent(`
|
||||
∞∞∞markdown
|
||||
# Markdown!
|
||||
`)
|
||||
await page.locator("body").press("Alt+Enter")
|
||||
await page.waitForTimeout(100);
|
||||
expect(await heynotePage.getCursorPosition()).toBe(11)
|
||||
})
|
||||
|
||||
test("create block before first Markdown block", async ({page}) => {
|
||||
await heynotePage.setContent(`
|
||||
∞∞∞markdown
|
||||
# Markdown!
|
||||
∞∞∞text
|
||||
`)
|
||||
for (let i = 0; i < 5; i++) {
|
||||
await page.locator("body").press("ArrowDown")
|
||||
}
|
||||
await page.locator("body").press("Alt+Shift+Enter")
|
||||
await page.waitForTimeout(100);
|
||||
expect(await heynotePage.getCursorPosition()).toBe(11)
|
||||
})
|
||||
|
||||
const runTest = async (page, key, expectedBlocks) => {
|
||||
// create a new block
|
||||
await page.locator("body").press(key.replace("Mod", heynotePage.isMac ? "Meta" : "Control"))
|
||||
await page.waitForTimeout(100);
|
||||
await page.locator("body").pressSequentially("Block D")
|
||||
|
||||
// check that blocks are created
|
||||
expect((await heynotePage.getBlocks()).length).toBe(4)
|
||||
|
||||
// check that the content of each block is correct
|
||||
for (const expectedBlock of expectedBlocks) {
|
||||
const index = expectedBlocks.indexOf(expectedBlock);
|
||||
expect(await heynotePage.getBlockContent(index)).toBe(`Block ${expectedBlock}`)
|
||||
}
|
||||
|
||||
// check that only one block delimiter widget has the class first
|
||||
await expect(await page.locator("css=.heynote-block-start.first")).toHaveCount(1)
|
||||
}
|
||||
|
@ -35,6 +35,10 @@ export class HeynotePage {
|
||||
await this.page.evaluate((content) => window._heynote_editor.setContent(content), content)
|
||||
}
|
||||
|
||||
async getCursorPosition() {
|
||||
return await this.page.evaluate(() => window._heynote_editor.getCursorPosition())
|
||||
}
|
||||
|
||||
async getBlockContent(blockIndex) {
|
||||
const blocks = await this.getBlocks()
|
||||
const content = await this.getContent()
|
||||
|
@ -14,7 +14,7 @@
|
||||
"noEmit": true,
|
||||
"allowJs": true
|
||||
},
|
||||
"include": ["src"],
|
||||
"include": ["src"," shared-utils"],
|
||||
"references": [
|
||||
{ "path": "./tsconfig.node.json" }
|
||||
]
|
||||
|
@ -6,5 +6,5 @@
|
||||
"resolveJsonModule": true,
|
||||
"allowSyntheticDefaultImports": true
|
||||
},
|
||||
"include": ["vite.config.ts", "package.json", "electron"]
|
||||
"include": ["vite.config.ts", "package.json", "electron", "shared-utils"]
|
||||
}
|
||||
|
@ -8,11 +8,35 @@ import license from 'rollup-plugin-license'
|
||||
import pkg from './package.json'
|
||||
import path from 'path'
|
||||
|
||||
import { keyHelpStr } from "./shared-utils/key-helper";
|
||||
|
||||
rmSync('dist-electron', { recursive: true, force: true })
|
||||
|
||||
const isDevelopment = process.env.NODE_ENV === "development" || !!process.env.VSCODE_DEBUG
|
||||
const isProduction = process.env.NODE_ENV === "production"
|
||||
|
||||
const updateReadmeKeybinds = async () => {
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
const readmePath = path.resolve(__dirname, 'README.md')
|
||||
let readme = fs.readFileSync(readmePath, 'utf-8')
|
||||
const keybindsRegex = /^(### What are the default keyboard shortcuts\?\s*).*?^(```\s+#)/gms
|
||||
const shortcuts = `$1**On Mac**
|
||||
|
||||
\`\`\`
|
||||
${keyHelpStr('darwin')}
|
||||
\`\`\`
|
||||
|
||||
**On Windows and Linux**
|
||||
|
||||
\`\`\`
|
||||
${keyHelpStr('win32')}
|
||||
$2`
|
||||
|
||||
readme = readme.replace(keybindsRegex, shortcuts)
|
||||
fs.writeFileSync(readmePath, readme)
|
||||
}
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig({
|
||||
resolve: {
|
||||
@ -23,6 +47,7 @@ export default defineConfig({
|
||||
|
||||
plugins: [
|
||||
vue(),
|
||||
updateReadmeKeybinds(),
|
||||
electron([
|
||||
{
|
||||
// Main-Process entry file of the Electron App.
|
||||
|
Loading…
Reference in New Issue
Block a user