为什么此示例电子代码无法正常工作:将markdown文件加载到编辑器中? [英] Why isn't this sample Electron code working: Loading a markdown file into an editor?

查看:73
本文介绍了为什么此示例电子代码无法正常工作:将markdown文件加载到编辑器中?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的设置




  • Win10

  • Electron 2.0.1



我正在从电子应用,第3章,示例应用在其中将Markdown文件加载到Electron编辑器中,并在HTML中以双窗格视图显示。



但是,遵循了正确的过程并在本章结尾处获得了完全相同的源代码。我什么也没看到作者试图显示的东西。



复制:


  1. 运行项目;

  2. 打开一个.md文件;

  3. 请注意,两个窗格为空白。

我对此很陌生,无法从控制台中看到任何有用的信息。因此,如果有人可以对以下简短列表进行代码审查,将不胜感激!



这里是 main.js

  
const {app,BrowserWindow,dialog} = require('electron ');
const fs = require(’fs’);

让mainWindow = null;

app.on('ready',()=> {
console.log('Hello from Electron');
mainWindow = new BrowserWindow({
show:false,//延迟显示窗口以避免初始空白
webPreferences:{
nodeIntegration:true
}
});
mainWindow.loadFile(' ./index.html'); // relpath =与main.js
mainWindow.once('ready-to-show',()=> {
mainWindow.show();
}}
mainWindow.on('closed',()=> {
mainWindow = null;
});
});

const getFileFromUser = Exports.getFileFromUser =()=> {
const files = dialog.showOpenDialog(mainWindow,{
属性:['openFile'],
过滤器:[
{名称:'文本文件',扩展名:[' txt']},
{名称:'Markdown文件',扩展名:['md','markdown']}
]
});
if(files){openFile(files [0]); }
};

const openFile =(文件)=> {
const content = fs.readFileSync(file).toString();
mainWindow.webContents.send(文件已打开,文件,内容);
}

这里是 renderer.js

  const {remote,ipcRenderer} = require('electron'); 
const mainProcess = remote.require(’./ main.js’); //插入主流程
const标记= require('标记'); //导入标记为

的// //从document(index.html)中找到并参考 #markdown
const markdownView = document.querySelector(’#markdown');
const htmlView = document.querySelector(’#html’);
const newFileButton = document.querySelector(’#new-file’);
const openFileButton = document.querySelector(’#open-file’);
const saveMarkdownButton = document.querySelector(’#save-markdown’);
const revertButton = document.querySelector(’#revert’);
const saveHtmlButton = document.querySelector(’#save-html’);
const showFileButton = document.querySelector(’#show-file’);
const openInDefaultButton = document.querySelector(’#open-in-default’);

const renderMarkdownToHtml =(markdown)=> {
htmlView.innerHTML =标记(markdown,{清除:true});
};

markdownView.addEventListener('keyup',(event)=> {
const currentContent = event.target.value;
renderMarkdownToHtml(currentContent);
} );

openFileButton.addEventListener('click',()=> {
mainProcess.getFileFromUser();
});

ipcRenderer.on('file-opened',(event,file,content)=> {
markdownView.value = content;
renderMarkdownToHtml(content);
});



UPDATE



我打开了开发者工具在应用程序窗口内,并看到此错误

  remote.js:221未捕获的错误:无法调用远程方法'getFileFromUser'。检查方法签名是否正确。潜在的错误: path参数必须是字符串,缓冲区或URL类型之一。收到的类型未定义
基础堆栈:TypeError [ERR_INVALID_ARG_TYPE]: path参数必须是字符串,Buffer或URL类型之一。在Object.openSync(fs.js:439:10)接收到类型不确定的
(在Object.func(电子/js2c/asar.js:140:31)在
的Object.func [ as openSync](electron / js2c / asar.js:140:31)
在Object.readFileSync(fs.js:349:35)
在Object.fs.readFileSync(electron / js2c / asar。 js:542:40)Object.fs.readFileSync处的
(electron / js2c / asar.js:542:40)openFile处的
(hello_electron\app\main的路径)。 js:36:24)Object.exports.getFileFromUser中的
(path\to\hello_electron\app\main.js:32:18)
在electronic / js2c / browser_init.js: 6620:63 EventEmitter的
。< anonymous> (electron / js2c / browser_init.js:6473:21)

在electron / js2c / browser_init.js:6622:17
在EventEmitter。< anonymous> (electron / js2c / browser_init.js:6473:21)
在EventEmitter.emit(events.js:203:13)
在WebContents。< anonymous> (electron / js2c / browser_init.js:3845:23)
在WebContents.emit(events.js:203:13)
路径到\hello_electron\node_modules\标记的lib \marked.js:1541marked():从版本0.7.0开始,不推荐使用sanitize和sanitizer参数,因此不应使用,以后将删除它们。在此处了解更多信息:https://marked.js.org/#/USING_ADVANCED.md#options
checkSanitizeDeprecation @ path\to\hello_electron\node_modules\marked\lib\marked.js:1541

但是看看 main.js 代码



UPDATE 2



我发现这本书样本期望与我的版本不同的返回值 showOpenDialog



我的API文档对 showOpenDialog

  / ** 
*使用包含以下内容的对象进行解析:
*
* *`canceled`布尔值-是否该对话框已取消。
* *`filePaths` String []-用户选择的文件路径数组。如果取消了
*对话框,这将是一个空数组。
* *`bookmarks` String [](可选)_macOS_ _mas_-与
* basePath编码的字符串的`filePaths`数组匹配的数组,其中包含安全范围为
*书签数据。必须启用`securityScopedBookmarks`才能填充
*。
*
*`browserWindow`参数允许对话框将自身附加到父
*窗口,使其具有模式。
*
*过滤器指定了一系列文件类型,当您要将用户限制为特定类型时,可以显示或选择这些文件类型。例如:
*
*`extensions'数组应包含没有通配符或点的扩展名(例如
*`'png'`很好,但是''.png'`和`'* .png'`不好)。要显示所有文件,请使用
*`’*’`通配符(不支持其他通配符)。
*
* **注意:**在Windows和Linux上,打开的对话框不能同时是文件选择器
*和目录选择器,因此如果将`properties`设置为`[在这些平台上的'openFile',
*'openDirectory']`,将显示目录选择器。
* /

所以我将代码切换为使用文件。 filePaths ,但出现新错误

  remote.js:221未捕获错误:无法调用远程方法 getFileFromUser。检查方法签名是否正确。底层错误:无法读取未定义
的属性'0'底层堆栈:TypeError:无法读取Object.exports.getFileFromUser(path\to\hello\app\ \main.js:37:29)
在electronic / js2c / browser_init.js:6620:63
在EventEmitter。< anonymous> (electron / js2c / browser_init.js:6473:21)
在EventEmitter.emit(events.js:203:13)
在WebContents。 (electron / js2c / browser_init.js:3845:23)
在WebContents.emit(events.js:203:13)

在electron / js2c / browser_init.js:6622:17
在EventEmitter。< anonymous> (electron / js2c / browser_init.js:6473:21)
在EventEmitter.emit(events.js:203:13)
在WebContents。< anonymous> (electron / js2c / browser_init.js:3845:23)
在WebContents.emit(events.js:203:13)


解决方案

好的,自己解决。看来这本书是根据错误/过时的语法使用了 showOpenDialog API。该API可能曾经是同步的,但后来默认情况下变为异步。我必须替换示例代码

  const getFileFromUser = Exports.getFileFromUser =()=> {
const files = dialog.showOpenDialog(mainWindow,{
属性:['openFile'],
过滤器:[
{名称:'文本文件',扩展名:[' txt']},
{名称:'Markdown文件',扩展名:['md','markdown']}
]
});
if(files){openFile(files [0]); }
};

具有异步版本



< pre class = lang-js prettyprint-override> const getFileFromUser = Exports.getFileFromUser =()=> {
dialog.showOpenDialog(mainWindow,{
属性:['openFile'],
过滤器:[
{名称:'文本文件',扩展名:['txt'] },
{名称:'Markdown Files',扩展名:['md','markdown']}
]
})。then(result => {
if (result.filePaths.length> 0){openFile(result.filePaths [0]);}
})。catch(err => {
console.log(err);
})
};

此外,返回的承诺包含的内容超出了图书样本的预期。



此修复程序完成后,我可以按预期在窗格中看到加载的Markdown文件。


My setup

  • Win10
  • Electron 2.0.1

I'm following an example from the book Electron in Action , Chapter 3, where the sample app loads a Markdown file into an Electron editor and shows it in HTML within a dual-pane view.

However, having followed the exact procedure and arrived at the exact same source code at the end of the chapter. I'm seeing nothing the author was trying to show.

Repro:

  1. Run the project;
  2. Open a .md file;
  3. Notice that the two panes are blank.

I'm pretty new to this and fail to see anything useful from the console. So if anyone could code-review the following short listings it'd be much appreciated!

Here is the main.js


const { app, BrowserWindow, dialog } = require('electron');
const fs = require('fs');

let mainWindow = null;

app.on('ready', () => {
    console.log('Hello from Electron');
    mainWindow = new BrowserWindow({
        show: false, // Delay showing window to avoid initial blank.
        webPreferences: {
            nodeIntegration: true
        }
    });
    mainWindow.loadFile('./index.html'); // relpath = same folder as main.js
    mainWindow.once('ready-to-show', () => {
        mainWindow.show();
    })
    mainWindow.on('closed', () => {
        mainWindow = null;
    });
});

const getFileFromUser = exports.getFileFromUser = () => {
    const files = dialog.showOpenDialog(mainWindow, {
        properties: ['openFile'],
        filters: [
            { name: 'Text Files', extensions: ['txt'] },
            { name: 'Markdown Files', extensions: ['md', 'markdown'] }
        ]
    });
    if (files) { openFile(files[0]); }
};

const openFile = (file) => {
    const content = fs.readFileSync(file).toString();
    mainWindow.webContents.send('file-opened', file, content);
}

Here is renderer.js

const { remote, ipcRenderer } = require('electron');
const mainProcess = remote.require('./main.js'); // plug in main process
const marked = require('marked'); // import marked as marked

// From document(index.html), find and refer to section '#markdown'
const markdownView = document.querySelector('#markdown');
const htmlView = document.querySelector('#html');
const newFileButton = document.querySelector('#new-file');
const openFileButton = document.querySelector('#open-file');
const saveMarkdownButton = document.querySelector('#save-markdown');
const revertButton = document.querySelector('#revert');
const saveHtmlButton = document.querySelector('#save-html');
const showFileButton = document.querySelector('#show-file');
const openInDefaultButton = document.querySelector('#open-in-default');

const renderMarkdownToHtml = (markdown) => {
    htmlView.innerHTML = marked(markdown, { sanitize: true });
};

markdownView.addEventListener('keyup', (event) => {
    const currentContent = event.target.value;
    renderMarkdownToHtml(currentContent);
});

openFileButton.addEventListener('click', () => {
    mainProcess.getFileFromUser();
});

ipcRenderer.on('file-opened', (event, file, content) => {
    markdownView.value = content;
    renderMarkdownToHtml(content);
});

UPDATE

I opened the Developer Tool inside the app window and saw this error

remote.js:221 Uncaught Error: Could not call remote method 'getFileFromUser'. Check that the method signature is correct. Underlying error: The "path" argument must be one of type string, Buffer, or URL. Received type undefined
Underlying stack: TypeError [ERR_INVALID_ARG_TYPE]: The "path" argument must be one of type string, Buffer, or URL. Received type undefined
    at Object.openSync (fs.js:439:10)
    at Object.func (electron/js2c/asar.js:140:31)
    at Object.func [as openSync] (electron/js2c/asar.js:140:31)
    at Object.readFileSync (fs.js:349:35)
    at Object.fs.readFileSync (electron/js2c/asar.js:542:40)
    at Object.fs.readFileSync (electron/js2c/asar.js:542:40)
    at openFile (path\to\hello_electron\app\main.js:36:24)
    at Object.exports.getFileFromUser (path\to\hello_electron\app\main.js:32:18)
    at electron/js2c/browser_init.js:6620:63
    at EventEmitter.<anonymous> (electron/js2c/browser_init.js:6473:21)

    at electron/js2c/browser_init.js:6622:17
    at EventEmitter.<anonymous> (electron/js2c/browser_init.js:6473:21)
    at EventEmitter.emit (events.js:203:13)
    at WebContents.<anonymous> (electron/js2c/browser_init.js:3845:23)
    at WebContents.emit (events.js:203:13)
path\to\hello_electron\node_modules\marked\lib\marked.js:1541 marked(): sanitize and sanitizer parameters are deprecated since version 0.7.0, should not be used and will be removed in the future. Read more here: https://marked.js.org/#/USING_ADVANCED.md#options
checkSanitizeDeprecation @ path\to\hello_electron\node_modules\marked\lib\marked.js:1541

But looking at the main.js code above, I can't find why the path is invalid.

UPDATE 2

I found that the book sample was expecting a different returned value of showOpenDialog from my version.

My API doc says about showOpenDialog

/**
     * Resolve with an object containing the following:
     *
     * * `canceled` Boolean - whether or not the dialog was canceled.
     * * `filePaths` String[] - An array of file paths chosen by the user. If the
     * dialog is cancelled this will be an empty array.
     * * `bookmarks` String[] (optional) _macOS_ _mas_ - An array matching the
     * `filePaths` array of base64 encoded strings which contains security scoped
     * bookmark data. `securityScopedBookmarks` must be enabled for this to be
     * populated.
     *
     * The `browserWindow` argument allows the dialog to attach itself to a parent
     * window, making it modal.
     *
     * The `filters` specifies an array of file types that can be displayed or selected
     * when you want to limit the user to a specific type. For example:
     *
     * The `extensions` array should contain extensions without wildcards or dots (e.g.
     * `'png'` is good but `'.png'` and `'*.png'` are bad). To show all files, use the
     * `'*'` wildcard (no other wildcard is supported).
     *
     * **Note:** On Windows and Linux an open dialog can not be both a file selector
     * and a directory selector, so if you set `properties` to `['openFile',
     * 'openDirectory']` on these platforms, a directory selector will be shown.
     */

So I switched my code to use files.filePaths, but got new errors

remote.js:221 Uncaught Error: Could not call remote method 'getFileFromUser'. Check that the method signature is correct. Underlying error: Cannot read property '0' of undefined
Underlying stack: TypeError: Cannot read property '0' of undefined
    at Object.exports.getFileFromUser (path\to\hello\app\main.js:37:29)
    at electron/js2c/browser_init.js:6620:63
    at EventEmitter.<anonymous> (electron/js2c/browser_init.js:6473:21)
    at EventEmitter.emit (events.js:203:13)
    at WebContents.<anonymous> (electron/js2c/browser_init.js:3845:23)
    at WebContents.emit (events.js:203:13)

    at electron/js2c/browser_init.js:6622:17
    at EventEmitter.<anonymous> (electron/js2c/browser_init.js:6473:21)
    at EventEmitter.emit (events.js:203:13)
    at WebContents.<anonymous> (electron/js2c/browser_init.js:3845:23)
    at WebContents.emit (events.js:203:13)

解决方案

OK, solved it myself. It seems that the book was using the showOpenDialog API according to a wrong/outdated syntax. It is likely that the API used to be synchronous, but later became async by default. I had to replace the sample code

const getFileFromUser = exports.getFileFromUser = () => {
    const files = dialog.showOpenDialog(mainWindow, {
        properties: ['openFile'],
        filters: [
            { name: 'Text Files', extensions: ['txt'] },
            { name: 'Markdown Files', extensions: ['md', 'markdown'] }
        ]
    });
    if (files) { openFile(files[0]); }
};

with an async version

const getFileFromUser = exports.getFileFromUser = () => {
    dialog.showOpenDialog(mainWindow, {
        properties: ['openFile'],
        filters: [
            { name: 'Text Files', extensions: ['txt'] },
            { name: 'Markdown Files', extensions: ['md', 'markdown'] }
        ]
    }).then(result => {
        if (result.filePaths.length > 0) { openFile(result.filePaths[0]); }
    }).catch(err => {
        console.log(err);
    })
};

Also the returned promise contains more content than the book sample expects.

After this fix, I can see the loaded Markdown file in the panes as expected.

这篇关于为什么此示例电子代码无法正常工作:将markdown文件加载到编辑器中?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆